Source Code Cross Referenced for SvnUtils.java in  » IDE-Netbeans » subversion » org » netbeans » modules » subversion » util » 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 » IDE Netbeans » subversion » org.netbeans.modules.subversion.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.subversion.util;
0043:
0044:        import org.netbeans.modules.subversion.client.SvnClient;
0045:        import org.openide.*;
0046:        import org.openide.nodes.Node;
0047:        import org.openide.windows.TopComponent;
0048:        import org.openide.util.Lookup;
0049:        import org.openide.filesystems.FileUtil;
0050:        import org.openide.filesystems.FileObject;
0051:        import org.netbeans.api.project.*;
0052:        import org.netbeans.api.queries.SharabilityQuery;
0053:        import org.netbeans.modules.subversion.FileStatusCache;
0054:        import org.netbeans.modules.subversion.Subversion;
0055:        import org.netbeans.modules.subversion.FileInformation;
0056:        import java.io.*;
0057:        import java.util.*;
0058:        import java.text.ParseException;
0059:        import java.util.logging.Level;
0060:        import java.util.regex.Pattern;
0061:        import java.util.regex.PatternSyntaxException;
0062:        import org.netbeans.modules.subversion.SvnModuleConfig;
0063:        import org.netbeans.modules.subversion.client.PropertiesClient;
0064:        import org.netbeans.modules.subversion.client.SvnClientExceptionHandler;
0065:        import org.netbeans.modules.subversion.options.AnnotationExpression;
0066:        import org.netbeans.modules.versioning.spi.VCSContext;
0067:        import org.netbeans.modules.versioning.util.Utils;
0068:        import org.openide.util.NbBundle;
0069:        import org.tigris.subversion.svnclientadapter.*;
0070:        import org.tigris.subversion.svnclientadapter.utils.SVNUrlUtils;
0071:
0072:        /**
0073:         * Subversion-specific utilities.
0074:         * TODO: PETR Move generic methods to versioncontrol module
0075:         *
0076:         * @author Maros Sandor
0077:         */
0078:        public class SvnUtils {
0079:
0080:            private static final Pattern metadataPattern = Pattern
0081:                    .compile(".*\\" + File.separatorChar + "(\\.|_)svn(\\"
0082:                            + File.separatorChar + ".*|$)");
0083:
0084:            private static final FileFilter svnFileFilter = new FileFilter() {
0085:                public boolean accept(File pathname) {
0086:                    if (Subversion.getInstance().isAdministrative(pathname))
0087:                        return false;
0088:                    return SharabilityQuery.getSharability(pathname) != SharabilityQuery.NOT_SHARABLE;
0089:                }
0090:            };
0091:
0092:            /**
0093:             * Semantics is similar to {@link org.openide.windows.TopComponent#getActivatedNodes()} except that this
0094:             * method returns File objects instead od Nodes. Every node is examined for Files it represents. File and Folder
0095:             * nodes represent their underlying files or folders. Project nodes are represented by their source groups. Other
0096:             * logical nodes must provide FileObjects in their Lookup.
0097:             *
0098:             * @return File [] array of activated files
0099:             * @param nodes or null (then taken from windowsystem, it may be wrong on editor tabs #66700).
0100:             */
0101:            public static Context getCurrentContext(Node[] nodes) {
0102:                if (nodes == null) {
0103:                    nodes = TopComponent.getRegistry().getActivatedNodes();
0104:                }
0105:                VCSContext ctx = VCSContext.forNodes(nodes);
0106:                return new Context(new ArrayList(ctx
0107:                        .computeFiles(svnFileFilter)), new ArrayList(ctx
0108:                        .getRootFiles()), new ArrayList(ctx.getExclusions()));
0109:            }
0110:
0111:            /**
0112:             * Semantics is similar to {@link org.openide.windows.TopComponent#getActivatedNodes()} except that this
0113:             * method returns File objects instead od Nodes. Every node is examined for Files it represents. File and Folder
0114:             * nodes represent their underlying files or folders. Project nodes are represented by their source groups. Other
0115:             * logical nodes must provide FileObjects in their Lookup.
0116:             *
0117:             * @param nodes null (then taken from windowsystem, it may be wrong on editor tabs #66700).
0118:             * @param includingFileStatus if any activated file does not have this CVS status, an empty array is returned
0119:             * @param includingFolderStatus if any activated folder does not have this CVS status, an empty array is returned
0120:             * @return File [] array of activated files, or an empty array if any of examined files/folders does not have given status
0121:             */
0122:            public static Context getCurrentContext(Node[] nodes,
0123:                    int includingFileStatus, int includingFolderStatus) {
0124:                Context context = getCurrentContext(nodes);
0125:                FileStatusCache cache = Subversion.getInstance()
0126:                        .getStatusCache();
0127:                File[] files = context.getRootFiles();
0128:                for (int i = 0; i < files.length; i++) {
0129:                    File file = files[i];
0130:                    FileInformation fi = cache.getStatus(file);
0131:                    if (file.isDirectory()) {
0132:                        if ((fi.getStatus() & includingFolderStatus) == 0)
0133:                            return Context.Empty;
0134:                    } else {
0135:                        if ((fi.getStatus() & includingFileStatus) == 0)
0136:                            return Context.Empty;
0137:                    }
0138:                }
0139:                return context;
0140:            }
0141:
0142:            /**
0143:             * @return <code>true</code> if
0144:             * <ul>
0145:             *  <li> the node contains a project in its lookup and
0146:             *  <li> the project contains at least one CVS versioned source group
0147:             * </ul>
0148:             * otherwise <code>false</code>.
0149:             */
0150:            public static boolean isVersionedProject(Node node) {
0151:                Lookup lookup = node.getLookup();
0152:                Project project = (Project) lookup.lookup(Project.class);
0153:                return isVersionedProject(project);
0154:            }
0155:
0156:            /**
0157:             * @return <code>true</code> if
0158:             * <ul>
0159:             *  <li> the project != null and
0160:             *  <li> the project contains at least one CVS versioned source group
0161:             * </ul>
0162:             * otherwise <code>false</code>.
0163:             */
0164:            public static boolean isVersionedProject(Project project) {
0165:                if (project != null) {
0166:                    FileStatusCache cache = Subversion.getInstance()
0167:                            .getStatusCache();
0168:                    Sources sources = ProjectUtils.getSources(project);
0169:                    SourceGroup[] sourceGroups = sources
0170:                            .getSourceGroups(Sources.TYPE_GENERIC);
0171:                    for (int j = 0; j < sourceGroups.length; j++) {
0172:                        SourceGroup sourceGroup = sourceGroups[j];
0173:                        File f = FileUtil.toFile(sourceGroup.getRootFolder());
0174:                        //if (f != null) { XXX fallback if experimntal should not work
0175:                        //                    File probe = new File (f, ".svn");
0176:                        //                    File probe2 = new File (f, "_svn");
0177:                        //                    if (probe.isDirectory() || probe2.isDirectory()) {
0178:                        //                        return true;
0179:                        //                    }
0180:                        //                }
0181:                        if ((cache.getStatus(f).getStatus() & FileInformation.STATUS_MANAGED) != 0)
0182:                            return true; // XXX experimental
0183:                    }
0184:                }
0185:                return false;
0186:            }
0187:
0188:            /**
0189:             * Determines all files and folders that belong to a given project and adds them to the supplied Collection.
0190:             *
0191:             * @param filteredFiles destination collection of Files
0192:             * @param project project to examine
0193:             */
0194:            public static void addProjectFiles(Collection<File> filteredFiles,
0195:                    Collection<File> rootFiles,
0196:                    Collection<File> rootFilesExclusions, Project project) {
0197:                FileStatusCache cache = Subversion.getInstance()
0198:                        .getStatusCache();
0199:                Sources sources = ProjectUtils.getSources(project);
0200:                SourceGroup[] sourceGroups = sources
0201:                        .getSourceGroups(Sources.TYPE_GENERIC);
0202:                for (int j = 0; j < sourceGroups.length; j++) {
0203:                    SourceGroup sourceGroup = sourceGroups[j];
0204:                    FileObject srcRootFo = sourceGroup.getRootFolder();
0205:                    File rootFile = FileUtil.toFile(srcRootFo);
0206:                    if ((cache.getStatus(rootFile).getStatus() & FileInformation.STATUS_MANAGED) == 0)
0207:                        continue;
0208:                    rootFiles.add(rootFile);
0209:                    boolean containsSubprojects = false;
0210:                    FileObject[] rootChildren = srcRootFo.getChildren();
0211:                    Set<File> projectFiles = new HashSet<File>(
0212:                            rootChildren.length);
0213:                    for (int i = 0; i < rootChildren.length; i++) {
0214:                        FileObject rootChildFo = rootChildren[i];
0215:                        if (Subversion.getInstance().isAdministrative(
0216:                                rootChildFo.getNameExt()))
0217:                            continue;
0218:                        File child = FileUtil.toFile(rootChildFo);
0219:                        if (sourceGroup.contains(rootChildFo)) {
0220:                            // TODO: #60516 deep scan is required here but not performed due to performace reasons
0221:                            projectFiles.add(child);
0222:                        } else {
0223:                            int status = cache.getStatus(child).getStatus();
0224:                            if (status != FileInformation.STATUS_NOTVERSIONED_EXCLUDED) {
0225:                                rootFilesExclusions.add(child);
0226:                                containsSubprojects = true;
0227:                            }
0228:                        }
0229:                    }
0230:                    if (containsSubprojects) {
0231:                        filteredFiles.addAll(projectFiles);
0232:                    } else {
0233:                        filteredFiles.add(rootFile);
0234:                    }
0235:                }
0236:            }
0237:
0238:            /**
0239:             * May take a long time for many projects, consider making the call from worker threads.
0240:             *
0241:             * @param projects projects to examine
0242:             * @return Context context that defines list of supplied projects
0243:             */
0244:            public static Context getProjectsContext(Project[] projects) {
0245:                List<File> filtered = new ArrayList<File>();
0246:                List<File> roots = new ArrayList<File>();
0247:                List<File> exclusions = new ArrayList<File>();
0248:                for (int i = 0; i < projects.length; i++) {
0249:                    addProjectFiles(filtered, roots, exclusions, projects[i]);
0250:                }
0251:                return new Context(filtered, roots, exclusions);
0252:            }
0253:
0254:            public static File[] toFileArray(Collection<FileObject> fileObjects) {
0255:                Set<File> files = new HashSet<File>(
0256:                        fileObjects.size() * 4 / 3 + 1);
0257:                for (Iterator<FileObject> i = fileObjects.iterator(); i
0258:                        .hasNext();) {
0259:                    files.add(FileUtil.toFile(i.next()));
0260:                }
0261:                files.remove(null);
0262:                return files.toArray(new File[files.size()]);
0263:            }
0264:
0265:            /**
0266:             * Tests parent/child relationship of files.
0267:             *
0268:             * @param parent file to be parent of the second parameter
0269:             * @param file file to be a child of the first parameter
0270:             * @return true if the second parameter represents the same file as the first parameter OR is its descendant (child)
0271:             */
0272:            public static boolean isParentOrEqual(File parent, File file) {
0273:                for (; file != null; file = file.getParentFile()) {
0274:                    if (file.equals(parent))
0275:                        return true;
0276:                }
0277:                return false;
0278:            }
0279:
0280:            /**
0281:             * Computes previous revision or <code>null</code>
0282:             * for initial.
0283:             *
0284:             * @param revision num.dot revision or <code>null</code>
0285:             */
0286:            public static String previousRevision(String revision) {
0287:                return revision == null ? null : Long.toString(Long
0288:                        .parseLong(revision) - 1);
0289:            }
0290:
0291:            /**
0292:             * Compute relative path to repository root.
0293:             * For not yet versioned files guess the URL
0294:             * from parent context.
0295:             *
0296:             * <p>I/O intensive avoid calling it frnm AWT.
0297:             *
0298:             * @return the repository url or null for unknown
0299:             */
0300:            public static String getRelativePath(File file)
0301:                    throws SVNClientException {
0302:                String repositoryPath = null;
0303:
0304:                List<String> path = new ArrayList<String>();
0305:                SVNUrl repositoryURL = null;
0306:                boolean fileIsManaged = false;
0307:                while (Subversion.getInstance().isManaged(file)) {
0308:                    fileIsManaged = true;
0309:
0310:                    ISVNInfo info = null;
0311:                    try {
0312:                        SvnClient client = Subversion.getInstance().getClient(
0313:                                false);
0314:                        info = client.getInfoFromWorkingCopy(file);
0315:                    } catch (SVNClientException ex) {
0316:                        if (SvnClientExceptionHandler.isUnversionedResource(ex
0317:                                .getMessage()) == false) {
0318:                            SvnClientExceptionHandler.notifyException(ex,
0319:                                    false, false);
0320:                        }
0321:                    }
0322:
0323:                    if (info != null && info.getUrl() != null) {
0324:                        SVNUrl fileURL = decode(info.getUrl());
0325:                        repositoryURL = info.getRepository();
0326:
0327:                        if (fileURL != null && repositoryURL != null) {
0328:                            String fileLink = fileURL.toString();
0329:                            String repositoryLink = repositoryURL.toString();
0330:                            repositoryPath = fileLink.substring(repositoryLink
0331:                                    .length());
0332:
0333:                            Iterator it = path.iterator();
0334:                            StringBuffer sb = new StringBuffer();
0335:                            while (it.hasNext()) {
0336:                                String segment = (String) it.next();
0337:                                sb.append("/"); // NOI18N
0338:                                sb.append(segment);
0339:                            }
0340:                            repositoryPath += sb.toString();
0341:                            break;
0342:                        }
0343:                    }
0344:
0345:                    path.add(0, file.getName());
0346:                    file = file.getParentFile();
0347:
0348:                }
0349:                if (repositoryURL == null & fileIsManaged) {
0350:                    // The file is managed but we haven't found the repository URL in it's metadata - 
0351:                    // this looks like the WC was created with a client < 1.3.0. I wouldn't mind for myself and
0352:                    // get the URL from the server, it's just that it could be quite a performance killer.
0353:                    // XXX and now i'm just currious how we will handle this if there will be some javahl or 
0354:                    // pure java client suport -> without dispatching to our metadata parser
0355:                    throw new SVNClientException(NbBundle.getMessage(
0356:                            SvnUtils.class, "MSG_too_old_WC"));
0357:                }
0358:                return repositoryPath;
0359:            }
0360:
0361:            /**
0362:             * Compute relative path to repository root.
0363:             * For not yet versioned files guess the URL
0364:             * from parent context.
0365:             *
0366:             * <p>I/O intensive avoid calling it frnm AWT.
0367:             *
0368:             * @return the repository url or null for unknown
0369:             * XXX we need this until we get a local implementation for client.getInfoFromWorkingCopy(file);
0370:             */
0371:            public static String getRelativePath(SVNUrl repositoryURL, File file)
0372:                    throws SVNClientException {
0373:                String repositoryPath = null;
0374:
0375:                SvnClient client;
0376:                try {
0377:                    client = Subversion.getInstance().getClient(false);
0378:                } catch (SVNClientException ex) {
0379:                    SvnClientExceptionHandler.notifyException(ex, false, false);
0380:                    return null;
0381:                }
0382:
0383:                List<String> path = new ArrayList<String>();
0384:                boolean fileIsManaged = false;
0385:                while (Subversion.getInstance().isManaged(file)) {
0386:                    fileIsManaged = true;
0387:
0388:                    ISVNStatus status = null;
0389:                    try {
0390:                        status = client.getSingleStatus(file);
0391:                    } catch (SVNClientException ex) {
0392:                        if (SvnClientExceptionHandler.isUnversionedResource(ex
0393:                                .getMessage()) == false) {
0394:                            SvnClientExceptionHandler.notifyException(ex,
0395:                                    false, false);
0396:                        }
0397:                    }
0398:
0399:                    if (status != null && status.getUrl() != null) {
0400:                        SVNUrl fileURL = status.getUrl();
0401:
0402:                        if (fileURL != null && repositoryURL != null) {
0403:                            fileURL = decode(fileURL);
0404:                            String fileLink = fileURL.toString();
0405:                            String repositoryLink = repositoryURL.toString();
0406:                            repositoryPath = fileLink.substring(repositoryLink
0407:                                    .length());
0408:
0409:                            Iterator it = path.iterator();
0410:                            StringBuffer sb = new StringBuffer();
0411:                            while (it.hasNext()) {
0412:                                String segment = (String) it.next();
0413:                                sb.append("/"); // NOI18N
0414:                                sb.append(segment);
0415:                            }
0416:                            repositoryPath += sb.toString();
0417:                            break;
0418:                        }
0419:                    }
0420:
0421:                    path.add(0, file.getName());
0422:                    file = file.getParentFile();
0423:
0424:                }
0425:                if (repositoryURL == null & fileIsManaged) {
0426:                    // The file is managed but we haven't found the repository URL in it's metadata - 
0427:                    // this looks like the WC was created with a client < 1.3.0. I wouldn't mind for myself and
0428:                    // get the URL from the server, it's just that it could be quite a performance killer.
0429:                    throw new SVNClientException(NbBundle.getMessage(
0430:                            SvnUtils.class, "MSG_too_old_WC"));
0431:                }
0432:                return repositoryPath.startsWith("/") ? repositoryPath
0433:                        .substring(1) : repositoryPath;
0434:            }
0435:
0436:            /**
0437:             * Returns the repository root for the given file.
0438:             * For not yet versioned files guess the URL
0439:             * from parent context.
0440:             *
0441:             * <p>I/O intensive avoid calling it frnm AWT.
0442:             *
0443:             * @return the repository url or null for unknown
0444:             */
0445:            public static SVNUrl getRepositoryRootUrl(File file)
0446:                    throws SVNClientException {
0447:                SvnClient client;
0448:                try {
0449:                    client = Subversion.getInstance().getClient(false);
0450:                } catch (SVNClientException ex) {
0451:                    SvnClientExceptionHandler.notifyException(ex, false, false);
0452:                    return null;
0453:                }
0454:
0455:                SVNUrl repositoryURL = null;
0456:                boolean fileIsManaged = false;
0457:                while (Subversion.getInstance().isManaged(file)) {
0458:                    fileIsManaged = true;
0459:                    ISVNInfo info = null;
0460:                    try {
0461:                        info = client.getInfoFromWorkingCopy(file);
0462:                    } catch (SVNClientException ex) {
0463:                        if (SvnClientExceptionHandler.isUnversionedResource(ex
0464:                                .getMessage()) == false) {
0465:                            SvnClientExceptionHandler.notifyException(ex,
0466:                                    false, false);
0467:                        }
0468:                    }
0469:
0470:                    if (info != null && info.getUrl() != null) {
0471:                        repositoryURL = decode(info.getRepository());
0472:                        if (repositoryURL != null) {
0473:                            break;
0474:                        }
0475:                    }
0476:
0477:                    // path.add(0, file.getName());
0478:                    file = file.getParentFile();
0479:
0480:                }
0481:                if (repositoryURL == null & fileIsManaged) {
0482:                    // The file is managed but we haven't found the repository URL in it's metadata - 
0483:                    // this looks like the WC was created with a client < 1.3.0. I wouldn't mind for myself and
0484:                    // get the URL from the server, it's just that it could be quite a performance killer.
0485:                    throw new SVNClientException(NbBundle.getMessage(
0486:                            SvnUtils.class, "MSG_too_old_WC"));
0487:                }
0488:                return repositoryURL;
0489:            }
0490:
0491:            /**
0492:             * Returns the repository URL for the given file.
0493:             * For not yet versioned files guess the URL
0494:             * from parent context.
0495:             *
0496:             * <p>I/O intensive avoid calling it frnm AWT.
0497:             *
0498:             * @return the repository url or null for unknown
0499:             */
0500:            public static SVNUrl getRepositoryUrl(File file)
0501:                    throws SVNClientException {
0502:
0503:                StringBuffer path = new StringBuffer();
0504:                SVNUrl fileURL = null;
0505:                SvnClient client = null;
0506:                try {
0507:                    client = Subversion.getInstance().getClient(false);
0508:                } catch (SVNClientException ex) {
0509:                    SvnClientExceptionHandler.notifyException(ex, false, false);
0510:                    return null;
0511:                }
0512:                boolean fileIsManaged = false;
0513:                while (Subversion.getInstance().isManaged(file)) {
0514:                    fileIsManaged = true;
0515:
0516:                    try {
0517:                        // it works with 1.3 workdirs and our .svn parser
0518:                        ISVNStatus status = getSingleStatus(client, file);
0519:                        if (status != null) {
0520:                            fileURL = decode(status.getUrl());
0521:                            if (fileURL != null) {
0522:                                break;
0523:                            }
0524:                        }
0525:                    } catch (SVNClientException ex) {
0526:                        if (SvnClientExceptionHandler.isUnversionedResource(ex
0527:                                .getMessage()) == false) {
0528:                            SvnClientExceptionHandler.notifyException(ex,
0529:                                    false, false);
0530:                        }
0531:                    }
0532:
0533:                    // slower fallback
0534:
0535:                    ISVNInfo info = null;
0536:                    try {
0537:                        info = client.getInfoFromWorkingCopy(file);
0538:                    } catch (SVNClientException ex) {
0539:                        if (SvnClientExceptionHandler.isUnversionedResource(ex
0540:                                .getMessage()) == false) {
0541:                            SvnClientExceptionHandler.notifyException(ex,
0542:                                    false, false);
0543:                        }
0544:                    }
0545:
0546:                    if (info != null) {
0547:                        fileURL = decode(info.getUrl());
0548:
0549:                        if (fileURL != null) {
0550:                            break;
0551:                        }
0552:                    }
0553:
0554:                    path.insert(0, file.getName()).insert(0, "/");
0555:                    file = file.getParentFile();
0556:
0557:                }
0558:                if (fileURL == null & fileIsManaged) {
0559:                    // The file is managed but we haven't found the URL in it's metadata - 
0560:                    // this looks like the WC was created with a client < 1.3.0. I wouldn't mind for myself and
0561:                    // get the URL from the server, it's just that it could be quite a performance killer.
0562:                    throw new SVNClientException(NbBundle.getMessage(
0563:                            SvnUtils.class, "MSG_too_old_WC"));
0564:                }
0565:                if (path.length() > 0)
0566:                    fileURL = fileURL.appendPath(path.toString());
0567:                return fileURL;
0568:            }
0569:
0570:            private static ISVNStatus getSingleStatus(SvnClient client,
0571:                    File file) throws SVNClientException {
0572:                return client.getSingleStatus(file);
0573:            }
0574:
0575:            /**
0576:             * Decodes svn URI by decoding %XX escape sequences.
0577:             * 
0578:             * @param url url to decode
0579:             * @return decoded url
0580:             */
0581:            private static SVNUrl decode(SVNUrl url) {
0582:                if (url == null)
0583:                    return null;
0584:                String s = url.toString();
0585:                StringBuffer sb = new StringBuffer(s.length());
0586:
0587:                boolean inQuery = false;
0588:                for (int i = 0; i < s.length(); i++) {
0589:                    char c = s.charAt(i);
0590:                    if (c == '?') {
0591:                        inQuery = true;
0592:                    } else if (c == '+' && inQuery) {
0593:                        sb.append(' ');
0594:                    } else if (isEncodedByte(c, s, i)) {
0595:                        List<Byte> byteList = new ArrayList<Byte>();
0596:                        do {
0597:                            byteList.add((byte) Integer.parseInt(s.substring(
0598:                                    i + 1, i + 3), 16));
0599:                            i += 3;
0600:                            c = s.charAt(i);
0601:                        } while (isEncodedByte(c, s, i));
0602:
0603:                        if (byteList.size() > 0) {
0604:                            byte[] bytes = new byte[byteList.size()];
0605:                            for (int ib = 0; ib < byteList.size(); ib++) {
0606:                                bytes[ib] = byteList.get(ib);
0607:                            }
0608:                            try {
0609:                                sb.append(new String(bytes, "UTF8"));
0610:                            } catch (Exception e) {
0611:                                Subversion.LOG.log(Level.INFO, null, e); // oops
0612:                            }
0613:                            i--;
0614:                        }
0615:                    } else {
0616:                        sb.append(c);
0617:                    }
0618:                }
0619:                try {
0620:                    return new SVNUrl(sb.toString());
0621:                } catch (java.net.MalformedURLException e) {
0622:                    throw new RuntimeException(e);
0623:                }
0624:            }
0625:
0626:            private static boolean isEncodedByte(char c, String s, int i) {
0627:                return c == '%' && i + 2 < s.length()
0628:                        && isHexDigit(s.charAt(i + 1))
0629:                        && isHexDigit(s.charAt(i + 2));
0630:            }
0631:
0632:            private static boolean isHexDigit(char c) {
0633:                return c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
0634:                        && c <= 'f';
0635:            }
0636:
0637:            /*
0638:             * Determines a versioned file's repository path
0639:             *
0640:             * @param file versioned file
0641:             * @return file's path in repository
0642:             */
0643:            public static String getRepositoryPath(File file)
0644:                    throws SVNClientException {
0645:                SVNUrl url = getRepositoryUrl(file);
0646:                SVNUrl rootUrl = getRepositoryRootUrl(file);
0647:                return SVNUrlUtils.getRelativePath(rootUrl, url, true);
0648:            }
0649:
0650:            /**
0651:             * @return true if the buffer is almost certainly binary.
0652:             * Note: Non-ASCII based encoding encoded text is binary,
0653:             * newlines cannot be reliably detected.
0654:             */
0655:            public static boolean isBinary(byte[] buffer) {
0656:                for (int i = 0; i < buffer.length; i++) {
0657:                    int ch = buffer[i];
0658:                    if (ch < 32 && ch != '\t' && ch != '\n' && ch != '\r') {
0659:                        return true;
0660:                    }
0661:                }
0662:                return false;
0663:            }
0664:
0665:            /**
0666:             * Compares two {@link FileInformation} objects by importance of statuses they represent.
0667:             */
0668:            public static class ByImportanceComparator<T> implements 
0669:                    Comparator<FileInformation> {
0670:                public int compare(FileInformation i1, FileInformation i2) {
0671:                    return getComparableStatus(i1.getStatus())
0672:                            - getComparableStatus(i2.getStatus());
0673:                }
0674:            }
0675:
0676:            /**
0677:             * Normalize flat files, Subversion treats folder as normal file
0678:             * so it's necessary explicitly list direct descendants to
0679:             * get classical flat behaviour.
0680:             *
0681:             * <p> E.g. revert on package node means:
0682:             * <ul>
0683:             *   <li>revert package folder properties AND
0684:             *   <li>revert all modified (including deleted) files in the folder
0685:             * </ul>
0686:             *
0687:             * @return files with given status and direct descendants with given status.
0688:             */
0689:            public static File[] flatten(File[] files, int status) {
0690:                LinkedList<File> ret = new LinkedList<File>();
0691:
0692:                FileStatusCache cache = Subversion.getInstance()
0693:                        .getStatusCache();
0694:                for (int i = 0; i < files.length; i++) {
0695:                    File dir = files[i];
0696:                    FileInformation info = cache.getStatus(dir);
0697:                    if ((status & info.getStatus()) != 0) {
0698:                        ret.add(dir);
0699:                    }
0700:                    File[] entries = cache.listFiles(dir); // comparing to dir.listFiles() lists already deleted too
0701:                    for (int e = 0; e < entries.length; e++) {
0702:                        File entry = entries[e];
0703:                        info = cache.getStatus(entry);
0704:                        if ((status & info.getStatus()) != 0) {
0705:                            ret.add(entry);
0706:                        }
0707:                    }
0708:                }
0709:
0710:                return ret.toArray(new File[ret.size()]);
0711:            }
0712:
0713:            /**
0714:             * Utility method that returns all non-excluded modified files that are
0715:             * under given roots (folders) and have one of specified statuses.
0716:             *
0717:             * @param context context to search
0718:             * @param includeStatus bit mask of file statuses to include in result
0719:             * @return File [] array of Files having specified status
0720:             */
0721:            public static File[] getModifiedFiles(Context context,
0722:                    int includeStatus) {
0723:                File[] all = Subversion.getInstance().getStatusCache()
0724:                        .listFiles(context, includeStatus);
0725:                List<File> files = new ArrayList<File>();
0726:                for (int i = 0; i < all.length; i++) {
0727:                    File file = all[i];
0728:                    String path = file.getAbsolutePath();
0729:                    if (SvnModuleConfig.getDefault().isExcludedFromCommit(path) == false) {
0730:                        files.add(file);
0731:                    }
0732:                }
0733:
0734:                // ensure that command roots (files that were explicitly selected by user) are included in Diff
0735:                FileStatusCache cache = Subversion.getInstance()
0736:                        .getStatusCache();
0737:                File[] rootFiles = context.getRootFiles();
0738:                for (int i = 0; i < rootFiles.length; i++) {
0739:                    File file = rootFiles[i];
0740:                    if (file.isFile()
0741:                            && (cache.getStatus(file).getStatus() & includeStatus) != 0
0742:                            && !files.contains(file)) {
0743:                        files.add(file);
0744:                    }
0745:                }
0746:                return files.toArray(new File[files.size()]);
0747:            }
0748:
0749:            /**
0750:             * Checks file location.
0751:             *
0752:             * @param file file to check
0753:             * @return true if the file or folder is a part of subverion metadata, false otherwise
0754:             */
0755:            public static boolean isPartOfSubversionMetadata(File file) {
0756:                return metadataPattern.matcher(file.getAbsolutePath())
0757:                        .matches();
0758:            }
0759:
0760:            /**
0761:             * Gets integer status that can be used in comparators. The more important the status is for the user,
0762:             * the lower value it has. Conflict is 0, unknown status is 100.
0763:             *
0764:             * @return status constant suitable for 'by importance' comparators
0765:             */
0766:            public static int getComparableStatus(int status) {
0767:                if (0 != (status & FileInformation.STATUS_VERSIONED_CONFLICT)) {
0768:                    return 0;
0769:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_MERGE)) {
0770:                    return 1;
0771:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_DELETEDLOCALLY)) {
0772:                    return 10;
0773:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY)) {
0774:                    return 11;
0775:                } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) {
0776:                    return 12;
0777:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) {
0778:                    return 13;
0779:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) {
0780:                    return 14;
0781:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY)) {
0782:                    return 30;
0783:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_NEWINREPOSITORY)) {
0784:                    return 31;
0785:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY)) {
0786:                    return 32;
0787:                } else if (0 != (status & FileInformation.STATUS_VERSIONED_UPTODATE)) {
0788:                    return 50;
0789:                } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) {
0790:                    return 100;
0791:                } else if (0 != (status & FileInformation.STATUS_NOTVERSIONED_NOTMANAGED)) {
0792:                    return 101;
0793:                } else if (status == FileInformation.STATUS_UNKNOWN) {
0794:                    return 102;
0795:                } else {
0796:                    throw new IllegalArgumentException("Uncomparable status: "
0797:                            + status); // NOI18N
0798:                }
0799:            }
0800:
0801:            /**
0802:             * Returns a symbolic branch/tag name if the given file lives
0803:             * in a location specified by an AnnotationExpression
0804:             *
0805:             * @param file
0806:             * @return name or null
0807:             */
0808:            public static String getCopy(File file) {
0809:                SVNUrl url;
0810:                try {
0811:                    url = getRepositoryUrl(file);
0812:                } catch (SVNClientException ex) {
0813:                    SvnClientExceptionHandler.notifyException(ex, false, false);
0814:                    return null;
0815:                }
0816:                return getCopy(url, SvnModuleConfig.getDefault()
0817:                        .getAnnotationExpresions());
0818:            }
0819:
0820:            /**
0821:             * Returns a symbolic branch/tag name if the given url represents
0822:             * a location specified by an AnnotationExpression
0823:             *
0824:             * @param url
0825:             * @return name or null
0826:             */
0827:            public static String getCopy(SVNUrl url) {
0828:                return getCopy(url, SvnModuleConfig.getDefault()
0829:                        .getAnnotationExpresions());
0830:            }
0831:
0832:            /**
0833:             * Returns a symbolic branch/tag name if the given url represents
0834:             * a location specified by an AnnotationExpression
0835:             *
0836:             * @param url
0837:             * @param annotationExpressions
0838:             * @return name or null
0839:             */
0840:            private static String getCopy(SVNUrl url,
0841:                    List<AnnotationExpression> annotationExpressions) {
0842:                if (url != null) {
0843:                    String urlString = url.toString();
0844:                    for (Iterator<AnnotationExpression> it = annotationExpressions
0845:                            .iterator(); it.hasNext();) {
0846:                        String name = it.next().getCopyName(urlString);
0847:                        if (name != null) {
0848:                            return name;
0849:                        }
0850:                    }
0851:                }
0852:                return null;
0853:            }
0854:
0855:            /**
0856:             * Refreshes statuses of this folder and all its parent folders up to filesystem root.
0857:             *
0858:             * @param folder folder to refresh
0859:             */
0860:            public static void refreshParents(File folder) {
0861:                if (folder == null)
0862:                    return;
0863:                refreshParents(folder.getParentFile());
0864:                Subversion.getInstance().getStatusCache().refresh(folder,
0865:                        FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0866:            }
0867:
0868:            /**
0869:             * Refreshes the status for the given file and all its children
0870:             * 
0871:             * @param file
0872:             */
0873:            public static void refreshRecursively(File file) {
0874:                FileStatusCache cache = Subversion.getInstance()
0875:                        .getStatusCache();
0876:                cache.refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0877:                File[] files = file.listFiles();
0878:                if (files != null) {
0879:                    for (int i = 0; i < files.length; i++) {
0880:                        if (!(SvnUtils.isPartOfSubversionMetadata(files[i]) || Subversion
0881:                                .getInstance().isAdministrative(files[i]))) {
0882:                            cache.refresh(files[i],
0883:                                    FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0884:                            if (files[i].isDirectory()) {
0885:                                refreshRecursively(files[i]);
0886:                            }
0887:                        }
0888:                    }
0889:                }
0890:            }
0891:
0892:            /**
0893:             * Rips an eventual username off - e.g. user@svn.host.org
0894:             * 
0895:             * @param host - hostname with a userneame
0896:             * @return host - hostname without the username
0897:             */
0898:            public static String ripUserFromHost(String host) {
0899:                int idx = host.indexOf('@');
0900:                if (idx < 0) {
0901:                    return host;
0902:                } else {
0903:                    return host.substring(idx + 1);
0904:                }
0905:            }
0906:
0907:            public static SVNRevision getSVNRevision(String revisionString) {
0908:                try {
0909:                    // HEAD, PREV, BASE, COMMITED, ...
0910:                    return SVNRevision.getRevision(revisionString);
0911:                } catch (ParseException ex) {
0912:                    return new SVNRevision.Number(Long
0913:                            .parseLong(revisionString));
0914:                }
0915:            }
0916:
0917:            /*
0918:             * Returns the first pattern from the list which matches with the given value.
0919:             * The patterns are interpreted as shell paterns.
0920:             *
0921:             * @param patterns
0922:             * @param value
0923:             * @return the first pattern matching with the given value
0924:             */
0925:            public static List<String> getMatchinIgnoreParterns(
0926:                    List<String> patterns, String value, boolean onlyFirstMatch) {
0927:                List<String> ret = new ArrayList<String>();
0928:                for (Iterator<String> i = patterns.iterator(); i.hasNext();) {
0929:                    try {
0930:                        // may contain shell patterns (almost identical to RegExp)
0931:                        String patternString = i.next();
0932:                        String shellPatternString = regExpToFilePatterns(patternString);
0933:                        Pattern pattern = Pattern.compile(shellPatternString);
0934:                        if (pattern.matcher(value).matches()) {
0935:                            ret.add(patternString);
0936:                            if (onlyFirstMatch) {
0937:                                return ret;
0938:                            }
0939:                        }
0940:                    } catch (PatternSyntaxException e) {
0941:                        // it's difference between shell and regexp
0942:                        // or user error (set invalid property), rethrow?
0943:                        Subversion.LOG.log(Level.INFO, null, e);
0944:                    }
0945:                }
0946:                return ret;
0947:            }
0948:
0949:            private static String regExpToFilePatterns(String exp) {
0950:                exp = exp.replaceAll("\\.", "\\\\."); // NOI18N
0951:                exp = exp.replaceAll("\\*", ".*"); // NOI18N
0952:                exp = exp.replaceAll("\\?", "."); // NOI18N
0953:
0954:                exp = exp.replaceAll("\\$", "\\\\\\$"); // NOI18N
0955:                exp = exp.replaceAll("\\^", "\\\\^"); // NOI18N
0956:                exp = exp.replaceAll("\\<", "\\\\<"); // NOI18N
0957:                exp = exp.replaceAll("\\>", "\\\\>"); // NOI18N
0958:                exp = exp.replaceAll("\\[", "\\\\["); // NOI18N
0959:                exp = exp.replaceAll("\\]", "\\\\]"); // NOI18N
0960:                exp = exp.replaceAll("\\{", "\\\\{"); // NOI18N
0961:                exp = exp.replaceAll("\\}", "\\\\}"); // NOI18N
0962:                exp = exp.replaceAll("\\(", "\\\\("); // NOI18N
0963:                exp = exp.replaceAll("\\)", "\\\\)"); // NOI18N
0964:                exp = exp.replaceAll("\\+", "\\\\+"); // NOI18N
0965:                exp = exp.replaceAll("\\|", "\\\\|"); // NOI18N
0966:
0967:                return exp;
0968:            }
0969:
0970:            /**
0971:             * Reads the svn:mime-type property or uses content analysis for unversioned files.
0972:             * 
0973:             * @param file file to examine
0974:             * @return String mime type of the file (or best guess)
0975:             */
0976:            public static String getMimeType(File file) {
0977:                FileObject fo = FileUtil.toFileObject(file);
0978:                String foMime;
0979:                if (fo == null) {
0980:                    foMime = "content/unknown";
0981:                } else {
0982:                    foMime = fo.getMIMEType();
0983:                }
0984:                FileStatusCache cache = Subversion.getInstance()
0985:                        .getStatusCache();
0986:                if ((cache.getStatus(file).getStatus() & FileInformation.STATUS_VERSIONED) == 0) {
0987:                    if (foMime.startsWith("text")) {
0988:                        return foMime;
0989:                    }
0990:                    return Utils.isFileContentText(file) ? "text/plain"
0991:                            : "application/octet-stream";
0992:                } else {
0993:                    PropertiesClient client = new PropertiesClient(file);
0994:                    try {
0995:                        byte[] mimeProperty = client.getProperties().get(
0996:                                "svn:mime-type");
0997:                        if (mimeProperty == null) {
0998:                            return foMime;
0999:                        }
1000:                        return new String(mimeProperty);
1001:                    } catch (IOException e) {
1002:                        return foMime;
1003:                    }
1004:                }
1005:            }
1006:
1007:            public static <T> boolean equals(List<T> l1, List<T> l2) {
1008:
1009:                if (l1 == null && l2 == null) {
1010:                    return true;
1011:                }
1012:
1013:                if ((l1 == null && l2 != null && l2.size() > 0)
1014:                        || (l2 == null && l1 != null && l1.size() > 0)) {
1015:                    return false;
1016:                }
1017:
1018:                if (l1.size() != l2.size()) {
1019:                    return false;
1020:                }
1021:
1022:                for (T t : l1) {
1023:                    if (!l2.contains(t)) {
1024:                        return false;
1025:                    }
1026:                }
1027:
1028:                return true;
1029:            }
1030:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.