Source Code Cross Referenced for SVNUpdateClient.java in  » Source-Control » tmatesoft-SVN » org » tmatesoft » svn » core » wc » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Source Control » tmatesoft SVN » org.tmatesoft.svn.core.wc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * ====================================================================
0003:         * Copyright (c) 2004-2008 TMate Software Ltd.  All rights reserved.
0004:         *
0005:         * This software is licensed as described in the file COPYING, which
0006:         * you should have received as part of this distribution.  The terms
0007:         * are also available at http://svnkit.com/license.html
0008:         * If newer versions of this license are posted there, you may use a
0009:         * newer version instead, at your option.
0010:         * ====================================================================
0011:         */
0012:        package org.tmatesoft.svn.core.wc;
0013:
0014:        import java.io.File;
0015:        import java.io.OutputStream;
0016:        import java.util.HashMap;
0017:        import java.util.Iterator;
0018:        import java.util.Map;
0019:        import java.util.StringTokenizer;
0020:
0021:        import org.tmatesoft.svn.core.SVNCancelException;
0022:        import org.tmatesoft.svn.core.SVNErrorCode;
0023:        import org.tmatesoft.svn.core.SVNErrorMessage;
0024:        import org.tmatesoft.svn.core.SVNException;
0025:        import org.tmatesoft.svn.core.SVNNodeKind;
0026:        import org.tmatesoft.svn.core.SVNProperty;
0027:        import org.tmatesoft.svn.core.SVNURL;
0028:        import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
0029:        import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
0030:        import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
0031:        import org.tmatesoft.svn.core.internal.util.SVNTimeUtil;
0032:        import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor;
0033:        import org.tmatesoft.svn.core.internal.wc.SVNCancellableOutputStream;
0034:        import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
0035:        import org.tmatesoft.svn.core.internal.wc.SVNEventFactory;
0036:        import org.tmatesoft.svn.core.internal.wc.SVNExportEditor;
0037:        import org.tmatesoft.svn.core.internal.wc.SVNExternalInfo;
0038:        import org.tmatesoft.svn.core.internal.wc.SVNFileType;
0039:        import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
0040:        import org.tmatesoft.svn.core.internal.wc.SVNPropertiesManager;
0041:        import org.tmatesoft.svn.core.internal.wc.SVNUpdateEditor;
0042:        import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea;
0043:        import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
0044:        import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo;
0045:        import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
0046:        import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter;
0047:        import org.tmatesoft.svn.core.internal.wc.admin.SVNTranslator;
0048:        import org.tmatesoft.svn.core.internal.wc.admin.SVNVersionedProperties;
0049:        import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
0050:        import org.tmatesoft.svn.core.io.ISVNReporter;
0051:        import org.tmatesoft.svn.core.io.ISVNReporterBaton;
0052:        import org.tmatesoft.svn.core.io.SVNRepository;
0053:
0054:        /**
0055:         * This class provides methods which allow to check out, update, switch and relocate a
0056:         * Working Copy as well as export an unversioned directory or file from a repository.
0057:         * 
0058:         * <p>
0059:         * Here's a list of the <b>SVNUpdateClient</b>'s methods 
0060:         * matched against corresponing commands of the SVN command line 
0061:         * client:
0062:         * 
0063:         * <table cellpadding="3" cellspacing="1" border="0" width="40%" bgcolor="#999933">
0064:         * <tr bgcolor="#ADB8D9" align="left">
0065:         * <td><b>SVNKit</b></td>
0066:         * <td><b>Subversion</b></td>
0067:         * </tr>   
0068:         * <tr bgcolor="#EAEAEA" align="left">
0069:         * <td>doCheckout()</td><td>'svn checkout'</td>
0070:         * </tr>
0071:         * <tr bgcolor="#EAEAEA" align="left">
0072:         * <td>doUpdate()</td><td>'svn update'</td>
0073:         * </tr>
0074:         * <tr bgcolor="#EAEAEA" align="left">
0075:         * <td>doSwitch()</td><td>'svn switch'</td>
0076:         * </tr>
0077:         * <tr bgcolor="#EAEAEA" align="left">
0078:         * <td>doRelocate()</td><td>'svn switch --relocate oldURL newURL'</td>
0079:         * </tr>
0080:         * <tr bgcolor="#EAEAEA" align="left">
0081:         * <td>doExport()</td><td>'svn export'</td>
0082:         * </tr>
0083:         * </table>
0084:         * 
0085:         * @version 1.1.1
0086:         * @author  TMate Software Ltd.
0087:         * @see     <a target="_top" href="http://svnkit.com/kb/examples/">Examples</a>
0088:         */
0089:        public class SVNUpdateClient extends SVNBasicClient {
0090:
0091:            /**
0092:             * Constructs and initializes an <b>SVNUpdateClient</b> object
0093:             * with the specified run-time configuration and authentication 
0094:             * drivers.
0095:             * 
0096:             * <p>
0097:             * If <code>options</code> is <span class="javakeyword">null</span>,
0098:             * then this <b>SVNUpdateClient</b> will be using a default run-time
0099:             * configuration driver  which takes client-side settings from the 
0100:             * default SVN's run-time configuration area but is not able to
0101:             * change those settings (read more on {@link ISVNOptions} and {@link SVNWCUtil}).  
0102:             * 
0103:             * <p>
0104:             * If <code>authManager</code> is <span class="javakeyword">null</span>,
0105:             * then this <b>SVNUpdateClient</b> will be using a default authentication
0106:             * and network layers driver (see {@link SVNWCUtil#createDefaultAuthenticationManager()})
0107:             * which uses server-side settings and auth storage from the 
0108:             * default SVN's run-time configuration area (or system properties
0109:             * if that area is not found).
0110:             * 
0111:             * @param authManager an authentication and network layers driver
0112:             * @param options     a run-time configuration options driver     
0113:             */
0114:            public SVNUpdateClient(ISVNAuthenticationManager authManager,
0115:                    ISVNOptions options) {
0116:                super (authManager, options);
0117:            }
0118:
0119:            public SVNUpdateClient(ISVNRepositoryPool repositoryPool,
0120:                    ISVNOptions options) {
0121:                super (repositoryPool, options);
0122:            }
0123:
0124:            /**
0125:             * Brings the Working Copy item up-to-date with repository changes at the specified
0126:             * revision.
0127:             * 
0128:             * <p>
0129:             * As a revision <b>SVNRevision</b>'s pre-defined constant fields can be used. For example,
0130:             * to update the Working Copy to the latest revision of the repository use 
0131:             * {@link SVNRevision#HEAD HEAD}.
0132:             * 
0133:             * @param  file			the Working copy item to be updated
0134:             * @param  revision		the desired revision against which the item will be updated 
0135:             * @param  recursive	if <span class="javakeyword">true</span> and <code>file</code> is
0136:             * 						a directory then the entire tree will be updated, otherwise if 
0137:             * 						<span class="javakeyword">false</span> - only items located immediately
0138:             * 						in the directory itself
0139:             * @return				the revision number to which <code>file</code> was updated to
0140:             * @throws SVNException 
0141:             */
0142:            public long doUpdate(File file, SVNRevision revision,
0143:                    boolean recursive) throws SVNException {
0144:                file = new File(SVNPathUtil.validateFilePath(file
0145:                        .getAbsolutePath()));
0146:                SVNWCAccess wcAccess = createWCAccess();
0147:                SVNAdminAreaInfo adminInfo = null;
0148:                try {
0149:                    adminInfo = wcAccess.openAnchor(file, true,
0150:                            recursive ? SVNWCAccess.INFINITE_DEPTH : 0);
0151:                    SVNAdminArea anchorArea = adminInfo.getAnchor();
0152:                    final SVNReporter reporter = new SVNReporter(adminInfo,
0153:                            file, true, recursive, getDebugLog());
0154:
0155:                    SVNEntry entry = anchorArea.getEntry(anchorArea
0156:                            .getThisDirName(), false);
0157:                    SVNURL url = entry.getSVNURL();
0158:                    if (url == null) {
0159:                        SVNErrorMessage err = SVNErrorMessage.create(
0160:                                SVNErrorCode.ENTRY_MISSING_URL,
0161:                                "Entry ''{0}'' has no URL", anchorArea
0162:                                        .getRoot());
0163:                        SVNErrorManager.error(err);
0164:                    }
0165:                    SVNUpdateEditor editor = new SVNUpdateEditor(adminInfo,
0166:                            null, recursive, isLeaveConflictsUnresolved());
0167:                    SVNRepository repos = createRepository(url, true);
0168:
0169:                    String target = "".equals(adminInfo.getTargetName()) ? null
0170:                            : adminInfo.getTargetName();
0171:                    long revNumber = getRevisionNumber(revision, repos, file);
0172:                    SVNURL reposRoot = repos.getRepositoryRoot(true);
0173:                    wcAccess.setRepositoryRoot(file, reposRoot);
0174:                    repos.update(revNumber, target, recursive, reporter,
0175:                            SVNCancellableEditor.newInstance(editor, this ,
0176:                                    getDebugLog()));
0177:
0178:                    if (editor.getTargetRevision() >= 0) {
0179:                        if (recursive && !isIgnoreExternals()) {
0180:                            handleExternals(adminInfo);
0181:                        }
0182:                        dispatchEvent(SVNEventFactory
0183:                                .createUpdateCompletedEvent(adminInfo, editor
0184:                                        .getTargetRevision()));
0185:                    }
0186:                    return editor.getTargetRevision();
0187:                } finally {
0188:                    wcAccess.close();
0189:                    sleepForTimeStamp();
0190:                }
0191:            }
0192:
0193:            /**
0194:             * Updates the Working Copy item to mirror a new URL. 
0195:             * 
0196:             * <p>
0197:             * As a revision <b>SVNRevision</b>'s pre-defined constant fields can be used. For example,
0198:             * to update the Working Copy to the latest revision of the repository use 
0199:             * {@link SVNRevision#HEAD HEAD}.
0200:             * 
0201:             * <p>
0202:             * Calling this method is equivalent to 
0203:             * <code>doSwitch(file, url, SVNRevision.UNDEFINED, revision, recursive)</code>.
0204:             * 
0205:             * @param  file			the Working copy item to be switched
0206:             * @param  url			the repository location as a target against which the item will 
0207:             * 						be switched
0208:             * @param  revision		the desired revision of the repository target   
0209:             * @param  recursive	if <span class="javakeyword">true</span> and <code>file</code> is
0210:             * 						a directory then the entire tree will be updated, otherwise if 
0211:             * 						<span class="javakeyword">false</span> - only items located immediately
0212:             * 						in the directory itself
0213:             * @return				the revision number to which <code>file</code> was updated to
0214:             * @throws SVNException 
0215:             */
0216:            public long doSwitch(File file, SVNURL url, SVNRevision revision,
0217:                    boolean recursive) throws SVNException {
0218:                return doSwitch(file, url, SVNRevision.UNDEFINED, revision,
0219:                        recursive);
0220:            }
0221:
0222:            /**
0223:             * Updates the Working Copy item to mirror a new URL. 
0224:             * 
0225:             * <p>
0226:             * As a revision <b>SVNRevision</b>'s pre-defined constant fields can be used. For example,
0227:             * to update the Working Copy to the latest revision of the repository use 
0228:             * {@link SVNRevision#HEAD HEAD}.
0229:             * 
0230:             * @param  file         the Working copy item to be switched
0231:             * @param  url          the repository location as a target against which the item will 
0232:             *                      be switched
0233:             * @param  pegRevision  a revision in which <code>file</code> is first looked up
0234:             *                      in the repository
0235:             * @param  revision     the desired revision of the repository target   
0236:             * @param  recursive    if <span class="javakeyword">true</span> and <code>file</code> is
0237:             *                      a directory then the entire tree will be updated, otherwise if 
0238:             *                      <span class="javakeyword">false</span> - only items located immediately
0239:             *                      in the directory itself
0240:             * @return              the revision number to which <code>file</code> was updated to
0241:             * @throws SVNException
0242:             */
0243:            public long doSwitch(File file, SVNURL url,
0244:                    SVNRevision pegRevision, SVNRevision revision,
0245:                    boolean recursive) throws SVNException {
0246:                SVNWCAccess wcAccess = createWCAccess();
0247:                try {
0248:                    SVNAdminAreaInfo info = wcAccess.openAnchor(file, true,
0249:                            SVNWCAccess.INFINITE_DEPTH);
0250:                    final SVNReporter reporter = new SVNReporter(info, file,
0251:                            true, recursive, getDebugLog());
0252:                    SVNAdminArea anchorArea = info.getAnchor();
0253:                    SVNEntry entry = anchorArea.getEntry(anchorArea
0254:                            .getThisDirName(), false);
0255:                    if (entry == null) {
0256:                        SVNErrorMessage err = SVNErrorMessage.create(
0257:                                SVNErrorCode.UNVERSIONED_RESOURCE,
0258:                                "''{0}'' is not under version control",
0259:                                anchorArea.getRoot());
0260:                        SVNErrorManager.error(err);
0261:                    }
0262:                    SVNURL sourceURL = entry.getSVNURL();
0263:                    if (sourceURL == null) {
0264:                        SVNErrorMessage err = SVNErrorMessage.create(
0265:                                SVNErrorCode.ENTRY_MISSING_URL,
0266:                                "Directory ''{0}'' has no URL", anchorArea
0267:                                        .getRoot());
0268:                        SVNErrorManager.error(err);
0269:                    }
0270:                    SVNRepository repository = createRepository(sourceURL, true);
0271:                    long revNumber = getRevisionNumber(revision, repository,
0272:                            file);
0273:                    if (pegRevision != null && pegRevision.isValid()) {
0274:                        SVNRepositoryLocation[] locs = getLocations(url, null,
0275:                                null, pegRevision, SVNRevision
0276:                                        .create(revNumber),
0277:                                SVNRevision.UNDEFINED);
0278:                        url = locs[0].getURL();
0279:                    }
0280:
0281:                    SVNUpdateEditor editor = new SVNUpdateEditor(info, url
0282:                            .toString(), recursive,
0283:                            isLeaveConflictsUnresolved());
0284:                    String target = "".equals(info.getTargetName()) ? null
0285:                            : info.getTargetName();
0286:                    repository.update(url, revNumber, target, recursive,
0287:                            reporter, SVNCancellableEditor.newInstance(editor,
0288:                                    this , getDebugLog()));
0289:
0290:                    if (editor.getTargetRevision() >= 0 && recursive
0291:                            && !isIgnoreExternals()) {
0292:                        handleExternals(info);
0293:                        dispatchEvent(SVNEventFactory
0294:                                .createUpdateCompletedEvent(info, editor
0295:                                        .getTargetRevision()));
0296:                    }
0297:                    return editor.getTargetRevision();
0298:                } finally {
0299:                    wcAccess.close();
0300:                    sleepForTimeStamp();
0301:                }
0302:            }
0303:
0304:            /**
0305:             * Checks out a Working Copy from a repository.
0306:             * 
0307:             * <p>
0308:             * If the destination path (<code>dstPath</code>) is <span class="javakeyword">null</span>
0309:             * then the last component of <code>url</code> is used for the local directory name.
0310:             * 
0311:             * <p>
0312:             * As a revision <b>SVNRevision</b>'s pre-defined constant fields can be used. For example,
0313:             * to check out a Working Copy at the latest revision of the repository use 
0314:             * {@link SVNRevision#HEAD HEAD}.
0315:             * 
0316:             * @param  url			a repository location from where a Working Copy will be checked out		
0317:             * @param  dstPath		the local path where the Working Copy will be placed
0318:             * @param  pegRevision	the revision at which <code>url</code> will be firstly seen
0319:             * 						in the repository to make sure it's the one that is needed
0320:             * @param  revision		the desired revision of the Working Copy to be checked out
0321:             * @param  recursive	if <span class="javakeyword">true</span> and <code>url</code> is
0322:             * 						a directory then the entire tree will be checked out, otherwise if 
0323:             * 						<span class="javakeyword">false</span> - only items located immediately
0324:             * 						in the directory itself
0325:             * @return				the revision number of the Working Copy
0326:             * @throws SVNException <code>url</code> refers to a file, not a directory; <code>dstPath</code>
0327:             * 						already exists but it is a file, not a directory; <code>dstPath</code> already
0328:             * 						exists and is a versioned directory but has a different URL (repository location
0329:             * 						against which the directory is controlled)  
0330:             */
0331:            public long doCheckout(SVNURL url, File dstPath,
0332:                    SVNRevision pegRevision, SVNRevision revision,
0333:                    boolean recursive) throws SVNException {
0334:                if (dstPath == null) {
0335:                    SVNErrorMessage err = SVNErrorMessage.create(
0336:                            SVNErrorCode.BAD_FILENAME,
0337:                            "Checkout destination path can not be NULL");
0338:                    SVNErrorManager.error(err);
0339:                }
0340:                pegRevision = pegRevision == null ? SVNRevision.UNDEFINED
0341:                        : pegRevision;
0342:
0343:                if (!revision.isValid() && pegRevision.isValid()) {
0344:                    revision = pegRevision;
0345:                }
0346:
0347:                if (!revision.isValid()) {
0348:                    revision = SVNRevision.HEAD;
0349:                }
0350:
0351:                SVNRepository repos = createRepository(url, null, pegRevision,
0352:                        revision);
0353:                url = repos.getLocation();
0354:                long revNumber = getRevisionNumber(revision, repos, null);
0355:                SVNNodeKind targetNodeKind = repos.checkPath("", revNumber);
0356:                if (targetNodeKind == SVNNodeKind.FILE) {
0357:                    SVNErrorMessage err = SVNErrorMessage.create(
0358:                            SVNErrorCode.UNSUPPORTED_FEATURE,
0359:                            "URL ''{0}'' refers to a file, not a directory",
0360:                            url);
0361:                    SVNErrorManager.error(err);
0362:                } else if (targetNodeKind == SVNNodeKind.NONE) {
0363:                    SVNErrorMessage err = SVNErrorMessage.create(
0364:                            SVNErrorCode.RA_ILLEGAL_URL,
0365:                            "URL ''{0}'' doesn''t exist", url);
0366:                    SVNErrorManager.error(err);
0367:                }
0368:                String uuid = repos.getRepositoryUUID(true);
0369:                SVNURL repositoryRoot = repos.getRepositoryRoot(true);
0370:
0371:                long result = -1;
0372:                try {
0373:                    SVNWCAccess wcAccess = createWCAccess();
0374:                    SVNFileType kind = SVNFileType.getType(dstPath);
0375:                    if (kind == SVNFileType.NONE) {
0376:                        SVNAdminAreaFactory.createVersionedDirectory(dstPath,
0377:                                url, repositoryRoot, uuid, revNumber);
0378:                        result = doUpdate(dstPath, revision, recursive);
0379:                    } else if (kind == SVNFileType.DIRECTORY) {
0380:                        int formatVersion = SVNAdminAreaFactory.checkWC(
0381:                                dstPath, true);
0382:                        if (formatVersion != 0) {
0383:                            SVNAdminArea adminArea = wcAccess.open(dstPath,
0384:                                    false, 0);
0385:                            SVNEntry rootEntry = adminArea.getEntry(adminArea
0386:                                    .getThisDirName(), false);
0387:                            wcAccess.closeAdminArea(dstPath);
0388:                            if (rootEntry.getSVNURL() != null
0389:                                    && url.equals(rootEntry.getSVNURL())) {
0390:                                result = doUpdate(dstPath, revision, recursive);
0391:                            } else {
0392:                                String message = "''{0}'' is already a working copy for a different URL";
0393:                                if (rootEntry.isIncomplete()) {
0394:                                    message += "; perform update to complete it";
0395:                                }
0396:                                SVNErrorMessage err = SVNErrorMessage.create(
0397:                                        SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0398:                                        message, dstPath);
0399:                                SVNErrorManager.error(err);
0400:                            }
0401:                        } else {
0402:                            SVNAdminAreaFactory.createVersionedDirectory(
0403:                                    dstPath, url, repositoryRoot, uuid,
0404:                                    revNumber);
0405:                            result = doUpdate(dstPath, revision, recursive);
0406:                        }
0407:                    } else {
0408:                        SVNErrorMessage err = SVNErrorMessage
0409:                                .create(
0410:                                        SVNErrorCode.WC_NODE_KIND_CHANGE,
0411:                                        "''{0}'' already exists and is not a directory",
0412:                                        dstPath);
0413:                        SVNErrorManager.error(err);
0414:                    }
0415:                } finally {
0416:                    sleepForTimeStamp();
0417:                }
0418:                return result;
0419:            }
0420:
0421:            /**
0422:             * Exports a clean directory or single file from a repository.
0423:             * 
0424:             * <p>
0425:             * If <code>eolStyle</code> is not <span class="javakeyword">null</span> then it should denote
0426:             * a specific End-Of-Line marker for the files to be exported. Significant values for 
0427:             * <code>eolStyle</code> are:
0428:             * <ul>
0429:             * <li>"CRLF" (Carriage Return Line Feed) - this causes files to contain '\r\n' line ending sequences 
0430:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker is used by 
0431:             * software on the Windows platform).
0432:             * <li>"LF" (Line Feed) - this causes files to contain '\n' line ending sequences 
0433:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker is used by 
0434:             * software on the Unix platform). 
0435:             * <li>"CR" (Carriage Return) - this causes files to contain '\r' line ending sequences 
0436:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker was used by 
0437:             * software on older Macintosh platforms).
0438:             * <li>"native" - this causes files to contain the EOL markers that are native to the operating system 
0439:             * on which SVNKit is run.
0440:             * </ul>
0441:             * 
0442:             * @param  url				a repository location from where the unversioned directory/file  will
0443:             * 							be exported
0444:             * @param  dstPath			the local path where the repository items will be exported to 			
0445:             * @param  pegRevision		the revision at which <code>url</code> will be firstly seen
0446:             * 							in the repository to make sure it's the one that is needed
0447:             * @param  revision			the desired revision of the directory/file to be exported
0448:             * @param  eolStyle			a string that denotes a specific End-Of-Line charecter;  
0449:             * @param  force			<span class="javakeyword">true</span> to fore the operation even
0450:             * 							if there are local files with the same names as those in the repository
0451:             * 							(local ones will be replaced) 
0452:             * @param  recursive		if <span class="javakeyword">true</span> and <code>url</code> is
0453:             * 							a directory then the entire tree will be exported, otherwise if 
0454:             * 							<span class="javakeyword">false</span> - only items located immediately
0455:             * 							in the directory itself
0456:             * @return					the revision number of the exported directory/file 
0457:             * @throws SVNException
0458:             */
0459:            public long doExport(SVNURL url, File dstPath,
0460:                    SVNRevision pegRevision, SVNRevision revision,
0461:                    String eolStyle, boolean force, boolean recursive)
0462:                    throws SVNException {
0463:                SVNRepository repository = createRepository(url, null,
0464:                        pegRevision, revision);
0465:                long revisionNumber = getRevisionNumber(revision, repository,
0466:                        null);
0467:                long exportedRevision = doRemoteExport(repository,
0468:                        revisionNumber, dstPath, eolStyle, force, recursive);
0469:                dispatchEvent(SVNEventFactory.createUpdateCompletedEvent(
0470:                        (SVNAdminAreaInfo) null, exportedRevision));
0471:                return exportedRevision;
0472:            }
0473:
0474:            /**
0475:             * Exports a clean directory or single file from eihter a source Working Copy or
0476:             * a repository.
0477:             * 
0478:             * <p>
0479:             * How this method works:
0480:             * <ul>
0481:             * <li> If <code>revision</code> is different from {@link SVNRevision#BASE BASE}, 
0482:             * {@link SVNRevision#WORKING WORKING}, {@link SVNRevision#COMMITTED COMMITTED}, 
0483:             * {@link SVNRevision#UNDEFINED UNDEFINED} - then the repository origin of <code>srcPath</code>
0484:             * will be exported (what is done by "remote" {@link #doExport(SVNURL, File, SVNRevision, SVNRevision, String, boolean, boolean)
0485:             * doExport()}).
0486:             * <li> In other cases a clean unversioned copy of <code>srcPath</code> - either a directory or a single file -
0487:             * is exported to <code>dstPath</code>. 
0488:             * </ul>
0489:             * 
0490:             * <p>
0491:             * If <code>eolStyle</code> is not <span class="javakeyword">null</span> then it should denote
0492:             * a specific End-Of-Line marker for the files to be exported. Significant values for 
0493:             * <code>eolStyle</code> are:
0494:             * <ul>
0495:             * <li>"CRLF" (Carriage Return Line Feed) - this causes files to contain '\r\n' line ending sequences 
0496:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker is used by 
0497:             * software on the Windows platform).
0498:             * <li>"LF" (Line Feed) - this causes files to contain '\n' line ending sequences 
0499:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker is used by 
0500:             * software on the Unix platform). 
0501:             * <li>"CR" (Carriage Return) - this causes files to contain '\r' line ending sequences 
0502:             * for EOL markers, regardless of the operating system in use (for instance, this EOL marker was used by 
0503:             * software on older Macintosh platforms).
0504:             * <li>"native" - this causes files to contain the EOL markers that are native to the operating system 
0505:             * on which SVNKit is run.
0506:             * </ul>
0507:             * 
0508:             * @param  srcPath			a repository location from where the unversioned directory/file  will
0509:             * 							be exported
0510:             * @param  dstPath			the local path where the repository items will be exported to 			
0511:             * @param  pegRevision		the revision at which <code>url</code> will be firstly seen
0512:             * 							in the repository to make sure it's the one that is needed
0513:             * @param  revision			the desired revision of the directory/file to be exported
0514:             * @param  eolStyle			a string that denotes a specific End-Of-Line charecter;  
0515:             * @param  force			<span class="javakeyword">true</span> to fore the operation even
0516:             * 							if there are local files with the same names as those in the repository
0517:             * 							(local ones will be replaced) 
0518:             * @param  recursive		if <span class="javakeyword">true</span> and <code>url</code> is
0519:             * 							a directory then the entire tree will be exported, otherwise if 
0520:             * 							<span class="javakeyword">false</span> - only items located immediately
0521:             * 							in the directory itself
0522:             * @return					the revision number of the exported directory/file 
0523:             * @throws SVNException
0524:             */
0525:            public long doExport(File srcPath, final File dstPath,
0526:                    SVNRevision pegRevision, SVNRevision revision,
0527:                    String eolStyle, final boolean force, boolean recursive)
0528:                    throws SVNException {
0529:                long exportedRevision = -1;
0530:                if (revision != SVNRevision.BASE
0531:                        && revision != SVNRevision.WORKING
0532:                        && revision != SVNRevision.COMMITTED
0533:                        && revision != SVNRevision.UNDEFINED) {
0534:                    SVNRepository repository = createRepository(null, srcPath,
0535:                            pegRevision, revision);
0536:                    long revisionNumber = getRevisionNumber(revision,
0537:                            repository, srcPath);
0538:                    exportedRevision = doRemoteExport(repository,
0539:                            revisionNumber, dstPath, eolStyle, force, recursive);
0540:                } else {
0541:                    if (revision == SVNRevision.UNDEFINED) {
0542:                        revision = SVNRevision.WORKING;
0543:                    }
0544:                    copyVersionedDir(srcPath, dstPath, revision, eolStyle,
0545:                            force, recursive);
0546:                }
0547:                dispatchEvent(SVNEventFactory.createUpdateCompletedEvent(
0548:                        (SVNAdminAreaInfo) null, exportedRevision));
0549:                return exportedRevision;
0550:            }
0551:
0552:            private void copyVersionedDir(File from, File to,
0553:                    SVNRevision revision, String eolStyle, boolean force,
0554:                    boolean recursive) throws SVNException {
0555:                SVNWCAccess wcAccess = createWCAccess();
0556:                SVNAdminArea adminArea = wcAccess.probeOpen(from, false, 0);
0557:                SVNEntry entry = wcAccess.getEntry(from, false);
0558:                if (entry == null) {
0559:                    wcAccess.close();
0560:                    SVNErrorMessage err = SVNErrorMessage
0561:                            .create(
0562:                                    SVNErrorCode.ENTRY_NOT_FOUND,
0563:                                    "''{0}'' is not under version control or doesn''t exist",
0564:                                    from, SVNErrorMessage.TYPE_WARNING);
0565:                    SVNErrorManager.error(err);
0566:                }
0567:
0568:                if (revision == SVNRevision.WORKING
0569:                        && entry.isScheduledForDeletion()) {
0570:                    return;
0571:                }
0572:                if (revision != SVNRevision.WORKING
0573:                        && entry.isScheduledForAddition()) {
0574:                    return;
0575:                }
0576:                if (entry.isDirectory()) {
0577:                    // create dir
0578:                    boolean dirCreated = to.mkdirs();
0579:                    if (!to.exists() || to.isFile()) {
0580:                        SVNErrorMessage err = SVNErrorMessage.create(
0581:                                SVNErrorCode.IO_ERROR,
0582:                                "Cannot create directory ''{0}''", to);
0583:                        SVNErrorManager.error(err);
0584:                    }
0585:                    if (!dirCreated && to.isDirectory() && !force) {
0586:                        SVNErrorMessage err = SVNErrorMessage
0587:                                .create(
0588:                                        SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0589:                                        "''{0}'' already exists and will not be owerwritten unless forced",
0590:                                        to);
0591:                        SVNErrorManager.error(err);
0592:                    }
0593:                    // read entries
0594:                    for (Iterator ents = adminArea.entries(false); ents
0595:                            .hasNext();) {
0596:                        SVNEntry childEntry = (SVNEntry) ents.next();
0597:                        if (childEntry.isDirectory()) {
0598:                            if (adminArea.getThisDirName().equals(
0599:                                    childEntry.getName())) {
0600:                                continue;
0601:                            } else if (recursive) {
0602:                                File childTo = new File(to, childEntry
0603:                                        .getName());
0604:                                File childFrom = new File(from, childEntry
0605:                                        .getName());
0606:                                copyVersionedDir(childFrom, childTo, revision,
0607:                                        eolStyle, force, recursive);
0608:                            }
0609:                        } else if (childEntry.isFile()) {
0610:                            File childTo = new File(to, childEntry.getName());
0611:                            copyVersionedFile(childTo, adminArea, childEntry
0612:                                    .getName(), revision, eolStyle);
0613:                        }
0614:                    }
0615:                } else if (entry.isFile()) {
0616:                    copyVersionedFile(to, adminArea, entry.getName(), revision,
0617:                            eolStyle);
0618:                }
0619:
0620:                wcAccess.close();
0621:            }
0622:
0623:            private void copyVersionedFile(File dstPath,
0624:                    SVNAdminArea adminArea, String fileName,
0625:                    SVNRevision revision, String eol) throws SVNException {
0626:                SVNEntry entry = adminArea.getEntry(fileName, false);
0627:                if (revision == SVNRevision.WORKING
0628:                        && entry.isScheduledForDeletion()) {
0629:                    return;
0630:                }
0631:                if (revision != SVNRevision.WORKING
0632:                        && entry.isScheduledForAddition()) {
0633:                    return;
0634:                }
0635:                boolean modified = false;
0636:                SVNVersionedProperties props = null;
0637:                long timestamp;
0638:                if (revision != SVNRevision.WORKING) {
0639:                    props = adminArea.getBaseProperties(fileName);
0640:                } else {
0641:                    props = adminArea.getProperties(fileName);
0642:                    modified = adminArea.hasTextModifications(fileName, false);
0643:                }
0644:                boolean special = props.getPropertyValue(SVNProperty.SPECIAL) != null;
0645:                boolean executable = props
0646:                        .getPropertyValue(SVNProperty.EXECUTABLE) != null;
0647:                String keywords = props.getPropertyValue(SVNProperty.KEYWORDS);
0648:                byte[] eols = eol != null ? SVNTranslator.getEOL(eol) : null;
0649:                if (eols == null) {
0650:                    eol = props.getPropertyValue(SVNProperty.EOL_STYLE);
0651:                    eols = SVNTranslator.getWorkingEOL(eol);
0652:                }
0653:                if (modified && !special) {
0654:                    timestamp = adminArea.getFile(fileName).lastModified();
0655:                } else {
0656:                    timestamp = SVNTimeUtil.parseDateAsLong(entry
0657:                            .getCommittedDate());
0658:                }
0659:                Map keywordsMap = null;
0660:                if (keywords != null) {
0661:                    String rev = Long.toString(entry.getCommittedRevision());
0662:                    String author;
0663:                    if (modified) {
0664:                        author = "(local)";
0665:                        rev += "M";
0666:                    } else {
0667:                        author = entry.getAuthor();
0668:                    }
0669:                    keywordsMap = SVNTranslator.computeKeywords(keywords, entry
0670:                            .getURL(), author, entry.getCommittedDate(), rev,
0671:                            getOptions());
0672:                }
0673:                File srcFile = revision == SVNRevision.WORKING ? adminArea
0674:                        .getFile(fileName) : adminArea.getBaseFile(fileName,
0675:                        false);
0676:                SVNFileType fileType = SVNFileType.getType(srcFile);
0677:                if (fileType == SVNFileType.SYMLINK
0678:                        && revision == SVNRevision.WORKING) {
0679:                    // base will be translated OK, but working not.
0680:                    File tmpBaseFile = adminArea.getBaseFile(fileName, true);
0681:                    try {
0682:                        SVNTranslator.translate(srcFile, tmpBaseFile, eols,
0683:                                keywordsMap, special, false);
0684:                        SVNTranslator.translate(tmpBaseFile, dstPath, eols,
0685:                                keywordsMap, special, true);
0686:                    } finally {
0687:                        tmpBaseFile.delete();
0688:                    }
0689:                } else {
0690:                    SVNTranslator.translate(srcFile, dstPath, eols,
0691:                            keywordsMap, special, true);
0692:                }
0693:                if (executable) {
0694:                    SVNFileUtil.setExecutable(dstPath, true);
0695:                }
0696:                if (!special && timestamp > 0) {
0697:                    dstPath.setLastModified(timestamp);
0698:                }
0699:            }
0700:
0701:            private long doRemoteExport(SVNRepository repository,
0702:                    final long revNumber, File dstPath, String eolStyle,
0703:                    boolean force, boolean recursive) throws SVNException {
0704:                SVNNodeKind dstKind = repository.checkPath("", revNumber);
0705:                if (dstKind == SVNNodeKind.DIR) {
0706:                    SVNExportEditor editor = new SVNExportEditor(this ,
0707:                            repository.getLocation().toString(), dstPath,
0708:                            force, eolStyle, getOptions());
0709:                    repository.update(revNumber, null, recursive,
0710:                            new ISVNReporterBaton() {
0711:                                public void report(ISVNReporter reporter)
0712:                                        throws SVNException {
0713:                                    reporter.setPath("", null, revNumber, true);
0714:                                    reporter.finishReport();
0715:                                }
0716:                            }, SVNCancellableEditor.newInstance(editor, this ,
0717:                                    getDebugLog()));
0718:                    // nothing may be created.
0719:                    SVNFileType fileType = SVNFileType.getType(dstPath);
0720:                    if (fileType == SVNFileType.NONE) {
0721:                        editor.openRoot(revNumber);
0722:                    }
0723:                    if (!isIgnoreExternals() && recursive) {
0724:                        Map externals = editor.getCollectedExternals();
0725:                        for (Iterator files = externals.keySet().iterator(); files
0726:                                .hasNext();) {
0727:                            File rootFile = (File) files.next();
0728:                            String propValue = (String) externals.get(rootFile);
0729:                            if (propValue == null) {
0730:                                continue;
0731:                            }
0732:                            SVNExternalInfo[] infos = SVNAdminAreaInfo
0733:                                    .parseExternals("", propValue);
0734:                            for (int i = 0; i < infos.length; i++) {
0735:                                File targetDir = new File(rootFile, infos[i]
0736:                                        .getPath());
0737:                                SVNURL srcURL = infos[i].getOldURL();
0738:                                long externalRevNumber = infos[i]
0739:                                        .getOldRevision();
0740:                                SVNRevision srcRevision = externalRevNumber >= 0 ? SVNRevision
0741:                                        .create(externalRevNumber)
0742:                                        : SVNRevision.HEAD;
0743:                                String relativePath = targetDir.equals(dstPath) ? ""
0744:                                        : targetDir
0745:                                                .getAbsolutePath()
0746:                                                .substring(
0747:                                                        dstPath
0748:                                                                .getAbsolutePath()
0749:                                                                .length() + 1);
0750:                                relativePath = relativePath.replace(
0751:                                        File.separatorChar, '/');
0752:                                dispatchEvent(SVNEventFactory
0753:                                        .createUpdateExternalEvent(
0754:                                                (SVNAdminAreaInfo) null,
0755:                                                relativePath));
0756:                                try {
0757:                                    setEventPathPrefix(relativePath);
0758:                                    doExport(srcURL, targetDir, srcRevision,
0759:                                            srcRevision, eolStyle, force,
0760:                                            recursive);
0761:                                } catch (SVNException e) {
0762:                                    if (e instanceof  SVNCancelException) {
0763:                                        throw e;
0764:                                    }
0765:                                    dispatchEvent(new SVNEvent(e
0766:                                            .getErrorMessage()));
0767:                                } finally {
0768:                                    setEventPathPrefix(null);
0769:                                }
0770:                            }
0771:                        }
0772:                    }
0773:                } else if (dstKind == SVNNodeKind.FILE) {
0774:                    String url = repository.getLocation().toString();
0775:                    if (dstPath.isDirectory()) {
0776:                        dstPath = new File(dstPath, SVNEncodingUtil
0777:                                .uriDecode(SVNPathUtil.tail(url)));
0778:                    }
0779:                    if (dstPath.exists()) {
0780:                        if (!force) {
0781:                            SVNErrorMessage err = SVNErrorMessage.create(
0782:                                    SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0783:                                    "Path ''{0}'' already exists", dstPath);
0784:                            SVNErrorManager.error(err);
0785:                        }
0786:                    } else {
0787:                        dstPath.getParentFile().mkdirs();
0788:                    }
0789:                    Map properties = new HashMap();
0790:                    OutputStream os = null;
0791:                    File tmpFile = SVNFileUtil.createUniqueFile(dstPath
0792:                            .getParentFile(), ".export", ".tmp");
0793:                    try {
0794:                        os = SVNFileUtil.openFileForWriting(tmpFile);
0795:                        try {
0796:                            repository.getFile("", revNumber, properties,
0797:                                    new SVNCancellableOutputStream(os, this ));
0798:                        } finally {
0799:                            SVNFileUtil.closeFile(os);
0800:                        }
0801:                        if (force && dstPath.exists()) {
0802:                            SVNFileUtil.deleteAll(dstPath, this );
0803:                        }
0804:                        boolean binary = SVNProperty
0805:                                .isBinaryMimeType((String) properties
0806:                                        .get(SVNProperty.MIME_TYPE));
0807:                        Map keywords = SVNTranslator.computeKeywords(
0808:                                (String) properties.get(SVNProperty.KEYWORDS),
0809:                                url, (String) properties
0810:                                        .get(SVNProperty.LAST_AUTHOR),
0811:                                (String) properties
0812:                                        .get(SVNProperty.COMMITTED_DATE),
0813:                                (String) properties
0814:                                        .get(SVNProperty.COMMITTED_REVISION),
0815:                                getOptions());
0816:                        byte[] eols = null;
0817:                        if (SVNProperty.EOL_STYLE_NATIVE.equals(properties
0818:                                .get(SVNProperty.EOL_STYLE))) {
0819:                            eols = SVNTranslator
0820:                                    .getWorkingEOL(eolStyle != null ? eolStyle
0821:                                            : (String) properties
0822:                                                    .get(SVNProperty.EOL_STYLE));
0823:                        } else if (properties
0824:                                .containsKey(SVNProperty.EOL_STYLE)) {
0825:                            eols = SVNTranslator
0826:                                    .getWorkingEOL((String) properties
0827:                                            .get(SVNProperty.EOL_STYLE));
0828:                        }
0829:                        if (binary) {
0830:                            eols = null;
0831:                            keywords = null;
0832:                        }
0833:                        SVNTranslator.translate(tmpFile, dstPath, eols,
0834:                                keywords,
0835:                                properties.get(SVNProperty.SPECIAL) != null,
0836:                                true);
0837:                    } finally {
0838:                        SVNFileUtil.deleteFile(tmpFile);
0839:                    }
0840:                    if (properties.get(SVNProperty.EXECUTABLE) != null) {
0841:                        SVNFileUtil.setExecutable(dstPath, true);
0842:                    }
0843:                    dispatchEvent(SVNEventFactory.createExportAddedEvent(
0844:                            dstPath.getParentFile(), dstPath, SVNNodeKind.FILE));
0845:                } else {
0846:                    SVNErrorMessage err = SVNErrorMessage.create(
0847:                            SVNErrorCode.RA_ILLEGAL_URL,
0848:                            "URL ''{0}'' doesn't exist", repository
0849:                                    .getLocation());
0850:                    SVNErrorManager.error(err);
0851:                }
0852:                return revNumber;
0853:            }
0854:
0855:            /**
0856:             * Substitutes the beginning part of a Working Copy's URL with a new one.
0857:             * 
0858:             * <p> 
0859:             * When a repository root location or a URL schema is changed the old URL of the 
0860:             * Working Copy which starts with <code>oldURL</code> should be substituted for a
0861:             * new URL beginning - <code>newURL</code>.
0862:             * 
0863:             * @param  dst				a Working Copy item's path 
0864:             * @param  oldURL			the old beginning part of the repository's URL that should
0865:             * 							be overwritten  
0866:             * @param  newURL			a new beginning part for the repository location that
0867:             * 							will overwrite <code>oldURL</code> 
0868:             * @param  recursive		if <span class="javakeyword">true</span> and <code>dst</code> is
0869:             * 							a directory then the entire tree will be relocated, otherwise if 
0870:             * 							<span class="javakeyword">false</span> - only <code>dst</code> itself
0871:             * @throws SVNException
0872:             */
0873:            public void doRelocate(File dst, SVNURL oldURL, SVNURL newURL,
0874:                    boolean recursive) throws SVNException {
0875:                SVNWCAccess wcAccess = createWCAccess();
0876:                try {
0877:                    SVNAdminArea adminArea = wcAccess.probeOpen(dst, true,
0878:                            recursive ? SVNWCAccess.INFINITE_DEPTH : 0);
0879:                    String name = dst.equals(adminArea.getRoot()) ? adminArea
0880:                            .getThisDirName() : dst.getName();
0881:                    String from = oldURL.toString();
0882:                    String to = newURL.toString();
0883:                    if (from.endsWith("/")) {
0884:                        from = from.substring(0, from.length() - 1);
0885:                    }
0886:                    if (to.endsWith("/")) {
0887:                        to = to.substring(0, to.length() - 1);
0888:                    }
0889:                    doRelocate(adminArea, name, from, to, recursive,
0890:                            new HashMap());
0891:                } finally {
0892:                    wcAccess.close();
0893:                }
0894:            }
0895:
0896:            /**
0897:             * Canonicalizes all urls in the specified Working Copy.
0898:             * 
0899:             * @param dst               a WC path     
0900:             * @param omitDefaultPort   if <span class="javakeyword">true</span> then removes all
0901:             *                          port numbers from urls which equal to default ones, otherwise
0902:             *                          does not
0903:             * @param recursive         recurses an operation
0904:             * @throws SVNException
0905:             */
0906:            public void doCanonicalizeURLs(File dst, boolean omitDefaultPort,
0907:                    boolean recursive) throws SVNException {
0908:                SVNWCAccess wcAccess = createWCAccess();
0909:                try {
0910:                    SVNAdminAreaInfo adminAreaInfo = wcAccess.openAnchor(dst,
0911:                            true, recursive ? SVNWCAccess.INFINITE_DEPTH : 0);
0912:                    SVNAdminArea target = adminAreaInfo.getTarget();
0913:                    SVNEntry entry = wcAccess.getEntry(dst, false);
0914:                    String name = target.getThisDirName();
0915:                    if (entry != null && entry.isFile()) {
0916:                        name = entry.getName();
0917:                    }
0918:                    doCanonicalizeURLs(adminAreaInfo, target, name,
0919:                            omitDefaultPort, recursive);
0920:                    if (recursive && !isIgnoreExternals()) {
0921:                        for (Iterator externals = adminAreaInfo.externals(); externals
0922:                                .hasNext();) {
0923:                            SVNExternalInfo info = (SVNExternalInfo) externals
0924:                                    .next();
0925:                            try {
0926:                                doCanonicalizeURLs(info.getFile(),
0927:                                        omitDefaultPort, true);
0928:                            } catch (SVNCancelException e) {
0929:                                throw e;
0930:                            } catch (SVNException e) {
0931:                                getDebugLog().info(e);
0932:                            }
0933:                        }
0934:                    }
0935:                } finally {
0936:                    wcAccess.close();
0937:                }
0938:            }
0939:
0940:            private void doCanonicalizeURLs(SVNAdminAreaInfo adminAreaInfo,
0941:                    SVNAdminArea adminArea, String name,
0942:                    boolean omitDefaultPort, boolean recursive)
0943:                    throws SVNException {
0944:                boolean save = false;
0945:                checkCancelled();
0946:                if (!adminArea.getThisDirName().equals(name)) {
0947:                    SVNEntry entry = adminArea.getEntry(name, true);
0948:                    save = canonicalizeEntry(entry, omitDefaultPort);
0949:                    adminArea.getWCProperties(name).setPropertyValue(
0950:                            SVNProperty.WC_URL, null);
0951:                    if (save) {
0952:                        adminArea.saveEntries(false);
0953:                    }
0954:                    return;
0955:                }
0956:                if (!isIgnoreExternals()) {
0957:                    String externalsValue = adminArea.getProperties(
0958:                            adminArea.getThisDirName()).getPropertyValue(
0959:                            SVNProperty.EXTERNALS);
0960:                    adminAreaInfo.addExternals(adminArea, externalsValue);
0961:                    if (externalsValue != null) {
0962:                        externalsValue = canonicalizeExtenrals(externalsValue,
0963:                                omitDefaultPort);
0964:                        adminArea.getProperties(adminArea.getThisDirName())
0965:                                .setPropertyValue(SVNProperty.EXTERNALS,
0966:                                        externalsValue);
0967:                    }
0968:                }
0969:
0970:                SVNEntry rootEntry = adminArea.getEntry(adminArea
0971:                        .getThisDirName(), true);
0972:                save = canonicalizeEntry(rootEntry, omitDefaultPort);
0973:                adminArea.getWCProperties(adminArea.getThisDirName())
0974:                        .setPropertyValue(SVNProperty.WC_URL, null);
0975:                // now all child entries that doesn't has repos/url has new values.
0976:                for (Iterator ents = adminArea.entries(true); ents.hasNext();) {
0977:                    SVNEntry entry = (SVNEntry) ents.next();
0978:                    if (adminArea.getThisDirName().equals(entry.getName())) {
0979:                        continue;
0980:                    }
0981:                    checkCancelled();
0982:                    if (recursive
0983:                            && entry.isDirectory()
0984:                            && (entry.isScheduledForAddition() || !entry
0985:                                    .isDeleted()) && !entry.isAbsent()) {
0986:                        SVNAdminArea childArea = adminArea.getWCAccess()
0987:                                .retrieve(adminArea.getFile(entry.getName()));
0988:                        if (childArea != null) {
0989:                            doCanonicalizeURLs(adminAreaInfo, childArea, "",
0990:                                    omitDefaultPort, recursive);
0991:                        }
0992:                    }
0993:                    save |= canonicalizeEntry(entry, omitDefaultPort);
0994:                    SVNVersionedProperties properties = adminArea
0995:                            .getWCProperties(entry.getName());
0996:                    if (properties != null) {
0997:                        properties.setPropertyValue(SVNProperty.WC_URL, null);
0998:                    }
0999:                }
1000:                if (save) {
1001:                    adminArea.saveEntries(true);
1002:                }
1003:            }
1004:
1005:            private static String canonicalizeExtenrals(String externals,
1006:                    boolean omitDefaultPort) throws SVNException {
1007:                if (externals == null) {
1008:                    return null;
1009:                }
1010:                StringBuffer canonicalized = new StringBuffer();
1011:                for (StringTokenizer lines = new StringTokenizer(externals,
1012:                        "\r\n", true); lines.hasMoreTokens();) {
1013:                    String line = lines.nextToken();
1014:                    if (line.trim().length() == 0
1015:                            || line.trim().startsWith("#")
1016:                            || line.indexOf('\r') >= 0
1017:                            || line.indexOf('\n') >= 0) {
1018:                        canonicalized.append(line);
1019:                        continue;
1020:                    }
1021:                    String[] tokens = line.split("[ \t]");
1022:                    int index = tokens.length - 1;
1023:                    SVNURL url = null;
1024:                    if (index >= 1) {
1025:                        try {
1026:                            url = SVNURL.parseURIEncoded(tokens[index]);
1027:                        } catch (SVNException e) {
1028:                            url = null;
1029:                        }
1030:                    }
1031:                    SVNURL canonicalURL = canonicalizeURL(url, omitDefaultPort);
1032:                    if (canonicalURL == null) {
1033:                        canonicalized.append(line);
1034:                    } else {
1035:                        canonicalized.append(tokens[0]);
1036:                        canonicalized.append(' ');
1037:                        if (index == 2) {
1038:                            canonicalized.append(tokens[1]);
1039:                            canonicalized.append(' ');
1040:                        }
1041:                        canonicalized.append(canonicalURL.toString());
1042:                    }
1043:                }
1044:                return canonicalized.toString();
1045:            }
1046:
1047:            private static boolean canonicalizeEntry(SVNEntry entry,
1048:                    boolean omitDefaultPort) throws SVNException {
1049:                boolean updated = false;
1050:                SVNURL root = canonicalizeURL(entry.getRepositoryRootURL(),
1051:                        omitDefaultPort);
1052:                if (root != null) {
1053:                    updated |= entry.setRepositoryRootURL(root);
1054:                }
1055:                SVNURL url = canonicalizeURL(entry.getSVNURL(), omitDefaultPort);
1056:                if (url != null) {
1057:                    updated |= entry.setURL(url.toString());
1058:                }
1059:                SVNURL copyFrom = canonicalizeURL(entry.getCopyFromSVNURL(),
1060:                        omitDefaultPort);
1061:                if (copyFrom != null) {
1062:                    updated |= entry.setCopyFromURL(copyFrom.toString());
1063:                }
1064:                return updated;
1065:            }
1066:
1067:            private static SVNURL canonicalizeURL(SVNURL url,
1068:                    boolean omitDefaultPort) throws SVNException {
1069:                if (url == null || url.getPort() <= 0) {
1070:                    // no url or file url.
1071:                    return null;
1072:                }
1073:                int defaultPort = SVNURL
1074:                        .getDefaultPortNumber(url.getProtocol());
1075:                if (defaultPort <= 0) {
1076:                    // file or svn+ext URL.
1077:                    return null;
1078:                }
1079:                if (omitDefaultPort) {
1080:                    // remove port if it is same as default.
1081:                    if (url.hasPort() && url.getPort() == defaultPort) {
1082:                        return SVNURL.create(url.getProtocol(), url
1083:                                .getUserInfo(), url.getHost(), -1, url
1084:                                .getPath(), false);
1085:                    }
1086:                } else if (!url.hasPort()) {
1087:                    // set port if there is no port set.
1088:                    return SVNURL.create(url.getProtocol(), url.getUserInfo(),
1089:                            url.getHost(), url.getPort(), url.getPath(), false);
1090:                }
1091:                return null;
1092:            }
1093:
1094:            private void handleExternals(SVNAdminAreaInfo info)
1095:                    throws SVNException {
1096:                for (Iterator externals = info.externals(); externals.hasNext();) {
1097:                    SVNExternalInfo external = (SVNExternalInfo) externals
1098:                            .next();
1099:                    if (external.getOldURL() == null
1100:                            && external.getNewURL() == null) {
1101:                        continue;
1102:                    }
1103:                    long revNumber = external.getNewRevision();
1104:                    SVNRevision revision = revNumber >= 0 ? SVNRevision
1105:                            .create(revNumber) : getExternalRevision(external
1106:                            .getFile(), external.getNewURL());
1107:                    setEventPathPrefix(external.getPath());
1108:                    try {
1109:                        if (external.getOldURL() == null) {
1110:                            external.getFile().mkdirs();
1111:                            dispatchEvent(SVNEventFactory
1112:                                    .createUpdateExternalEvent(info, ""));
1113:                            doCheckout(external.getNewURL(),
1114:                                    external.getFile(), revision, revision,
1115:                                    true);
1116:                        } else if (external.getNewURL() == null) {
1117:                            SVNWCAccess wcAccess = createWCAccess();
1118:                            SVNAdminArea area = wcAccess.open(external
1119:                                    .getFile(), true,
1120:                                    SVNWCAccess.INFINITE_DEPTH);
1121:                            SVNException error = null;
1122:                            try {
1123:                                area.removeFromRevisionControl(area
1124:                                        .getThisDirName(), true, false);
1125:                            } catch (SVNException svne) {
1126:                                error = svne;
1127:                            }
1128:
1129:                            if (error == null
1130:                                    || error.getErrorMessage().getErrorCode() == SVNErrorCode.WC_LEFT_LOCAL_MOD) {
1131:                                try {
1132:                                    wcAccess.close();
1133:                                } catch (SVNException svne) {
1134:                                    error = error == null ? svne : error;
1135:                                }
1136:                            }
1137:
1138:                            if (error != null
1139:                                    && error.getErrorMessage().getErrorCode() != SVNErrorCode.WC_LEFT_LOCAL_MOD) {
1140:                                throw error;
1141:                            }
1142:                        } else {
1143:                            dispatchEvent(SVNEventFactory
1144:                                    .createUpdateExternalEvent(info, ""));
1145:                            if (!external.getFile().isDirectory()) {
1146:                                boolean created = external.getFile().mkdirs();
1147:                                try {
1148:                                    doCheckout(external.getNewURL(), external
1149:                                            .getFile(), revision, revision,
1150:                                            true);
1151:                                } catch (SVNException e) {
1152:                                    if (created
1153:                                            && e.getErrorMessage()
1154:                                                    .getErrorCode() == SVNErrorCode.RA_ILLEGAL_URL) {
1155:                                        SVNFileUtil.deleteAll(external
1156:                                                .getFile(), true);
1157:                                    }
1158:                                    throw e;
1159:                                }
1160:                            } else {
1161:                                File[] children = external.getFile()
1162:                                        .listFiles();
1163:                                if (children != null && children.length == 0) {
1164:                                    // unversioned empty directory.
1165:                                    try {
1166:                                        doCheckout(external.getNewURL(),
1167:                                                external.getFile(), revision,
1168:                                                revision, true);
1169:                                    } catch (SVNException e) {
1170:                                        throw e;
1171:                                    }
1172:                                    continue;
1173:                                }
1174:                                SVNWCAccess wcAccess = createWCAccess();
1175:                                SVNAdminArea area = wcAccess.open(external
1176:                                        .getFile(), true, 0);
1177:                                SVNEntry entry = area.getEntry(area
1178:                                        .getThisDirName(), false);
1179:                                wcAccess.close();
1180:                                String url = entry.getURL();
1181:
1182:                                if (entry != null && entry.getURL() != null) {
1183:                                    if (external.getNewURL().toString().equals(
1184:                                            url)) {
1185:                                        doUpdate(external.getFile(), revision,
1186:                                                true);
1187:                                        continue;
1188:                                    } else if (entry.getRepositoryRoot() != null) {
1189:                                        if (!SVNPathUtil.isAncestor(entry
1190:                                                .getRepositoryRoot(), external
1191:                                                .getNewURL().toString())) {
1192:                                            SVNRepository repos = createRepository(
1193:                                                    external.getNewURL(), true);
1194:                                            SVNURL reposRoot = repos
1195:                                                    .getRepositoryRoot(true);
1196:                                            try {
1197:                                                doRelocate(external.getFile(),
1198:                                                        entry.getSVNURL(),
1199:                                                        reposRoot, true);
1200:                                            } catch (SVNException svne) {
1201:                                                if (svne.getErrorMessage()
1202:                                                        .getErrorCode() == SVNErrorCode.WC_INVALID_RELOCATION
1203:                                                        || svne
1204:                                                                .getErrorMessage()
1205:                                                                .getErrorCode() == SVNErrorCode.CLIENT_INVALID_RELOCATION) {
1206:                                                    deleteExternal(external);
1207:                                                    external.getFile().mkdirs();
1208:                                                    doCheckout(external
1209:                                                            .getNewURL(),
1210:                                                            external.getFile(),
1211:                                                            revision, revision,
1212:                                                            true);
1213:                                                    continue;
1214:                                                }
1215:                                                throw svne;
1216:                                            }
1217:                                        }
1218:                                        doSwitch(external.getFile(), external
1219:                                                .getNewURL(), revision, true);
1220:                                        continue;
1221:                                    }
1222:                                }
1223:                                deleteExternal(external);
1224:                                external.getFile().mkdirs();
1225:                                doCheckout(external.getNewURL(), external
1226:                                        .getFile(), revision, revision, true);
1227:                            }
1228:                        }
1229:                    } catch (SVNException th) {
1230:                        if (th instanceof  SVNCancelException) {
1231:                            throw th;
1232:                        }
1233:                        getDebugLog().info(th);
1234:                        File file = external.getFile();
1235:                        SVNEvent event = SVNEventFactory
1236:                                .createSkipEvent(file, file,
1237:                                        SVNEventAction.SKIP,
1238:                                        SVNEventAction.UPDATE_EXTERNAL,
1239:                                        SVNNodeKind.DIR);
1240:                        event.setErrorMessage(th.getErrorMessage());
1241:                        dispatchEvent(event);
1242:                    } finally {
1243:                        setEventPathPrefix(null);
1244:                    }
1245:                }
1246:            }
1247:
1248:            protected SVNRevision getExternalRevision(File file, SVNURL newURL) {
1249:                if (file == null || newURL == null) {
1250:                    return SVNRevision.HEAD;
1251:                }
1252:                return SVNRevision.HEAD;
1253:            }
1254:
1255:            private void deleteExternal(SVNExternalInfo external)
1256:                    throws SVNException {
1257:                SVNWCAccess wcAccess = createWCAccess();
1258:                SVNAdminArea adminArea = wcAccess.open(external.getFile(),
1259:                        true, SVNWCAccess.INFINITE_DEPTH);
1260:                SVNException error = null;
1261:                try {
1262:                    adminArea.removeFromRevisionControl(adminArea
1263:                            .getThisDirName(), true, false);
1264:                } catch (SVNException svne) {
1265:                    getDebugLog().info(svne);
1266:                    error = svne;
1267:                }
1268:
1269:                if (error == null
1270:                        || error.getErrorMessage().getErrorCode() == SVNErrorCode.WC_LEFT_LOCAL_MOD) {
1271:                    wcAccess.close();
1272:                }
1273:
1274:                if (error != null
1275:                        && error.getErrorMessage().getErrorCode() == SVNErrorCode.WC_LEFT_LOCAL_MOD) {
1276:                    external.getFile().getParentFile().mkdirs();
1277:                    File newLocation = SVNFileUtil.createUniqueFile(external
1278:                            .getFile().getParentFile(), external.getFile()
1279:                            .getName(), ".OLD");
1280:                    SVNFileUtil.rename(external.getFile(), newLocation);
1281:                } else if (error != null) {
1282:                    throw error;
1283:                }
1284:            }
1285:
1286:            private Map validateRelocateTargetURL(SVNURL targetURL,
1287:                    String expectedUUID, Map validatedURLs, boolean isRoot)
1288:                    throws SVNException {
1289:                if (validatedURLs == null) {
1290:                    return null;
1291:                }
1292:
1293:                for (Iterator targetURLs = validatedURLs.keySet().iterator(); targetURLs
1294:                        .hasNext();) {
1295:                    SVNURL validatedURL = (SVNURL) targetURLs.next();
1296:                    if (targetURL.toString()
1297:                            .startsWith(validatedURL.toString())) {
1298:                        if (isRoot && !targetURL.equals(validatedURL)) {
1299:                            SVNErrorMessage err = SVNErrorMessage
1300:                                    .create(
1301:                                            SVNErrorCode.CLIENT_INVALID_RELOCATION,
1302:                                            "''{0}'' is not the root of the repository",
1303:                                            targetURL);
1304:                            SVNErrorManager.error(err);
1305:                        }
1306:                        String validatedUUID = (String) validatedURLs
1307:                                .get(validatedURL);
1308:                        if (expectedUUID != null
1309:                                && !expectedUUID.equals(validatedUUID)) {
1310:                            SVNErrorMessage err = SVNErrorMessage
1311:                                    .create(
1312:                                            SVNErrorCode.CLIENT_INVALID_RELOCATION,
1313:                                            "The repository at ''{0}'' has uuid ''{1}'', but the WC has ''{2}''",
1314:                                            new Object[] { validatedURL,
1315:                                                    expectedUUID, validatedUUID });
1316:                            SVNErrorManager.error(err);
1317:                        }
1318:                        return validatedURLs;
1319:                    }
1320:                }
1321:                SVNRepository repos = createRepository(targetURL, false);
1322:                try {
1323:                    SVNURL actualRoot = repos.getRepositoryRoot(true);
1324:                    if (isRoot && !targetURL.equals(actualRoot)) {
1325:                        SVNErrorMessage err = SVNErrorMessage.create(
1326:                                SVNErrorCode.CLIENT_INVALID_RELOCATION,
1327:                                "''{0}'' is not the root of the repository",
1328:                                targetURL);
1329:                        SVNErrorManager.error(err);
1330:                    }
1331:
1332:                    String actualUUID = repos.getRepositoryUUID(true);
1333:                    if (expectedUUID != null
1334:                            && !expectedUUID.equals(actualUUID)) {
1335:                        SVNErrorMessage err = SVNErrorMessage
1336:                                .create(
1337:                                        SVNErrorCode.CLIENT_INVALID_RELOCATION,
1338:                                        "The repository at ''{0}'' has uuid ''{1}'', but the WC has ''{2}''",
1339:                                        new Object[] { targetURL, expectedUUID,
1340:                                                actualUUID });
1341:                        SVNErrorManager.error(err);
1342:                    }
1343:                    validatedURLs.put(targetURL, actualUUID);
1344:                } finally {
1345:                    repos.closeSession();
1346:                }
1347:                return validatedURLs;
1348:            }
1349:
1350:            private Map relocateEntry(SVNEntry entry, String from, String to,
1351:                    Map validatedURLs) throws SVNException {
1352:                if (entry.getRepositoryRoot() != null) {
1353:                    // that is what i do not understand :)
1354:                    String repos = entry.getRepositoryRoot();
1355:                    if (from.length() > repos.length()) {
1356:                        String fromPath = from.substring(repos.length());
1357:                        if (!to.endsWith(fromPath)) {
1358:                            SVNErrorMessage err = SVNErrorMessage
1359:                                    .create(SVNErrorCode.WC_INVALID_RELOCATION,
1360:                                            "Relocate can only change the repository part of an URL");
1361:                            SVNErrorManager.error(err);
1362:                        }
1363:                        from = repos;
1364:                        to = to.substring(0, to.length() - fromPath.length());
1365:                    }
1366:                    if (repos.startsWith(from)) {
1367:                        entry.setRepositoryRoot(to
1368:                                + repos.substring(from.length()));
1369:                        validatedURLs = validateRelocateTargetURL(entry
1370:                                .getRepositoryRootURL(), entry.getUUID(),
1371:                                validatedURLs, true);
1372:                    }
1373:                }
1374:                if (entry.getURL() != null && entry.getURL().startsWith(from)) {
1375:                    entry.setURL(to + entry.getURL().substring(from.length()));
1376:                    if (entry.getUUID() != null && validatedURLs != null) {
1377:                        validatedURLs = validateRelocateTargetURL(entry
1378:                                .getSVNURL(), entry.getUUID(), validatedURLs,
1379:                                false);
1380:                    }
1381:                }
1382:                if (entry.getCopyFromURL() != null
1383:                        && entry.getCopyFromURL().startsWith(from)) {
1384:                    entry.setCopyFromURL(to
1385:                            + entry.getCopyFromURL().substring(from.length()));
1386:                    if (entry.getUUID() != null && validatedURLs != null) {
1387:                        validatedURLs = validateRelocateTargetURL(entry
1388:                                .getCopyFromSVNURL(), entry.getUUID(),
1389:                                validatedURLs, false);
1390:                    }
1391:                }
1392:                return validatedURLs;
1393:            }
1394:
1395:            private Map doRelocate(SVNAdminArea adminArea, String name,
1396:                    String from, String to, boolean recursive, Map validatedURLs)
1397:                    throws SVNException {
1398:                SVNEntry entry = adminArea.getEntry(name, true);
1399:                if (entry == null) {
1400:                    SVNErrorMessage err = SVNErrorMessage
1401:                            .create(SVNErrorCode.ENTRY_NOT_FOUND);
1402:                    SVNErrorManager.error(err);
1403:                }
1404:
1405:                if (entry.isFile()) {
1406:                    relocateEntry(entry, from, to, validatedURLs);
1407:                    SVNPropertiesManager.deleteWCProperties(adminArea, name,
1408:                            false);
1409:                    adminArea.saveEntries(false);
1410:                    return validatedURLs;
1411:                }
1412:
1413:                validatedURLs = relocateEntry(entry, from, to, validatedURLs);
1414:                SVNWCAccess wcAccess = adminArea.getWCAccess();
1415:                for (Iterator entries = adminArea.entries(true); entries
1416:                        .hasNext();) {
1417:                    SVNEntry childEntry = (SVNEntry) entries.next();
1418:                    if (adminArea.getThisDirName().equals(childEntry.getName())) {
1419:                        continue;
1420:                    }
1421:                    if (recursive
1422:                            && childEntry.isDirectory()
1423:                            && (childEntry.isScheduledForAddition() || !childEntry
1424:                                    .isDeleted()) && !childEntry.isAbsent()) {
1425:                        File childDir = adminArea.getFile(childEntry.getName());
1426:                        if (wcAccess.isMissing(childDir)) {
1427:                            continue;
1428:                        }
1429:                        SVNAdminArea childArea = wcAccess.retrieve(childDir);
1430:                        validatedURLs = doRelocate(childArea, childArea
1431:                                .getThisDirName(), from, to, recursive,
1432:                                validatedURLs);
1433:                    }
1434:                    validatedURLs = relocateEntry(childEntry, from, to,
1435:                            validatedURLs);
1436:                    SVNPropertiesManager.deleteWCProperties(adminArea,
1437:                            childEntry.getName(), false);
1438:                }
1439:                SVNPropertiesManager.deleteWCProperties(adminArea, "", false);
1440:                adminArea.saveEntries(false);
1441:                return validatedURLs;
1442:            }
1443:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.