Source Code Cross Referenced for SVNCopyClient.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.ArrayList;
0017:        import java.util.Arrays;
0018:        import java.util.Collection;
0019:        import java.util.Collections;
0020:        import java.util.HashMap;
0021:        import java.util.Iterator;
0022:        import java.util.Map;
0023:        import java.util.TreeMap;
0024:
0025:        import org.tmatesoft.svn.core.SVNCommitInfo;
0026:        import org.tmatesoft.svn.core.SVNErrorCode;
0027:        import org.tmatesoft.svn.core.SVNErrorMessage;
0028:        import org.tmatesoft.svn.core.SVNException;
0029:        import org.tmatesoft.svn.core.SVNNodeKind;
0030:        import org.tmatesoft.svn.core.SVNProperty;
0031:        import org.tmatesoft.svn.core.SVNURL;
0032:        import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
0033:        import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
0034:        import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
0035:        import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
0036:        import org.tmatesoft.svn.core.internal.wc.ISVNCommitPathHandler;
0037:        import org.tmatesoft.svn.core.internal.wc.SVNCancellableOutputStream;
0038:        import org.tmatesoft.svn.core.internal.wc.SVNCommitMediator;
0039:        import org.tmatesoft.svn.core.internal.wc.SVNCommitUtil;
0040:        import org.tmatesoft.svn.core.internal.wc.SVNCommitter;
0041:        import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
0042:        import org.tmatesoft.svn.core.internal.wc.SVNEventFactory;
0043:        import org.tmatesoft.svn.core.internal.wc.SVNFileType;
0044:        import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
0045:        import org.tmatesoft.svn.core.internal.wc.SVNPropertiesManager;
0046:        import org.tmatesoft.svn.core.internal.wc.SVNWCManager;
0047:        import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea;
0048:        import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
0049:        import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
0050:        import org.tmatesoft.svn.core.io.ISVNEditor;
0051:        import org.tmatesoft.svn.core.io.SVNRepository;
0052:
0053:        /**
0054:         * The <b>SVNCopyClient</b> provides methods to perform any kinds of copying and moving that SVN
0055:         * supports - operating on both Working Copies (WC) and URLs.
0056:         * 
0057:         * <p>
0058:         * Copy operations allow a user to copy versioned files and directories with all their 
0059:         * previous history in several ways. 
0060:         * 
0061:         * <p>
0062:         * Supported copy operations are:
0063:         * <ul>
0064:         * <li> Working Copy to Working Copy (WC-to-WC) copying - this operation copies the source
0065:         * Working Copy item to the destination one and schedules the source copy for addition with history.
0066:         * <li> Working Copy to URL (WC-to-URL) copying - this operation commits to the repository (exactly
0067:         * to that repository location that is specified by URL) a copy of the Working Copy item.
0068:         * <li> URL to Working Copy (URL-to-WC) copying - this operation will copy the source item from
0069:         * the repository to the Working Copy item and schedule the source copy for addition with history.
0070:         * <li> URL to URL (URL-to-URL) copying - this is a fully repository-side operation, it commits 
0071:         * a copy of the source item to a specified repository location (within the same repository, of
0072:         * course). 
0073:         * </ul>
0074:         * 
0075:         * <p> 
0076:         * Besides just copying <b>SVNCopyClient</b> also is able to move a versioned item - that is
0077:         * first making a copy of the source item and then scheduling the source item for deletion 
0078:         * when operating on a Working Copy, or right committing the deletion of the source item when 
0079:         * operating immediately on the repository.
0080:         * 
0081:         * <p>
0082:         * Supported move operations are:
0083:         * <ul>
0084:         * <li> Working Copy to Working Copy (WC-to-WC) moving - this operation copies the source
0085:         * Working Copy item to the destination one and schedules the source item for deletion.
0086:         * <li> URL to URL (URL-to-URL) moving - this is a fully repository-side operation, it commits 
0087:         * a copy of the source item to a specified repository location and deletes the source item. 
0088:         * </ul>
0089:         * 
0090:         * <p>
0091:         * Overloaded <b>doCopy()</b> methods of <b>SVNCopyClient</b> are similar to
0092:         * <code>'svn copy'</code> and <code>'svn move'</code> commands of the SVN command line client. 
0093:         * 
0094:         * @version 1.1.1
0095:         * @author  TMate Software Ltd.
0096:         * @see     <a target="_top" href="http://svnkit.com/kb/examples/">Examples</a>
0097:         * 
0098:         */
0099:        public class SVNCopyClient extends SVNBasicClient {
0100:
0101:            private ISVNCommitHandler myCommitHandler;
0102:            private ISVNCommitParameters myCommitParameters;
0103:
0104:            /**
0105:             * Constructs and initializes an <b>SVNCopyClient</b> object
0106:             * with the specified run-time configuration and authentication 
0107:             * drivers.
0108:             * 
0109:             * <p>
0110:             * If <code>options</code> is <span class="javakeyword">null</span>,
0111:             * then this <b>SVNCopyClient</b> will be using a default run-time
0112:             * configuration driver  which takes client-side settings from the 
0113:             * default SVN's run-time configuration area but is not able to
0114:             * change those settings (read more on {@link ISVNOptions} and {@link SVNWCUtil}).  
0115:             * 
0116:             * <p>
0117:             * If <code>authManager</code> is <span class="javakeyword">null</span>,
0118:             * then this <b>SVNCopyClient</b> will be using a default authentication
0119:             * and network layers driver (see {@link SVNWCUtil#createDefaultAuthenticationManager()})
0120:             * which uses server-side settings and auth storage from the 
0121:             * default SVN's run-time configuration area (or system properties
0122:             * if that area is not found).
0123:             * 
0124:             * @param authManager an authentication and network layers driver
0125:             * @param options     a run-time configuration options driver     
0126:             */
0127:            public SVNCopyClient(ISVNAuthenticationManager authManager,
0128:                    ISVNOptions options) {
0129:                super (authManager, options);
0130:            }
0131:
0132:            public SVNCopyClient(ISVNRepositoryPool repositoryPool,
0133:                    ISVNOptions options) {
0134:                super (repositoryPool, options);
0135:            }
0136:
0137:            /**
0138:             * Sets an implementation of <b>ISVNCommitHandler</b> to 
0139:             * the commit handler that will be used during commit operations to handle 
0140:             * commit log messages. The handler will receive a clien's log message and items 
0141:             * (represented as <b>SVNCommitItem</b> objects) that will be 
0142:             * committed. Depending on implementor's aims the initial log message can
0143:             * be modified (or something else) and returned back. 
0144:             * 
0145:             * <p>
0146:             * If using <b>SVNCopyClient</b> without specifying any
0147:             * commit handler then a default one will be used - {@link DefaultSVNCommitHandler}.
0148:             * 
0149:             * @param handler               an implementor's handler that will be used to handle 
0150:             *                              commit log messages
0151:             * @see   #getCommitHandler()
0152:             * @see   SVNCommitItem
0153:             */
0154:            public void setCommitHandler(ISVNCommitHandler handler) {
0155:                myCommitHandler = handler;
0156:            }
0157:
0158:            /**
0159:             * Returns the specified commit handler (if set) being in use or a default one 
0160:             * (<b>DefaultSVNCommitHandler</b>) if no special 
0161:             * implementations of <b>ISVNCommitHandler</b> were 
0162:             * previousely provided.
0163:             *   
0164:             * @return  the commit handler being in use or a default one
0165:             * @see     #setCommitHandler(ISVNCommitHandler)
0166:             * @see     DefaultSVNCommitHandler 
0167:             */
0168:            public ISVNCommitHandler getCommitHandler() {
0169:                if (myCommitHandler == null) {
0170:                    myCommitHandler = new DefaultSVNCommitHandler();
0171:                }
0172:                return myCommitHandler;
0173:            }
0174:
0175:            /**
0176:             * Sets commit parameters to use.
0177:             * 
0178:             * <p>
0179:             * When no parameters are set {@link DefaultSVNCommitParameters default} 
0180:             * ones are used. 
0181:             * 
0182:             * @param parameters commit parameters
0183:             * @see              #getCommitParameters()
0184:             */
0185:            public void setCommitParameters(ISVNCommitParameters parameters) {
0186:                myCommitParameters = parameters;
0187:            }
0188:
0189:            /**
0190:             * Returns commit parameters. 
0191:             * 
0192:             * <p>
0193:             * If no user parameters were previously specified, once creates and 
0194:             * returns {@link DefaultSVNCommitParameters default} ones. 
0195:             * 
0196:             * @return commit parameters
0197:             * @see    #setCommitParameters(ISVNCommitParameters)
0198:             */
0199:            public ISVNCommitParameters getCommitParameters() {
0200:                if (myCommitParameters == null) {
0201:                    myCommitParameters = new DefaultSVNCommitParameters();
0202:                }
0203:                return myCommitParameters;
0204:            }
0205:
0206:            /**
0207:             * Copies/moves a source URL to a destination one immediately committing changes
0208:             * to a repository. Equivalent to <code>doCopy(srcURL, srcRevision, dstURL, isMove, false, commitMessage)</code>.
0209:             * 
0210:             * @param  srcURL         a source repository location URL
0211:             * @param  srcRevision    a revision of <code>srcURL</code>
0212:             * @param  dstURL         a target URL where <code>srcURL</code> is to be
0213:             *                        copied/moved
0214:             * @param  isMove         <span class="javakeyword">true</span> to move the source
0215:             *                        to the target (only URL-to-URL), 
0216:             *                        <span class="javakeyword">false</span> to copy
0217:             * @param  commitMessage  a commit log message
0218:             * @return                information on the committed revision
0219:             * @throws SVNException
0220:             * @see                   #doCopy(SVNURL, SVNRevision, SVNURL, boolean, boolean, String)                       
0221:             */
0222:            public SVNCommitInfo doCopy(SVNURL srcURL, SVNRevision srcRevision,
0223:                    SVNURL dstURL, boolean isMove, String commitMessage)
0224:                    throws SVNException {
0225:                return doCopy(srcURL, srcRevision, dstURL, isMove, false,
0226:                        commitMessage);
0227:            }
0228:
0229:            /**
0230:             * Copies/moves a source URL to a destination one immediately committing changes
0231:             * to a repository. 
0232:             * 
0233:             * <p>
0234:             * If <code>dstURL</code> and <code>srcURL</code> are the same, 
0235:             * <code>failWhenDstExists</code> is <span class="javakeyword">false</span> and 
0236:             * <code>srcURL</code> is a directory then this directory will be copied into itself.
0237:             * 
0238:             * <p> 
0239:             * If <code>dstURL</code> is a directory, <code>dstURL</code> and <code>srcURL</code> are not the same, 
0240:             * <code>failWhenDstExists</code> is <span class="javakeyword">false</span>, <code>dstURL</code> 
0241:             * has not the last path element entry of <code>srcURL</code> then that entry will be copied into 
0242:             * <code>dstURL</code>. 
0243:             * 
0244:             * @param  srcURL            a source repository location URL
0245:             * @param  srcRevision       a revision of <code>srcURL</code>
0246:             * @param  dstURL            a target URL where <code>srcURL</code> is to be
0247:             *                           copied/moved
0248:             * @param  isMove            <span class="javakeyword">true</span> to move the source
0249:             *                           to the target (only URL-to-URL), 
0250:             *                           <span class="javakeyword">false</span> to copy
0251:             * @param failWhenDstExists  <span class="javakeyword">true</span> to force a failure if 
0252:             *                           the destination exists   
0253:             * @param  commitMessage     a commit log message
0254:             * @return                   information on the committed revision
0255:             * @throws SVNException      if one of the following is true:
0256:             *                           <ul>
0257:             *                           <li><code>srcURL</code> and <code>dstURL</code> are not in the
0258:             *                           same repository  
0259:             *                           <li><code>srcURL</code> was not found in <code>srcRevision</code>
0260:             *                           <li><code>dstURL</code> and <code>srcURL</code> are the same and 
0261:             *                           <code>failWhenDstExists</code> is <span class="javakeyword">true</span>
0262:             *                           <li><code>dstURL</code> already exists and <code>failWhenDstExists</code> 
0263:             *                           is <span class="javakeyword">true</span>
0264:             *                           <li><code>dstURL</code> already exists, <code>failWhenDstExists</code> 
0265:             *                           is <span class="javakeyword">false</span>, but <code>dstURL</code> 
0266:             *                           already contains the top path element name of <code>srcURL</code> 
0267:             *                           <li><code>isMove = </code><span class="javakeyword">true</span> and 
0268:             *                           <code>dstURL = srcURL</code>
0269:             *                           </ul>
0270:             */
0271:            public SVNCommitInfo doCopy(SVNURL srcURL, SVNRevision srcRevision,
0272:                    SVNURL dstURL, boolean isMove, boolean failWhenDstExists,
0273:                    String commitMessage) throws SVNException {
0274:                SVNURL topURL = SVNURLUtil.getCommonURLAncestor(srcURL, dstURL);
0275:                if (topURL == null) {
0276:                    SVNErrorMessage err = SVNErrorMessage
0277:                            .create(
0278:                                    SVNErrorCode.UNSUPPORTED_FEATURE,
0279:                                    "Source and dest appear not to be in the same repository (src: ''{0}''; dst: ''{1}'')",
0280:                                    new Object[] { srcURL, dstURL });
0281:                    SVNErrorManager.error(err);
0282:                }
0283:                boolean isResurrect = false;
0284:
0285:                if (dstURL.equals(srcURL)) {
0286:                    topURL = srcURL.removePathTail();
0287:                    isResurrect = true;
0288:                }
0289:
0290:                SVNRepository repository = createRepository(topURL, true);
0291:                if (!dstURL.equals(repository.getRepositoryRoot(true))
0292:                        && srcURL.getPath().startsWith(dstURL.getPath() + "/")) {
0293:                    isResurrect = true;
0294:                    topURL = topURL.removePathTail();
0295:                    repository = createRepository(topURL, true);
0296:                }
0297:
0298:                // substring one more char, because path always starts with /, and we need relative path.
0299:                String srcPath = srcURL.equals(topURL) ? "" : srcURL
0300:                        .getURIEncodedPath().substring(
0301:                                topURL.getURIEncodedPath().length() + 1);
0302:                srcPath = SVNEncodingUtil.uriDecode(srcPath);
0303:                String dstPath = dstURL.equals(topURL) ? "" : dstURL
0304:                        .getURIEncodedPath().substring(
0305:                                topURL.getURIEncodedPath().length() + 1);
0306:                dstPath = SVNEncodingUtil.uriDecode(dstPath);
0307:
0308:                if ("".equals(srcPath) && isMove) {
0309:                    SVNErrorMessage err = SVNErrorMessage.create(
0310:                            SVNErrorCode.UNSUPPORTED_FEATURE,
0311:                            "Cannot move URL ''{0}'' into itself", srcURL);
0312:                    SVNErrorManager.error(err);
0313:                }
0314:
0315:                long srcRevNumber = getRevisionNumber(srcRevision, repository,
0316:                        null);
0317:                long latestRevision = repository.getLatestRevision();
0318:
0319:                if (srcRevNumber < 0) {
0320:                    srcRevNumber = latestRevision;
0321:                }
0322:                SVNNodeKind srcKind = repository.checkPath(srcPath,
0323:                        srcRevNumber);
0324:                if (srcKind == SVNNodeKind.NONE) {
0325:                    SVNErrorMessage err = SVNErrorMessage.create(
0326:                            SVNErrorCode.FS_NOT_FOUND,
0327:                            "Path ''{0}'' does not exist in revision {1}",
0328:                            new Object[] { srcURL, new Long(srcRevNumber) });
0329:                    SVNErrorManager.error(err);
0330:                }
0331:                SVNNodeKind dstKind = repository.checkPath(dstPath,
0332:                        latestRevision);
0333:                if (dstKind == SVNNodeKind.DIR) {
0334:                    if (failWhenDstExists) {
0335:                        SVNErrorMessage err = SVNErrorMessage.create(
0336:                                SVNErrorCode.FS_ALREADY_EXISTS,
0337:                                "Path ''{0}'' already exists", dstPath);
0338:                        SVNErrorManager.error(err);
0339:                    }
0340:                    dstPath = SVNPathUtil.append(dstPath, SVNPathUtil
0341:                            .tail(srcURL.getPath()));
0342:                    if (repository.checkPath(dstPath, latestRevision) != SVNNodeKind.NONE) {
0343:                        SVNErrorMessage err = SVNErrorMessage.create(
0344:                                SVNErrorCode.FS_ALREADY_EXISTS,
0345:                                "Path ''{0}'' already exists", dstPath);
0346:                        SVNErrorManager.error(err);
0347:                    }
0348:                } else if (dstKind == SVNNodeKind.FILE) {
0349:                    SVNErrorMessage err = SVNErrorMessage.create(
0350:                            SVNErrorCode.FS_ALREADY_EXISTS,
0351:                            "Path ''{0}'' already exists", dstPath);
0352:                    SVNErrorManager.error(err);
0353:                }
0354:                Collection commitItems = new ArrayList(2);
0355:                commitItems.add(new SVNCommitItem(null, dstURL, srcURL,
0356:                        srcKind,
0357:                        SVNRevision.UNDEFINED/*create(srcRevNumber)*/,
0358:                        SVNRevision.create(srcRevNumber), true, false, false,
0359:                        false, true, false));
0360:                if (isMove) {
0361:                    commitItems.add(new SVNCommitItem(null, srcURL, null,
0362:                            srcKind, SVNRevision.create(srcRevNumber),
0363:                            SVNRevision.UNDEFINED, false, true, false, false,
0364:                            false, false));
0365:                }
0366:                commitMessage = getCommitHandler()
0367:                        .getCommitMessage(
0368:                                commitMessage,
0369:                                (SVNCommitItem[]) commitItems
0370:                                        .toArray(new SVNCommitItem[commitItems
0371:                                                .size()]));
0372:                if (commitMessage == null) {
0373:                    return SVNCommitInfo.NULL;
0374:                }
0375:
0376:                commitMessage = SVNCommitClient
0377:                        .validateCommitMessage(commitMessage);
0378:                ISVNEditor commitEditor = repository.getCommitEditor(
0379:                        commitMessage, null, false, null);
0380:                ISVNCommitPathHandler committer = new CopyCommitPathHandler(
0381:                        srcPath, srcRevNumber, srcKind, dstPath, isMove,
0382:                        isResurrect);
0383:                Collection paths = isMove ? Arrays.asList(new String[] {
0384:                        srcPath, dstPath }) : Collections
0385:                        .singletonList(dstPath);
0386:
0387:                SVNCommitInfo result = null;
0388:                try {
0389:                    SVNCommitUtil.driveCommitEditor(committer, paths,
0390:                            commitEditor, -1);
0391:                    result = commitEditor.closeEdit();
0392:                } catch (SVNException e) {
0393:                    try {
0394:                        commitEditor.abortEdit();
0395:                    } catch (SVNException inner) {
0396:                        //
0397:                    }
0398:                    SVNErrorMessage nestedErr = e.getErrorMessage();
0399:                    SVNErrorMessage err = SVNErrorMessage.create(nestedErr
0400:                            .getErrorCode(), "Commit failed (details follow):");
0401:                    SVNErrorManager.error(err, e.getErrorMessage());
0402:                }
0403:                if (result != null && result.getNewRevision() >= 0) {
0404:                    dispatchEvent(SVNEventFactory.createCommitCompletedEvent(
0405:                            null, result.getNewRevision()),
0406:                            ISVNEventHandler.UNKNOWN);
0407:                }
0408:                return result != null ? result : SVNCommitInfo.NULL;
0409:            }
0410:
0411:            /**
0412:             * Copies a source Working Copy path (or its repository location URL) to a destination 
0413:             * URL immediately committing changes to a repository.
0414:             * 
0415:             * <p>
0416:             * Equivalent to <code>doCopy(srcPath, srcRevision, dstURL, false, commitMessage)</code>. 
0417:             * 
0418:             * @param  srcPath        a source Working Copy path
0419:             * @param  srcRevision    a revision of <code>srcPath</code>
0420:             * @param  dstURL         a target URL where <code>srcPath</code> is to be
0421:             *                        copied
0422:             * @param  commitMessage  a commit log message
0423:             * @return                information on the committed revision
0424:             * @throws SVNException   if one of the following is true:
0425:             *                        <ul>
0426:             *                        <li><code>srcPath</code> is not under version control
0427:             *                        <li><code>srcPath</code> has no URL
0428:             *                        <li>the repository location of <code>srcPath</code> was not 
0429:             *                        found in <code>srcRevision</code>
0430:             *                        <li><code>dstURL</code> already exists
0431:             *                        </ul>
0432:             * @see                   #doCopy(File, SVNRevision, SVNURL, boolean, String)
0433:             */
0434:            public SVNCommitInfo doCopy(File srcPath, SVNRevision srcRevision,
0435:                    SVNURL dstURL, String commitMessage) throws SVNException {
0436:                return doCopy(srcPath, srcRevision, dstURL, false,
0437:                        commitMessage);
0438:            }
0439:
0440:            /**
0441:             * Copies a source Working Copy path (or its repository location URL) to a destination 
0442:             * URL immediately committing changes to a repository.
0443:             * 
0444:             * <p>
0445:             * If <code>srcRevision</code> is not {@link SVNRevision#WORKING} then the repository
0446:             * location URL of <code>srcPath</code> is copied to <code>dstURL</code>. Otherwise
0447:             * <code>srcPath</code> itself.
0448:             * 
0449:             * <p>
0450:             * <code>failWhenDstExists</code> behaves 
0451:             * like in {@link #doCopy(SVNURL, SVNRevision, SVNURL, boolean, boolean, String)}. 
0452:             * 
0453:             * @param  srcPath          a source Working Copy path
0454:             * @param  srcRevision      a revision of <code>srcPath</code>
0455:             * @param  dstURL           a target URL where <code>srcPath</code> is to be
0456:             *                          copied
0457:             * @param failWhenDstExists <span class="javakeyword">true</span> to force a failure if 
0458:             *                          the destination exists   
0459:             * @param  commitMessage    a commit log message
0460:             * @return                  information on the committed revision
0461:             * @throws SVNException     if one of the following is true:
0462:             *                          <ul>
0463:             *                          <li><code>srcPath</code> is not under version control
0464:             *                          <li><code>srcPath</code> has no URL
0465:             *                          <li>the repository location of <code>srcPath</code> was not 
0466:             *                          found in <code>srcRevision</code>
0467:             *                          <li><code>dstURL</code> already exists and 
0468:             *                          <code>failWhenDstExists</code> is <span class="javakeyword">true</span>
0469:             *                          </ul>
0470:             */
0471:            public SVNCommitInfo doCopy(File srcPath, SVNRevision srcRevision,
0472:                    SVNURL dstURL, boolean failWhenDstExists,
0473:                    String commitMessage) throws SVNException {
0474:                // may be url->url.
0475:                srcPath = new File(SVNPathUtil.validateFilePath(srcPath
0476:                        .getAbsolutePath()));
0477:                if (srcRevision.isValid() && srcRevision != SVNRevision.WORKING) {
0478:                    SVNWCAccess wcAccess = createWCAccess();
0479:                    wcAccess.probeOpen(srcPath, false, 0);
0480:                    SVNEntry srcEntry = wcAccess.getEntry(srcPath, false);
0481:                    wcAccess.close();
0482:
0483:                    if (srcEntry == null) {
0484:                        SVNErrorMessage err = SVNErrorMessage
0485:                                .create(SVNErrorCode.UNVERSIONED_RESOURCE,
0486:                                        "''{0}'' is not under version control",
0487:                                        srcPath);
0488:                        SVNErrorManager.error(err);
0489:                    }
0490:                    if (srcEntry.getURL() == null) {
0491:                        SVNErrorMessage err = SVNErrorMessage
0492:                                .create(
0493:                                        SVNErrorCode.ENTRY_MISSING_URL,
0494:                                        "''{0}'' does not seem to have a URL associated with it",
0495:                                        srcPath);
0496:                        SVNErrorManager.error(err);
0497:                    }
0498:                    return doCopy(srcEntry.getSVNURL(), srcRevision, dstURL,
0499:                            false, failWhenDstExists, commitMessage);
0500:                }
0501:                SVNWCAccess wcAccess = createWCAccess();
0502:                SVNAdminArea adminArea = wcAccess.probeOpen(srcPath, false,
0503:                        SVNWCAccess.INFINITE_DEPTH);
0504:                wcAccess.setAnchor(adminArea.getRoot());
0505:
0506:                SVNURL dstAnchorURL = dstURL.removePathTail();
0507:                String dstTarget = SVNPathUtil.tail(dstURL.toString());
0508:                dstTarget = SVNEncodingUtil.uriDecode(dstTarget);
0509:
0510:                SVNRepository repository = createRepository(dstAnchorURL, true);
0511:                SVNNodeKind dstKind = repository.checkPath(dstTarget, -1);
0512:                if (dstKind == SVNNodeKind.DIR) {
0513:                    if (failWhenDstExists) {
0514:                        SVNErrorMessage err = SVNErrorMessage.create(
0515:                                SVNErrorCode.FS_ALREADY_EXISTS,
0516:                                "Path ''{0}'' already exists", dstURL);
0517:                        SVNErrorManager.error(err);
0518:                    }
0519:                    dstURL = dstURL.appendPath(srcPath.getName(), false);
0520:                } else if (dstKind == SVNNodeKind.FILE) {
0521:                    SVNErrorMessage err = SVNErrorMessage.create(
0522:                            SVNErrorCode.FS_ALREADY_EXISTS,
0523:                            "File ''{0}'' already exists", dstURL);
0524:                    SVNErrorManager.error(err);
0525:                }
0526:
0527:                SVNCommitItem[] items = new SVNCommitItem[] { new SVNCommitItem(
0528:                        null, dstURL, null, SVNNodeKind.NONE,
0529:                        SVNRevision.UNDEFINED, SVNRevision.UNDEFINED, true,
0530:                        false, false, false, true, false) };
0531:                items[0].setWCAccess(adminArea.getWCAccess());
0532:                commitMessage = getCommitHandler().getCommitMessage(
0533:                        commitMessage, items);
0534:                if (commitMessage == null) {
0535:                    return SVNCommitInfo.NULL;
0536:                }
0537:
0538:                SVNAdminArea dirArea = null;
0539:                if (SVNFileType.getType(srcPath) == SVNFileType.DIRECTORY) {
0540:                    dirArea = wcAccess.retrieve(srcPath);
0541:                } else {
0542:                    dirArea = adminArea;
0543:                }
0544:
0545:                Collection tmpFiles = null;
0546:                SVNCommitInfo info = null;
0547:                ISVNEditor commitEditor = null;
0548:                try {
0549:                    Map commitables = new TreeMap();
0550:                    SVNEntry entry = wcAccess.getEntry(srcPath, false);
0551:                    if (entry == null) {
0552:                        SVNErrorMessage err = SVNErrorMessage
0553:                                .create(SVNErrorCode.ENTRY_NOT_FOUND,
0554:                                        "''{0}'' is not under version control",
0555:                                        srcPath);
0556:                        SVNErrorManager.error(err);
0557:                        return SVNCommitInfo.NULL;
0558:                    }
0559:
0560:                    SVNCommitUtil.harvestCommitables(commitables, dirArea,
0561:                            srcPath, null, entry, dstURL.toString(), entry
0562:                                    .getURL(), true, false, false, null, true,
0563:                            false, getCommitParameters());
0564:                    items = (SVNCommitItem[]) commitables.values().toArray(
0565:                            new SVNCommitItem[commitables.values().size()]);
0566:                    for (int i = 0; i < items.length; i++) {
0567:                        items[i].setWCAccess(wcAccess);
0568:                    }
0569:
0570:                    commitables = new TreeMap();
0571:                    dstURL = SVNURL.parseURIEncoded(SVNCommitUtil
0572:                            .translateCommitables(items, commitables));
0573:
0574:                    repository = createRepository(dstURL, true);
0575:                    SVNCommitMediator mediator = new SVNCommitMediator(
0576:                            commitables);
0577:                    tmpFiles = mediator.getTmpFiles();
0578:
0579:                    commitMessage = SVNCommitClient
0580:                            .validateCommitMessage(commitMessage);
0581:                    SVNURL root = repository.getRepositoryRoot(true);
0582:                    commitEditor = repository.getCommitEditor(commitMessage,
0583:                            null, false, mediator);
0584:                    info = SVNCommitter.commit(tmpFiles, commitables, root
0585:                            .getPath(), commitEditor);
0586:                    commitEditor = null;
0587:                } finally {
0588:                    if (tmpFiles != null) {
0589:                        for (Iterator files = tmpFiles.iterator(); files
0590:                                .hasNext();) {
0591:                            File file = (File) files.next();
0592:                            file.delete();
0593:                        }
0594:                    }
0595:                    if (commitEditor != null && info == null) {
0596:                        commitEditor.abortEdit();
0597:                    }
0598:                    if (wcAccess != null) {
0599:                        wcAccess.close();
0600:                    }
0601:                }
0602:                if (info != null && info.getNewRevision() >= 0) {
0603:                    dispatchEvent(SVNEventFactory.createCommitCompletedEvent(
0604:                            null, info.getNewRevision()),
0605:                            ISVNEventHandler.UNKNOWN);
0606:                }
0607:                return info != null ? info : SVNCommitInfo.NULL;
0608:            }
0609:
0610:            /**
0611:             * Copies a source URL to a destination Working Copy path. 
0612:             * 
0613:             * <p>
0614:             * <code>dstPath</code> will be automatically scheduled for addition with history.
0615:             * 
0616:             * @param  srcURL         a source URL
0617:             * @param  srcRevision    a revision of <code>srcURL</code>
0618:             * @param  dstPath        a destination WC path
0619:             * @return                the revision number of a source
0620:             * @throws SVNException   if one of the following is true:
0621:             *                        <ul>
0622:             *                        <li><code>srcURL</code> was not found in <code>srcRevision</code>
0623:             *                        <li><code>dstPath</code> already exists
0624:             *                        <li><code>dstPath</code> appears in <code>srcURL</code>
0625:             *                        <li><code>dstPath</code> and <code>srcURL</code> are from
0626:             *                        different repositories
0627:             *                        <li><code>dstPath</code> is under version control but missing
0628:             *                        </ul>
0629:             */
0630:            public long doCopy(SVNURL srcURL, SVNRevision srcRevision,
0631:                    File dstPath) throws SVNException {
0632:                SVNRepository repository = createRepository(srcURL, true);
0633:                if (!srcRevision.isValid()) {
0634:                    srcRevision = SVNRevision.HEAD;
0635:                }
0636:                long srcRevisionNumber = getRevisionNumber(srcRevision,
0637:                        repository, null);
0638:                SVNNodeKind srcKind = repository.checkPath("",
0639:                        srcRevisionNumber);
0640:
0641:                if (srcKind == SVNNodeKind.NONE) {
0642:                    if (SVNRevision.isValidRevisionNumber(srcRevisionNumber)) {
0643:                        SVNErrorMessage err = SVNErrorMessage.create(
0644:                                SVNErrorCode.FS_NOT_FOUND,
0645:                                "Path ''{0}'' not found in revision {1}",
0646:                                new Object[] { srcURL,
0647:                                        new Long(srcRevisionNumber) });
0648:                        SVNErrorManager.error(err);
0649:                    } else {
0650:                        SVNErrorMessage err = SVNErrorMessage.create(
0651:                                SVNErrorCode.FS_NOT_FOUND,
0652:                                "Path ''{0}'' not found in head revision",
0653:                                srcURL);
0654:                        SVNErrorManager.error(err);
0655:                    }
0656:                }
0657:
0658:                SVNFileType dstFileType = SVNFileType.getType(dstPath);
0659:                if (dstFileType == SVNFileType.DIRECTORY) {
0660:                    dstPath = new File(dstPath, SVNPathUtil.tail(srcURL
0661:                            .getPath()));
0662:                } else if (dstFileType != SVNFileType.NONE) {
0663:                    SVNErrorMessage err = SVNErrorMessage.create(
0664:                            SVNErrorCode.ENTRY_EXISTS,
0665:                            "File ''{0}'' already exists", dstPath);
0666:                    SVNErrorManager.error(err);
0667:                }
0668:                dstFileType = SVNFileType.getType(dstPath);
0669:                if (dstFileType != SVNFileType.NONE) {
0670:                    SVNErrorMessage err = SVNErrorMessage.create(
0671:                            SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0672:                            "''{0}'' is in the way", dstPath);
0673:                    SVNErrorManager.error(err);
0674:                }
0675:
0676:                SVNWCAccess dstAccess = createWCAccess();
0677:                long revision = -1;
0678:                try {
0679:                    SVNAdminArea adminArea = dstAccess.probeOpen(dstPath, true,
0680:                            0);
0681:
0682:                    SVNEntry dstEntry = dstAccess.getEntry(dstPath, false);
0683:                    if (dstEntry != null && !dstEntry.isDirectory()
0684:                            && !dstEntry.isScheduledForDeletion()) {
0685:                        SVNErrorMessage err = SVNErrorMessage
0686:                                .create(
0687:                                        SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0688:                                        "Entry for ''{0}'' exists (though the working copy file is missing)",
0689:                                        dstPath);
0690:                        SVNErrorManager.error(err);
0691:                    }
0692:
0693:                    boolean sameRepositories;
0694:
0695:                    String srcUUID = null;
0696:                    String dstUUID = null;
0697:
0698:                    try {
0699:                        srcUUID = repository.getRepositoryUUID(true);
0700:                        dstUUID = getUUIDFromPath(dstAccess, dstPath
0701:                                .getParentFile());
0702:                    } catch (SVNException e) {
0703:                        if (e.getErrorMessage().getErrorCode() == SVNErrorCode.RA_NO_REPOS_UUID) {
0704:                            srcUUID = dstUUID = null;
0705:                        } else {
0706:                            throw e;
0707:                        }
0708:                    }
0709:                    if (dstUUID == null || srcUUID == null) {
0710:                        sameRepositories = false;
0711:                    } else {
0712:                        sameRepositories = srcUUID.equals(dstUUID);
0713:                    }
0714:
0715:                    if (srcKind == SVNNodeKind.DIR) {
0716:                        // do checkout.
0717:                        SVNUpdateClient updateClient = new SVNUpdateClient(
0718:                                getRepositoryPool(), getOptions());
0719:                        updateClient.setEventHandler(getEventDispatcher());
0720:
0721:                        revision = updateClient.doCheckout(srcURL, dstPath,
0722:                                srcRevision, srcRevision, true);
0723:
0724:                        if (srcRevision == SVNRevision.HEAD && sameRepositories) {
0725:                            SVNAdminArea dstArea = dstAccess.open(dstPath,
0726:                                    true, SVNWCAccess.INFINITE_DEPTH);
0727:                            SVNEntry dstRootEntry = dstArea.getEntry(dstArea
0728:                                    .getThisDirName(), false);
0729:                            revision = dstRootEntry.getRevision();
0730:                        }
0731:                        if (sameRepositories) {
0732:                            SVNWCManager.add(dstPath, adminArea, srcURL,
0733:                                    revision);
0734:                        } else {
0735:                            SVNErrorMessage err = SVNErrorMessage
0736:                                    .create(
0737:                                            SVNErrorCode.UNSUPPORTED_FEATURE,
0738:                                            "Source URL ''{0}'' is from foreign repository; leaving it as a disjoint WC",
0739:                                            srcURL);
0740:                            SVNErrorManager.error(err);
0741:                        }
0742:                    } else if (srcKind == SVNNodeKind.FILE) {
0743:                        Map properties = new HashMap();
0744:                        File tmpFile = null;
0745:
0746:                        File baseTmpFile = adminArea.getBaseFile(dstPath
0747:                                .getName(), true);
0748:                        tmpFile = SVNFileUtil.createUniqueFile(baseTmpFile
0749:                                .getParentFile(), ".copy", ".tmp");
0750:                        OutputStream os = null;
0751:
0752:                        long realRevision = -1;
0753:                        try {
0754:                            os = SVNFileUtil.openFileForWriting(tmpFile);
0755:                            realRevision = repository.getFile("",
0756:                                    srcRevisionNumber, properties,
0757:                                    new SVNCancellableOutputStream(os, this ));
0758:                        } finally {
0759:                            SVNFileUtil.closeFile(os);
0760:                        }
0761:                        if (!SVNRevision
0762:                                .isValidRevisionNumber(srcRevisionNumber)) {
0763:                            srcRevisionNumber = realRevision;
0764:                        }
0765:
0766:                        SVNWCManager.addRepositoryFile(adminArea, dstPath
0767:                                .getName(), null, tmpFile, null, properties,
0768:                                sameRepositories ? srcURL.toString() : null,
0769:                                sameRepositories ? srcRevisionNumber : -1);
0770:
0771:                        dispatchEvent(SVNEventFactory.createAddedEvent(null,
0772:                                adminArea, dstAccess.getEntry(dstPath, false)));
0773:                        revision = srcRevisionNumber;
0774:                        sleepForTimeStamp();
0775:                    }
0776:                } finally {
0777:                    dstAccess.close();
0778:                }
0779:                return revision;
0780:            }
0781:
0782:            private String getUUIDFromPath(SVNWCAccess wcAccess, File path)
0783:                    throws SVNException {
0784:                SVNEntry entry = wcAccess.getEntry(path, true);
0785:                if (entry == null) {
0786:                    SVNErrorMessage err = SVNErrorMessage.create(
0787:                            SVNErrorCode.ENTRY_NOT_FOUND,
0788:                            "Can''t find entry for ''{0}''", path);
0789:                    SVNErrorManager.error(err);
0790:                }
0791:
0792:                String uuid = null;
0793:                if (entry.getUUID() != null) {
0794:                    uuid = entry.getUUID();
0795:                } else if (entry.getURL() != null) {
0796:                    SVNRepository repos = createRepository(entry.getSVNURL(),
0797:                            false);
0798:                    try {
0799:                        uuid = repos.getRepositoryUUID(true);
0800:                    } finally {
0801:                        repos.closeSession();
0802:                    }
0803:                } else {
0804:                    if (wcAccess.isWCRoot(path)) {
0805:                        SVNErrorMessage err = SVNErrorMessage.create(
0806:                                SVNErrorCode.ENTRY_MISSING_URL,
0807:                                "''{0}'' has no URL", path);
0808:                        SVNErrorManager.error(err);
0809:                    }
0810:                    uuid = getUUIDFromPath(wcAccess, path.getParentFile());
0811:                }
0812:                return uuid;
0813:            }
0814:
0815:            /**
0816:             * Copies/moves a source Working Copy path to a destination Working Copy path.
0817:             * 
0818:             * <p>
0819:             * If <code>srcRevision</code> is not {@link SVNRevision#WORKING} and 
0820:             * <code>isMove = </code><span class="javakeyword">false</span>, then the repository
0821:             * location URL of <code>srcPath</code> is copied to <code>dstPath</code>. Otherwise
0822:             * <code>srcPath</code> itself.
0823:             * 
0824:             * <p>
0825:             * <code>dstPath</code> will be automatically scheduled for addition with history.
0826:             * 
0827:             * @param  srcPath        a source WC path
0828:             * @param  srcRevision    a revision of <code>srcPath</code>
0829:             * @param  dstPath        a destination WC path 
0830:             * @param  force          <span class="javakeyword">true</span> to force the operation
0831:             *                        to run
0832:             * @param  isMove         <span class="javakeyword">true</span> to move the source
0833:             *                        to the target (only WC-to-WC), 
0834:             *                        <span class="javakeyword">false</span> to copy
0835:             * @throws SVNException   if one of the following is true:
0836:             *                        <ul>
0837:             *                        <li><code>dstPath</code> already exists and is in the way
0838:             *                        containing an item with the same name as the source
0839:             *                        <li><code>srcPath</code> is not under version control
0840:             *                        <li><code>srcPath</code> does not exist
0841:             *                        <li><code>srcPath</code> has no URL
0842:             *                        <li><code>dstPath</code> is a child of <code>srcPath</code>
0843:             *                        <li><code>dstPath</code> is scheduled for deletion
0844:             *                        <li><code>isMove = </code><span class="javakeyword">true</span> and 
0845:             *                        <code>dstURL = srcURL</code>
0846:             *                        </ul>
0847:             */
0848:            public void doCopy(File srcPath, SVNRevision srcRevision,
0849:                    File dstPath, boolean force, boolean isMove)
0850:                    throws SVNException {
0851:                srcPath = new File(SVNPathUtil.validateFilePath(srcPath
0852:                        .getAbsolutePath())).getAbsoluteFile();
0853:                dstPath = new File(SVNPathUtil.validateFilePath(dstPath
0854:                        .getAbsolutePath())).getAbsoluteFile();
0855:                if (srcRevision.isValid() && srcRevision != SVNRevision.WORKING
0856:                        && !isMove) {
0857:                    // url->wc copy
0858:                    SVNWCAccess wcAccess = createWCAccess();
0859:                    SVNURL srcURL = null;
0860:                    try {
0861:                        wcAccess.probeOpen(srcPath, false, 0);
0862:                        SVNEntry srcEntry = wcAccess.getEntry(srcPath, false);
0863:                        if (srcEntry == null) {
0864:                            SVNErrorMessage err = SVNErrorMessage.create(
0865:                                    SVNErrorCode.ENTRY_NOT_FOUND,
0866:                                    "''{0}'' is not under version control",
0867:                                    srcPath);
0868:                            SVNErrorManager.error(err);
0869:                        }
0870:                        if (srcEntry.getURL() == null) {
0871:                            SVNErrorMessage err = SVNErrorMessage.create(
0872:                                    SVNErrorCode.ENTRY_MISSING_URL,
0873:                                    "''{0}'' has no URL", srcPath);
0874:                            SVNErrorManager.error(err);
0875:                        }
0876:                        srcURL = srcEntry.getSVNURL();
0877:                    } finally {
0878:                        wcAccess.close();
0879:                    }
0880:                    doCopy(srcURL, srcRevision, dstPath);
0881:                    return;
0882:                }
0883:                // 1. can't copy src to its own child
0884:                if (SVNPathUtil.isChildOf(srcPath, dstPath)
0885:                        || srcPath.equals(dstPath)) {
0886:                    SVNErrorMessage err = SVNErrorMessage.create(
0887:                            SVNErrorCode.UNSUPPORTED_FEATURE,
0888:                            "Cannot copy ''{0}'' into its own child ''{1}''",
0889:                            new Object[] { srcPath, dstPath });
0890:                    SVNErrorManager.error(err);
0891:                }
0892:                // 2. can't move path into itself
0893:                if (isMove && srcPath.equals(dstPath)) {
0894:                    SVNErrorMessage err = SVNErrorMessage.create(
0895:                            SVNErrorCode.UNSUPPORTED_FEATURE,
0896:                            "Cannot move ''{0}'' into itself", srcPath);
0897:                    SVNErrorManager.error(err);
0898:                }
0899:                // 3. src should exist
0900:                SVNFileType srcType = SVNFileType.getType(srcPath);
0901:                if (srcType == SVNFileType.NONE) {
0902:                    SVNErrorMessage err = SVNErrorMessage.create(
0903:                            SVNErrorCode.NODE_UNKNOWN_KIND,
0904:                            "Path ''{0}'' does not exist", srcPath);
0905:                    SVNErrorManager.error(err);
0906:                }
0907:                // 4. if dst exists - use its child
0908:                SVNFileType dstType = SVNFileType.getType(dstPath);
0909:                if (dstType == SVNFileType.DIRECTORY) {
0910:                    dstPath = new File(dstPath, srcPath.getName());
0911:                    dstType = SVNFileType.getType(dstPath);
0912:                    if (dstType != SVNFileType.NONE) {
0913:                        SVNErrorMessage err = SVNErrorMessage.create(
0914:                                SVNErrorCode.WC_OBSTRUCTED_UPDATE,
0915:                                "''{0}'' already exists and is in the way",
0916:                                dstPath);
0917:                        SVNErrorManager.error(err);
0918:                    }
0919:                } else if (dstType != SVNFileType.NONE) {
0920:                    SVNErrorMessage err = SVNErrorMessage.create(
0921:                            SVNErrorCode.ENTRY_EXISTS,
0922:                            "File ''{0}'' already exists", dstPath);
0923:                    SVNErrorManager.error(err);
0924:                }
0925:
0926:                SVNWCAccess wcAccess = createWCAccess();
0927:                SVNAdminArea adminArea = null;
0928:                File srcParent = srcPath.getParentFile();
0929:                File dstParent = dstPath.getParentFile();
0930:
0931:                try {
0932:                    SVNAdminArea srcParentArea = null;
0933:                    if (isMove) {
0934:                        srcParentArea = wcAccess
0935:                                .open(
0936:                                        srcParent,
0937:                                        true,
0938:                                        srcType == SVNFileType.DIRECTORY ? SVNWCAccess.INFINITE_DEPTH
0939:                                                : 0);
0940:                        if (srcParent.equals(dstParent)) {
0941:                            adminArea = srcParentArea;
0942:                        } else {
0943:                            if (srcType == SVNFileType.DIRECTORY
0944:                                    && SVNPathUtil.isChildOf(srcParent,
0945:                                            dstParent)) {
0946:                                adminArea = wcAccess.retrieve(dstParent);
0947:                            } else {
0948:                                adminArea = wcAccess.open(dstParent, true, 0);
0949:                            }
0950:                        }
0951:
0952:                        if (!force) {
0953:                            try {
0954:                                SVNWCManager.canDelete(srcPath, getOptions(),
0955:                                        this );
0956:                            } catch (SVNException svne) {
0957:                                SVNErrorMessage err = svne
0958:                                        .getErrorMessage()
0959:                                        .wrap(
0960:                                                "Move will not be attempted unless forced");
0961:                                SVNErrorManager.error(err, svne);
0962:                            }
0963:                        }
0964:                    } else {
0965:                        adminArea = wcAccess.open(dstParent, true, 0);
0966:                    }
0967:
0968:                    SVNWCAccess copyAccess = createWCAccess();
0969:                    try {
0970:                        SVNAdminArea srcArea = copyAccess.probeOpen(srcPath,
0971:                                false, SVNWCAccess.INFINITE_DEPTH);
0972:                        SVNEntry dstEntry = adminArea.getEntry(adminArea
0973:                                .getThisDirName(), false);
0974:                        if (dstEntry == null) {
0975:                            SVNErrorMessage err = SVNErrorMessage.create(
0976:                                    SVNErrorCode.ENTRY_NOT_FOUND,
0977:                                    "''{0}'' is not under version control",
0978:                                    adminArea.getRoot());
0979:                            SVNErrorManager.error(err);
0980:                        }
0981:
0982:                        SVNEntry srcEntry = copyAccess.getEntry(srcPath, false);
0983:                        if (srcEntry == null) {
0984:                            SVNErrorMessage err = SVNErrorMessage.create(
0985:                                    SVNErrorCode.ENTRY_NOT_FOUND,
0986:                                    "''{0}'' is not under version control",
0987:                                    srcPath);
0988:                            SVNErrorManager.error(err);
0989:                        }
0990:
0991:                        if (srcEntry.getRepositoryRoot() != null
0992:                                && dstEntry.getRepositoryRoot() != null
0993:                                && !srcEntry.getRepositoryRoot().equals(
0994:                                        dstEntry.getRepositoryRoot())) {
0995:                            SVNErrorMessage err = SVNErrorMessage
0996:                                    .create(
0997:                                            SVNErrorCode.WC_INVALID_SCHEDULE,
0998:                                            "Cannot copy to ''{0}'', as it is not from repository ''{1}''; it is from ''{2}''",
0999:                                            new Object[] {
1000:                                                    adminArea.getRoot(),
1001:                                                    srcEntry
1002:                                                            .getRepositoryRoot(),
1003:                                                    dstEntry
1004:                                                            .getRepositoryRoot() });
1005:                            SVNErrorManager.error(err);
1006:                        }
1007:
1008:                        if (dstEntry.isScheduledForDeletion()) {
1009:                            SVNErrorMessage err = SVNErrorMessage
1010:                                    .create(
1011:                                            SVNErrorCode.WC_INVALID_SCHEDULE,
1012:                                            "Cannot copy to ''{0}'' as it is scheduled for deletion",
1013:                                            adminArea.getRoot());
1014:                            SVNErrorManager.error(err);
1015:                        }
1016:
1017:                        if (srcType == SVNFileType.FILE) {
1018:                            copyFile(adminArea, srcArea, srcPath, dstPath
1019:                                    .getName());
1020:                        } else if (srcType == SVNFileType.DIRECTORY) {
1021:                            copyDir(adminArea, srcArea, srcPath, dstPath
1022:                                    .getName());
1023:                        }
1024:                    } finally {
1025:                        copyAccess.close();
1026:                    }
1027:                    if (isMove) {
1028:                        SVNWCManager.delete(srcParentArea.getWCAccess(),
1029:                                srcParentArea, srcPath, true, false);
1030:                    }
1031:                } finally {
1032:                    wcAccess.close();
1033:                }
1034:
1035:            }
1036:
1037:            private void copyFile(SVNAdminArea dstParent, SVNAdminArea srcArea,
1038:                    File srcPath, String dstName) throws SVNException {
1039:                SVNWCAccess wcAccess = dstParent.getWCAccess();
1040:                File dstPath = dstParent.getFile(dstName);
1041:
1042:                if (SVNFileType.getType(dstPath) != SVNFileType.NONE) {
1043:                    SVNErrorMessage err = SVNErrorMessage
1044:                            .create(SVNErrorCode.ENTRY_EXISTS,
1045:                                    "''{0}'' already exists and is in the way",
1046:                                    dstPath);
1047:                    SVNErrorManager.error(err);
1048:                }
1049:
1050:                SVNEntry dstEntry = wcAccess.getEntry(dstPath, false);
1051:                if (dstEntry != null && dstEntry.isFile()) {
1052:                    if (!dstEntry.isScheduledForDeletion()) {
1053:                        SVNErrorMessage err = SVNErrorMessage.create(
1054:                                SVNErrorCode.ENTRY_EXISTS,
1055:                                "There is already a versioned item ''{0}''",
1056:                                dstPath);
1057:                        SVNErrorManager.error(err);
1058:                    }
1059:                }
1060:                SVNEntry srcEntry = srcArea.getWCAccess().getEntry(srcPath,
1061:                        false);
1062:                if (srcEntry == null) {
1063:                    SVNErrorMessage err = SVNErrorMessage
1064:                            .create(
1065:                                    SVNErrorCode.UNVERSIONED_RESOURCE,
1066:                                    "Cannot copy or move ''{0}'': it''s not under version control",
1067:                                    srcPath);
1068:                    SVNErrorManager.error(err);
1069:                }
1070:                if (srcEntry.isScheduledForAddition()
1071:                        || srcEntry.getURL() == null || srcEntry.isCopied()) {
1072:                    SVNErrorMessage err = SVNErrorMessage
1073:                            .create(
1074:                                    SVNErrorCode.UNSUPPORTED_FEATURE,
1075:                                    "Cannot copy or move ''{0}'': it''s not in repository yet; try committing first",
1076:                                    srcPath);
1077:                    SVNErrorManager.error(err);
1078:                }
1079:                File textBase = srcArea.getBaseFile(srcPath.getName(), false);
1080:                File tmpTextBase = dstParent.getBaseFile(dstName, true);
1081:                String copyFromURL = srcEntry.getURL();
1082:                long copyFromRevision = srcEntry.getRevision();
1083:
1084:                Map baseProperties = srcArea.getBaseProperties(
1085:                        srcEntry.getName()).asMap();
1086:                Map properties = srcArea.getProperties(srcEntry.getName())
1087:                        .asMap();
1088:
1089:                SVNFileUtil.copyFile(textBase, tmpTextBase, false);
1090:                File tmpFile = SVNFileUtil.createUniqueFile(
1091:                        dstParent.getRoot(), ".copy", ".tmp");
1092:                SVNFileUtil.copy(srcArea.getFile(srcEntry.getName()), tmpFile,
1093:                        false, false);
1094:
1095:                SVNWCManager.addRepositoryFile(dstParent, dstName, tmpFile,
1096:                        tmpTextBase, baseProperties, properties, copyFromURL,
1097:                        copyFromRevision);
1098:
1099:                SVNEvent event = SVNEventFactory.createAddedEvent(dstParent,
1100:                        dstName, SVNNodeKind.FILE, null);
1101:                dstParent.getWCAccess().handleEvent(event);
1102:
1103:            }
1104:
1105:            private void copyDir(SVNAdminArea dstParent, SVNAdminArea srcArea,
1106:                    File srcPath, String dstName) throws SVNException {
1107:                SVNEntry srcEntry = srcArea.getWCAccess().getEntry(srcPath,
1108:                        false);
1109:                if (srcEntry == null) {
1110:                    SVNErrorMessage err = SVNErrorMessage.create(
1111:                            SVNErrorCode.ENTRY_NOT_FOUND,
1112:                            "'{0}'' is not under version control", srcPath);
1113:                    SVNErrorManager.error(err);
1114:                }
1115:                if (srcEntry.isScheduledForAddition()
1116:                        || srcEntry.getURL() == null || srcEntry.isCopied()) {
1117:                    SVNErrorMessage err = SVNErrorMessage
1118:                            .create(
1119:                                    SVNErrorCode.UNSUPPORTED_FEATURE,
1120:                                    "Cannot copy or move ''{0}'': it''s not in repository yet; try committing first",
1121:                                    srcPath);
1122:                    SVNErrorManager.error(err);
1123:                }
1124:
1125:                File dstPath = dstParent.getFile(dstName);
1126:                SVNFileUtil.copyDirectory(srcPath, dstPath, true, srcArea
1127:                        .getWCAccess());
1128:                SVNWCClient wcClient = new SVNWCClient(
1129:                        (ISVNAuthenticationManager) null, (ISVNOptions) null);
1130:                wcClient.doCleanup(dstPath);
1131:
1132:                SVNWCAccess tmpAccess = SVNWCAccess.newInstance(null);
1133:                try {
1134:                    SVNAdminArea tmpDir = tmpAccess.open(dstPath, true,
1135:                            SVNWCAccess.INFINITE_DEPTH);
1136:                    postCopyCleanup(tmpDir);
1137:                } finally {
1138:                    tmpAccess.close();
1139:                }
1140:                SVNWCManager.add(dstPath, dstParent, srcEntry.getSVNURL(),
1141:                        srcEntry.getRevision());
1142:            }
1143:
1144:            static void postCopyCleanup(SVNAdminArea dir) throws SVNException {
1145:                SVNPropertiesManager.deleteWCProperties(dir, null, false);
1146:                SVNFileUtil.setHidden(dir.getAdminDirectory(), true);
1147:
1148:                for (Iterator entries = dir.entries(true); entries.hasNext();) {
1149:                    SVNEntry entry = (SVNEntry) entries.next();
1150:                    boolean deleted = entry.isDeleted();
1151:                    SVNNodeKind kind = entry.getKind();
1152:
1153:                    if (entry.isDeleted()) {
1154:                        entry.setSchedule(SVNProperty.SCHEDULE_DELETE);
1155:                        entry.setDeleted(false);
1156:                        if (entry.isDirectory()) {
1157:                            entry.setKind(SVNNodeKind.FILE);
1158:                        }
1159:                    }
1160:                    if (entry.getLockToken() != null) {
1161:                        entry.setLockToken(null);
1162:                        entry.setLockOwner(null);
1163:                        entry.setLockCreationDate(null);
1164:                    }
1165:                    if (!deleted && kind == SVNNodeKind.DIR
1166:                            && !dir.getThisDirName().equals(entry.getName())) {
1167:                        SVNAdminArea childDir = dir.getWCAccess().retrieve(
1168:                                dir.getFile(entry.getName()));
1169:                        postCopyCleanup(childDir);
1170:                    }
1171:                }
1172:                dir.saveEntries(false);
1173:            }
1174:
1175:            private static class CopyCommitPathHandler implements 
1176:                    ISVNCommitPathHandler {
1177:
1178:                private String mySrcPath;
1179:                private String myDstPath;
1180:                private long mySrcRev;
1181:                private boolean myIsMove;
1182:                private boolean myIsResurrect;
1183:                private SVNNodeKind mySrcKind;
1184:
1185:                public CopyCommitPathHandler(String srcPath, long srcRev,
1186:                        SVNNodeKind srcKind, String dstPath, boolean isMove,
1187:                        boolean isRessurect) {
1188:                    mySrcPath = srcPath;
1189:                    myDstPath = dstPath;
1190:                    mySrcRev = srcRev;
1191:                    myIsMove = isMove;
1192:                    mySrcKind = srcKind;
1193:                    myIsResurrect = isRessurect;
1194:                }
1195:
1196:                public boolean handleCommitPath(String commitPath,
1197:                        ISVNEditor commitEditor) throws SVNException {
1198:                    boolean doAdd = false;
1199:                    boolean doDelete = false;
1200:                    if (myIsResurrect) {
1201:                        if (!myIsMove) {
1202:                            doAdd = true;
1203:                        }
1204:                    } else {
1205:                        if (myIsMove) {
1206:                            if (commitPath.equals(mySrcPath)) {
1207:                                doDelete = true;
1208:                            } else {
1209:                                doAdd = true;
1210:                            }
1211:                        } else {
1212:                            doAdd = true;
1213:                        }
1214:                    }
1215:                    if (doDelete) {
1216:                        commitEditor.deleteEntry(mySrcPath, -1);
1217:                    }
1218:                    boolean closeDir = false;
1219:                    if (doAdd) {
1220:                        if (mySrcKind == SVNNodeKind.DIR) {
1221:                            commitEditor.addDir(myDstPath, mySrcPath, mySrcRev);
1222:                            closeDir = true;
1223:                        } else {
1224:                            commitEditor
1225:                                    .addFile(myDstPath, mySrcPath, mySrcRev);
1226:                            commitEditor.closeFile(myDstPath, null);
1227:                        }
1228:                    }
1229:                    return closeDir;
1230:                }
1231:            }
1232:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.