Source Code Cross Referenced for FileStatusCache.java in  » IDE-Netbeans » mercurial » org » netbeans » modules » mercurial » 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 » mercurial » org.netbeans.modules.mercurial 
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:        package org.netbeans.modules.mercurial;
0042:
0043:        import org.netbeans.modules.mercurial.util.HgUtils;
0044:        import org.netbeans.modules.turbo.Turbo;
0045:        import org.netbeans.modules.turbo.CustomProviders;
0046:        import org.netbeans.modules.versioning.util.Utils;
0047:        import org.netbeans.modules.versioning.spi.VCSContext;
0048:        import org.netbeans.modules.versioning.spi.VersioningSupport;
0049:        import org.openide.filesystems.FileSystem;
0050:        import org.openide.filesystems.FileUtil;
0051:        import org.netbeans.modules.mercurial.Mercurial;
0052:        import java.io.File;
0053:        import java.util.*;
0054:        import java.util.logging.Level;
0055:        import java.beans.PropertyChangeSupport;
0056:        import java.beans.PropertyChangeListener;
0057:        import java.io.File;
0058:        import org.netbeans.modules.mercurial.util.HgCommand;
0059:        import java.util.logging.Level;
0060:        import org.netbeans.api.queries.SharabilityQuery;
0061:
0062:        /**
0063:         * Central part of status management, deduces and caches statuses of files under version control.
0064:         *
0065:         * @author Maros Sandor
0066:         */
0067:        public class FileStatusCache {
0068:
0069:            /**
0070:             * Indicates that status of a file changed and listeners SHOULD check new status
0071:             * values if they are interested in this file.
0072:             * The New value is a ChangedEvent object (old FileInformation object may be null)
0073:             */
0074:            public static final String PROP_FILE_STATUS_CHANGED = "status.changed"; // NOI18N
0075:
0076:            /**
0077:             * A special map saying that no file inside the folder is managed.
0078:             */
0079:            private static final Map<File, FileInformation> NOT_MANAGED_MAP = new NotManagedMap();
0080:
0081:            public static final FileStatus REPOSITORY_STATUS_UNKNOWN = null;
0082:
0083:            // Constant FileInformation objects that can be safely reused
0084:            // Files that have a revision number cannot share FileInformation objects
0085:            private static final FileInformation FILE_INFORMATION_EXCLUDED = new FileInformation(
0086:                    FileInformation.STATUS_NOTVERSIONED_EXCLUDED, false);
0087:            private static final FileInformation FILE_INFORMATION_EXCLUDED_DIRECTORY = new FileInformation(
0088:                    FileInformation.STATUS_NOTVERSIONED_EXCLUDED, true);
0089:            private static final FileInformation FILE_INFORMATION_UPTODATE_DIRECTORY = new FileInformation(
0090:                    FileInformation.STATUS_VERSIONED_UPTODATE, true);
0091:            private static final FileInformation FILE_INFORMATION_NOTMANAGED = new FileInformation(
0092:                    FileInformation.STATUS_NOTVERSIONED_NOTMANAGED, false);
0093:            private static final FileInformation FILE_INFORMATION_NOTMANAGED_DIRECTORY = new FileInformation(
0094:                    FileInformation.STATUS_NOTVERSIONED_NOTMANAGED, true);
0095:            private static final FileInformation FILE_INFORMATION_UNKNOWN = new FileInformation(
0096:                    FileInformation.STATUS_UNKNOWN, false);
0097:            private static final FileInformation FILE_INFORMATION_NEWLOCALLY = new FileInformation(
0098:                    FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY, false);
0099:            public static final FileInformation FILE_INFORMATION_CONFLICT = new FileInformation(
0100:                    FileInformation.STATUS_VERSIONED_CONFLICT, false);
0101:            public static final FileInformation FILE_INFORMATION_REMOVEDLOCALLY = new FileInformation(
0102:                    FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY, false);
0103:
0104:            private PropertyChangeSupport listenerSupport = new PropertyChangeSupport(
0105:                    this );
0106:
0107:            /**
0108:             * Caches status of files in memory ant on disk
0109:             */
0110:            private final Turbo turbo;
0111:
0112:            private final String FILE_STATUS_MAP = DiskMapTurboProvider.ATTR_STATUS_MAP;
0113:
0114:            private DiskMapTurboProvider cacheProvider;
0115:
0116:            private Mercurial hg;
0117:
0118:            private Set<FileSystem> filesystemsToRefresh;
0119:
0120:            FileStatusCache() {
0121:                this .hg = Mercurial.getInstance();
0122:                cacheProvider = new DiskMapTurboProvider();
0123:                turbo = Turbo.createCustom(new CustomProviders() {
0124:                    private final Set providers = Collections
0125:                            .singleton(cacheProvider);
0126:
0127:                    public Iterator providers() {
0128:                        return providers.iterator();
0129:                    }
0130:                }, 200, 5000);
0131:            }
0132:
0133:            // --- Public interface -------------------------------------------------
0134:
0135:            /**
0136:             * Lists <b>modified files</b> and all folders that are known to be inside
0137:             * this folder. There are locally modified files present
0138:             * plus any files that exist in the folder in the remote repository.
0139:             *
0140:             * @param dir folder to list
0141:             * @return
0142:             */
0143:            public File[] listFiles(File dir) {
0144:                Set<File> files = getScannedFiles(dir, null).keySet();
0145:                return files.toArray(new File[files.size()]);
0146:            }
0147:
0148:            /**
0149:             * Check if this context has at least one file with the passed in status
0150:             *
0151:             * @param context context to examine
0152:             * @param includeStatus file status to check for
0153:             * @return boolean true if this context contains at least one file with the includeStatus, false otherwise
0154:             */
0155:            public boolean containsFileOfStatus(VCSContext context,
0156:                    int includeStatus) {
0157:                Map<File, FileInformation> allFiles = cacheProvider
0158:                        .getAllModifiedValues();
0159:                if (allFiles == null) {
0160:                    Mercurial.LOG.log(Level.FINE,
0161:                            "containsFileOfStatus(): allFiles == null"); // NOI18N
0162:                    return false;
0163:                }
0164:
0165:                Set<File> roots = context.getRootFiles();
0166:                Set<File> exclusions = context.getExclusions();
0167:                Set<File> setAllFiles = allFiles.keySet();
0168:                boolean bExclusions = exclusions != null
0169:                        && exclusions.size() > 0;
0170:                boolean bContainsFile = false;
0171:
0172:                for (File file : setAllFiles) {
0173:                    FileInformation info = (FileInformation) allFiles.get(file);
0174:                    if ((info.getStatus() & includeStatus) == 0)
0175:                        continue;
0176:                    for (File root : roots) {
0177:                        if (VersioningSupport.isFlat(root)) {
0178:                            if (file.equals(root)
0179:                                    || file.getParentFile().equals(root)) {
0180:                                bContainsFile = true;
0181:                                break;
0182:                            }
0183:                        } else {
0184:                            if (Utils.isAncestorOrEqual(root, file)) {
0185:                                File fileRoot = hg
0186:                                        .getTopmostManagedParent(file);
0187:                                File rootRoot = hg
0188:                                        .getTopmostManagedParent(root);
0189:                                // Make sure that file is in same repository as root
0190:                                if (rootRoot.equals(fileRoot)) {
0191:                                    bContainsFile = true;
0192:                                    break;
0193:                                }
0194:                            }
0195:                        }
0196:                    }
0197:                    // Check it is not an excluded file
0198:                    if (bContainsFile && bExclusions) {
0199:                        for (File excluded : exclusions) {
0200:                            if (!Utils.isAncestorOrEqual(excluded, file)) {
0201:                                return true;
0202:                            }
0203:                        }
0204:                    } else if (bContainsFile) {
0205:                        return true;
0206:                    }
0207:                }
0208:                return false;
0209:            }
0210:
0211:            /**
0212:             * Lists <b>interesting files</b> that are known to be inside given folders.
0213:             * These are locally and remotely modified and ignored files.
0214:             *
0215:             * <p>This method returns both folders and files.
0216:             *
0217:             * @param context context to examine
0218:             * @param includeStatus limit returned files to those having one of supplied statuses
0219:             * @return File [] array of interesting files
0220:             */
0221:            public File[] listFiles(VCSContext context, int includeStatus) {
0222:                Set<File> set = new HashSet<File>();
0223:                Map allFiles = cacheProvider.getAllModifiedValues();
0224:                if (allFiles == null) {
0225:                    Mercurial.LOG.log(Level.FINE,
0226:                            "FileStatusCache: listFiles(): allFiles == null"); // NOI18N
0227:                    return new File[0];
0228:                }
0229:
0230:                for (Iterator i = allFiles.keySet().iterator(); i.hasNext();) {
0231:                    File file = (File) i.next();
0232:                    FileInformation info = (FileInformation) allFiles.get(file);
0233:                    if ((info.getStatus() & includeStatus) == 0)
0234:                        continue;
0235:                    Set<File> roots = context.getRootFiles();
0236:                    for (File root : roots) {
0237:                        if (VersioningSupport.isFlat(root)) {
0238:                            if (file.equals(root)
0239:                                    || file.getParentFile().equals(root)) {
0240:                                set.add(file);
0241:                                break;
0242:                            }
0243:                        } else {
0244:                            if (Utils.isAncestorOrEqual(root, file)) {
0245:                                File fileRoot = hg
0246:                                        .getTopmostManagedParent(file);
0247:                                File rootRoot = hg
0248:                                        .getTopmostManagedParent(root);
0249:                                // Make sure that file is in same repository as root
0250:                                if (rootRoot.equals(fileRoot)) {
0251:                                    set.add(file);
0252:                                    break;
0253:                                }
0254:                            }
0255:                        }
0256:                    }
0257:                }
0258:                if (context.getExclusions().size() > 0) {
0259:                    for (Iterator i = context.getExclusions().iterator(); i
0260:                            .hasNext();) {
0261:                        File excluded = (File) i.next();
0262:                        for (Iterator j = set.iterator(); j.hasNext();) {
0263:                            File file = (File) j.next();
0264:                            if (Utils.isAncestorOrEqual(excluded, file)) {
0265:                                j.remove();
0266:                            }
0267:                        }
0268:                    }
0269:                }
0270:                return set.toArray(new File[set.size()]);
0271:            }
0272:
0273:            /**
0274:             * Lists <b>interesting files</b> that are known to be inside given folders.
0275:             * These are locally and remotely modified and ignored files.
0276:             *
0277:             * <p>Comapring to CVS this method returns both folders and files.
0278:             *
0279:             * @param roots context to examine
0280:             * @param includeStatus limit returned files to those having one of supplied statuses
0281:             * @return File [] array of interesting files
0282:             */
0283:            public File[] listFiles(File[] roots, int includeStatus) {
0284:                Set<File> set = new HashSet<File>();
0285:                Map allFiles = cacheProvider.getAllModifiedValues();
0286:                for (Iterator i = allFiles.keySet().iterator(); i.hasNext();) {
0287:                    File file = (File) i.next();
0288:                    FileInformation info = (FileInformation) allFiles.get(file);
0289:                    if ((info.getStatus() & includeStatus) == 0)
0290:                        continue;
0291:                    for (int j = 0; j < roots.length; j++) {
0292:                        File root = roots[j];
0293:                        if (VersioningSupport.isFlat(root)) {
0294:                            if (file.getParentFile().equals(root)) {
0295:                                set.add(file);
0296:                                break;
0297:                            }
0298:                        } else {
0299:                            if (Utils.isAncestorOrEqual(root, file)) {
0300:                                set.add(file);
0301:                                break;
0302:                            }
0303:                        }
0304:                    }
0305:                }
0306:                return set.toArray(new File[set.size()]);
0307:            }
0308:
0309:            /**
0310:             * Determines the versioning status of a file. This method accesses disk and may block for a long period of time.
0311:             *
0312:             * @param file file to get status for
0313:             * @return FileInformation structure containing the file status
0314:             * @see FileInformation
0315:             */
0316:            public FileInformation getStatus(File file) {
0317:                if (file.isDirectory()
0318:                        && (hg.isAdministrative(file) || HgUtils
0319:                                .isIgnored(file)))
0320:                    return FileStatusCache.FILE_INFORMATION_EXCLUDED_DIRECTORY;
0321:                File dir = file.getParentFile();
0322:                if (dir == null) {
0323:                    return FileStatusCache.FILE_INFORMATION_NOTMANAGED; //default for filesystem roots
0324:                }
0325:                Map files = getScannedFiles(dir, null);
0326:                if (files == FileStatusCache.NOT_MANAGED_MAP)
0327:                    return FileStatusCache.FILE_INFORMATION_NOTMANAGED;
0328:                FileInformation fi = (FileInformation) files.get(file);
0329:                if (fi != null) {
0330:                    return fi;
0331:                }
0332:                if (!exists(file))
0333:                    return FileStatusCache.FILE_INFORMATION_UNKNOWN;
0334:                if (file.isDirectory()) {
0335:                    return refresh(file, REPOSITORY_STATUS_UNKNOWN);
0336:                } else {
0337:                    return new FileInformation(
0338:                            FileInformation.STATUS_VERSIONED_UPTODATE, false);
0339:                }
0340:            }
0341:
0342:            /**
0343:             * Looks up cached file status.
0344:             *
0345:             * @param file file to check
0346:             * @return give file's status or null if the file's status is not in cache
0347:             */
0348:            @SuppressWarnings("unchecked")
0349:            // Need to change turbo module to remove warning at source
0350:            FileInformation getCachedStatus(File file, boolean bCheckSharability) {
0351:                File parent = file.getParentFile();
0352:                if (parent == null)
0353:                    return FileStatusCache.FILE_INFORMATION_NOTMANAGED_DIRECTORY;
0354:
0355:                Map<File, FileInformation> files = (Map<File, FileInformation>) turbo
0356:                        .readEntry(parent, FILE_STATUS_MAP);
0357:                FileInformation fi = files != null ? files.get(file) : null;
0358:                if (fi != null)
0359:                    return fi;
0360:
0361:                if (file.isDirectory()) {
0362:                    if (hg.isAdministrative(file)
0363:                            || HgUtils.isIgnored(file, bCheckSharability)) {
0364:                        return FileStatusCache.FILE_INFORMATION_EXCLUDED_DIRECTORY;
0365:                    } else {
0366:                        return FileStatusCache.FILE_INFORMATION_UPTODATE_DIRECTORY;
0367:                    }
0368:                }
0369:
0370:                return fi;
0371:            }
0372:
0373:            private FileInformation refresh(File file,
0374:                    FileStatus repositoryStatus, boolean forceChangeEvent) {
0375:                Mercurial.LOG.log(Level.FINE, "refresh(): {0}", file); // NOI18N
0376:                File dir = file.getParentFile();
0377:                if (dir == null) {
0378:                    return FileStatusCache.FILE_INFORMATION_NOTMANAGED; //default for filesystem roots
0379:                }
0380:                Map<File, FileInformation> files = getScannedFiles(dir, null); // Has side effect of updating the cache
0381:                if (files == FileStatusCache.NOT_MANAGED_MAP
0382:                        && repositoryStatus == FileStatusCache.REPOSITORY_STATUS_UNKNOWN)
0383:                    return FileStatusCache.FILE_INFORMATION_NOTMANAGED;
0384:                FileInformation current = files.get(file);
0385:
0386:                FileInformation fi = createFileInformation(file);
0387:
0388:                if (FileStatusCache.equivalent(fi, current)) {
0389:                    if (forceChangeEvent)
0390:                        fireFileStatusChanged(file, current, fi);
0391:                    return fi;
0392:                }
0393:
0394:                // do not include uptodate files into cache, missing directories must be included
0395:                if (current == null
0396:                        && !fi.isDirectory()
0397:                        && fi.getStatus() == FileInformation.STATUS_VERSIONED_UPTODATE) {
0398:                    if (forceChangeEvent)
0399:                        fireFileStatusChanged(file, current, fi);
0400:                    return fi;
0401:                }
0402:
0403:                file = FileUtil.normalizeFile(file);
0404:                dir = FileUtil.normalizeFile(dir);
0405:                Map<File, FileInformation> newFiles = new HashMap<File, FileInformation>(
0406:                        files);
0407:                if (fi.getStatus() == FileInformation.STATUS_UNKNOWN) {
0408:                    newFiles.remove(file);
0409:                    turbo.writeEntry(file, FILE_STATUS_MAP, null); // remove mapping in case of directories
0410:                } else if (fi.getStatus() == FileInformation.STATUS_VERSIONED_UPTODATE
0411:                        && file.isFile()) {
0412:                    newFiles.remove(file);
0413:                } else {
0414:                    newFiles.put(file, fi);
0415:                }
0416:                assert newFiles.containsKey(dir) == false;
0417:                turbo.writeEntry(dir, FILE_STATUS_MAP,
0418:                        newFiles.size() == 0 ? null : newFiles);
0419:
0420:                if (file.isDirectory() && needRecursiveRefresh(fi, current)) {
0421:                    File[] content = listFiles(file); // Has side effect of updating the cache
0422:                    for (int i = 0; i < content.length; i++) {
0423:                        refresh(content[i],
0424:                                FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0425:                    }
0426:                }
0427:                fireFileStatusChanged(file, current, fi);
0428:                return fi;
0429:            }
0430:
0431:            private FileInformation createFileInformation(File file) {
0432:                return createFileInformation(file, true);
0433:            }
0434:
0435:            private FileInformation createFileInformation(File file,
0436:                    Boolean callStatus) {
0437:                Mercurial.LOG.log(Level.FINE,
0438:                        "createFileInformation(): {0} {1}", new Object[] {
0439:                                file, callStatus }); // NOI18N
0440:                if (file == null)
0441:                    return FILE_INFORMATION_UNKNOWN;
0442:                if (hg.isAdministrative(file))
0443:                    return FILE_INFORMATION_EXCLUDED_DIRECTORY; // Excluded
0444:
0445:                File rootManagedFolder = hg.getTopmostManagedParent(file);
0446:                if (rootManagedFolder == null)
0447:                    return FILE_INFORMATION_UNKNOWN; // Avoiding returning NOT_MANAGED dir or file
0448:
0449:                if (file.isDirectory()) {
0450:                    if (HgUtils.isIgnored(file)) {
0451:                        return FILE_INFORMATION_EXCLUDED_DIRECTORY; // Excluded
0452:                    } else {
0453:                        return FILE_INFORMATION_UPTODATE_DIRECTORY; // Managed dir
0454:                    }
0455:                }
0456:
0457:                if (callStatus == false) {
0458:                    if (HgUtils.isIgnored(file)) {
0459:                        return FILE_INFORMATION_EXCLUDED; // Excluded
0460:                    }
0461:                    return null;
0462:                }
0463:
0464:                FileInformation fi;
0465:                try {
0466:                    fi = HgCommand.getSingleStatus(rootManagedFolder, file
0467:                            .getParent(), file.getName());
0468:                } catch (HgException ex) {
0469:                    Mercurial.LOG.log(Level.FINE,
0470:                            "createFileInformation() file: {0} {1}",
0471:                            new Object[] { file.getAbsolutePath(),
0472:                                    ex.toString() }); // NOI18N
0473:                    return FILE_INFORMATION_UNKNOWN;
0474:                }
0475:                return fi;
0476:
0477:            }
0478:
0479:            /**
0480:             * Refreshes the status of the file given the repository status. Repository status is filled
0481:             * in when this method is called while processing server output.
0482:             *
0483:             * <p>Note: it's not necessary if you use Subversion.getClient(), it
0484:             * updates the cache automatically using onNotify(). It's not
0485:             * fully reliable for removed files.
0486:             *
0487:             * @param file
0488:             * @param repositoryStatus
0489:             */
0490:            public FileInformation refresh(File file,
0491:                    FileStatus repositoryStatus) {
0492:                return refresh(file, repositoryStatus, false);
0493:            }
0494:
0495:            public FileInformation refreshForce(File file,
0496:                    FileStatus repositoryStatus) {
0497:                return refresh(file, repositoryStatus, true);
0498:            }
0499:
0500:            @SuppressWarnings("unchecked")
0501:            // Need to change turbo module to remove warning at source
0502:            public Map<File, FileInformation> getScannedFiles(File dir,
0503:                    Map<File, FileInformation> interestingFiles) {
0504:                Map<File, FileInformation> files;
0505:
0506:                files = (Map<File, FileInformation>) turbo.readEntry(dir,
0507:                        FILE_STATUS_MAP);
0508:                if (files != null)
0509:                    return files;
0510:                if (isNotManagedByDefault(dir)) {
0511:                    if (interestingFiles == null)
0512:                        return FileStatusCache.NOT_MANAGED_MAP;
0513:                }
0514:
0515:                dir = FileUtil.normalizeFile(dir);
0516:                files = scanFolder(dir, interestingFiles);
0517:                assert files.containsKey(dir) == false;
0518:                turbo.writeEntry(dir, FILE_STATUS_MAP, files);
0519:                if (interestingFiles == null) {
0520:                    for (Iterator i = files.keySet().iterator(); i.hasNext();) {
0521:                        File file = (File) i.next();
0522:                        FileInformation info = files.get(file);
0523:                        if ((info.getStatus() & (FileInformation.STATUS_LOCAL_CHANGE | FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) != 0) {
0524:                            fireFileStatusChanged(file, null, info);
0525:                        }
0526:                    }
0527:                }
0528:                return files;
0529:            }
0530:
0531:            public void refreshFileStatus(File file, FileInformation fi,
0532:                    Map<File, FileInformation> interestingFiles) {
0533:                refreshFileStatus(file, fi, interestingFiles, false);
0534:            }
0535:
0536:            public void refreshFileStatus(File file, FileInformation fi,
0537:                    Map<File, FileInformation> interestingFiles,
0538:                    boolean alwaysFireEvent) {
0539:                if (file == null || fi == null)
0540:                    return;
0541:                File dir = file.getParentFile();
0542:                if (dir == null)
0543:                    return;
0544:
0545:                Map<File, FileInformation> files = getScannedFiles(dir,
0546:                        interestingFiles);
0547:
0548:                if (files == null || files == FileStatusCache.NOT_MANAGED_MAP)
0549:                    return;
0550:                FileInformation current = files.get(file);
0551:                if (FileStatusCache.equivalent(fi, current)) {
0552:                    if (FileStatusCache.equivalent(FILE_INFORMATION_NEWLOCALLY,
0553:                            fi)) {
0554:                        if (HgUtils.isIgnored(file)) {
0555:                            Mercurial.LOG
0556:                                    .log(
0557:                                            Level.FINE,
0558:                                            "refreshFileStatus() file: {0} was LocallyNew but is NotSharable",
0559:                                            file.getAbsolutePath()); // NOI18N
0560:                            fi = FILE_INFORMATION_EXCLUDED;
0561:                        } else {
0562:                            return;
0563:                        }
0564:                    } else if (!FileStatusCache.equivalent(
0565:                            FILE_INFORMATION_REMOVEDLOCALLY, fi)) {
0566:                        return;
0567:                    }
0568:                }
0569:                if (FileStatusCache.equivalent(FILE_INFORMATION_NEWLOCALLY, fi)) {
0570:                    if (FileStatusCache.equivalent(FILE_INFORMATION_EXCLUDED,
0571:                            current)) {
0572:                        Mercurial.LOG
0573:                                .log(
0574:                                        Level.FINE,
0575:                                        "refreshFileStatus() file: {0} was LocallyNew but is Excluded",
0576:                                        file.getAbsolutePath()); // NOI18N
0577:                        return;
0578:                    } else if (current == null) {
0579:                        if (HgUtils.isIgnored(file)) {
0580:                            Mercurial.LOG
0581:                                    .log(
0582:                                            Level.FINE,
0583:                                            "refreshFileStatus() file: {0} was LocallyNew but current is null and is not NotSharable",
0584:                                            file.getAbsolutePath()); // NOI18N
0585:                            fi = FILE_INFORMATION_EXCLUDED;
0586:                        }
0587:                    }
0588:                }
0589:                file = FileUtil.normalizeFile(file);
0590:                dir = FileUtil.normalizeFile(dir);
0591:                Map<File, FileInformation> newFiles = new HashMap<File, FileInformation>(
0592:                        files);
0593:                if (fi.getStatus() == FileInformation.STATUS_UNKNOWN) {
0594:                    newFiles.remove(file);
0595:                    turbo.writeEntry(file, FILE_STATUS_MAP, null); // remove mapping in case of directories
0596:                } else if (fi.getStatus() == FileInformation.STATUS_VERSIONED_UPTODATE
0597:                        && file.isFile()) {
0598:                    newFiles.remove(file);
0599:                } else {
0600:                    newFiles.put(file, fi);
0601:                }
0602:                assert files.containsKey(dir) == false;
0603:                turbo.writeEntry(dir, FILE_STATUS_MAP, newFiles);
0604:
0605:                if (interestingFiles == null) {
0606:                    fireFileStatusChanged(file, current, fi);
0607:                } else if (alwaysFireEvent) {
0608:                    fireFileStatusChanged(file, null, fi);
0609:                }
0610:
0611:                return;
0612:            }
0613:
0614:            /**
0615:             * Two FileInformation objects are equivalent if their status contants are equal AND they both reperesent a file (or
0616:             * both represent a directory) AND Entries they cache, if they can be compared, are equal.
0617:             *
0618:             * @param other object to compare to
0619:             * @return true if status constants of both object are equal, false otherwise
0620:             */
0621:            private static boolean equivalent(FileInformation main,
0622:                    FileInformation other) {
0623:                if (other == null || main.getStatus() != other.getStatus()
0624:                        || main.isDirectory() != other.isDirectory())
0625:                    return false;
0626:
0627:                FileStatus e1 = main.getStatus(null);
0628:                FileStatus e2 = other.getStatus(null);
0629:                return e1 == e2 || e1 == null || e2 == null
0630:                        || FileStatusCache.equal(e1, e2);
0631:            }
0632:
0633:            /**
0634:             * Replacement for missing Entry.equals(). It is implemented as a separate method to maintain compatibility.
0635:             *
0636:             * @param e1 first entry to compare
0637:             * @param e2 second Entry to compare
0638:             * @return true if supplied entries contain equivalent information
0639:             */
0640:            private static boolean equal(FileStatus e1, FileStatus e2) {
0641:                // TODO: use your own logic here
0642:                return true;
0643:            }
0644:
0645:            private boolean needRecursiveRefresh(FileInformation fi,
0646:                    FileInformation current) {
0647:                if (fi.getStatus() == FileInformation.STATUS_NOTVERSIONED_EXCLUDED
0648:                        || current != null
0649:                        && current.getStatus() == FileInformation.STATUS_NOTVERSIONED_EXCLUDED)
0650:                    return true;
0651:                if (fi.getStatus() == FileInformation.STATUS_NOTVERSIONED_NOTMANAGED
0652:                        || current != null
0653:                        && current.getStatus() == FileInformation.STATUS_NOTVERSIONED_NOTMANAGED)
0654:                    return true;
0655:                return false;
0656:            }
0657:
0658:            /**
0659:             * Refreshes information about a given file or directory ONLY if its status is already cached. The
0660:             * only exception are non-existing files (new-in-repository) whose statuses are cached in all cases.
0661:             *
0662:             * @param file
0663:             * @param repositoryStatus
0664:             */
0665:            public void refreshCached(File file, FileStatus repositoryStatus) {
0666:                refresh(file, repositoryStatus);
0667:            }
0668:
0669:            /**
0670:             * Refreshes status of the specfified file or all files inside the 
0671:             * specified directory. 
0672:             *
0673:             * @param file
0674:             */
0675:            public void refreshCached(File root) {
0676:                if (root.isDirectory()) {
0677:                    File repository = Mercurial.getInstance()
0678:                            .getTopmostManagedParent(root);
0679:                    if (repository == null) {
0680:                        return;
0681:                    }
0682:                    File roots[] = new File[1];
0683:                    roots[0] = root;
0684:                    File[] files = listFiles(roots, ~0);
0685:                    if (files.length == 0) {
0686:                        return;
0687:                    }
0688:                    Map<File, FileInformation> allFiles;
0689:                    try {
0690:                        allFiles = HgCommand.getAllStatus(repository, root);
0691:                        for (int i = 0; i < files.length; i++) {
0692:                            File file = files[i];
0693:                            FileInformation fi = allFiles.get(file);
0694:                            if (fi == null) {
0695:                                // We have a file in the cache which seems to have disappeared
0696:                                refresh(
0697:                                        file,
0698:                                        FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0699:                            } else {
0700:                                refreshFileStatus(file, fi, null);
0701:                            }
0702:                        }
0703:                    } catch (HgException ex) {
0704:                        Mercurial.LOG
0705:                                .log(Level.FINE,
0706:                                        "refreshCached() file: {0} {1} { 2} ",
0707:                                        new Object[] {
0708:                                                repository.getAbsolutePath(),
0709:                                                root.getAbsolutePath(),
0710:                                                ex.toString() }); // NOI18N
0711:                    }
0712:                } else {
0713:                    refresh(root, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Refreshes status of all files inside given context. 
0719:             *
0720:             * @param ctx context to refresh
0721:             */
0722:            public void refreshCached(VCSContext ctx) {
0723:
0724:                for (File root : ctx.getRootFiles()) {
0725:                    refreshCached(root);
0726:                }
0727:            }
0728:
0729:            public void addToCache(Set<File> files) {
0730:                FileInformation fi = new FileInformation(
0731:                        FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY, null,
0732:                        false);
0733:                HashMap<File, Map<File, FileInformation>> dirMap = new HashMap<File, Map<File, FileInformation>>(
0734:                        files.size());
0735:
0736:                for (File file : files) {
0737:                    File parent = file.getParentFile();
0738:                    file = FileUtil.normalizeFile(file);
0739:                    parent = FileUtil.normalizeFile(parent);
0740:                    Map<File, FileInformation> currentDirMap = dirMap
0741:                            .get(parent);
0742:                    if (currentDirMap == null) {
0743:                        // 20 is a guess at number of files in a directory
0744:                        currentDirMap = new HashMap<File, FileInformation>(20);
0745:                        dirMap.put(parent, currentDirMap);
0746:                    }
0747:                    currentDirMap.put(file, fi);
0748:                }
0749:                for (File dir : dirMap.keySet()) {
0750:                    dir = FileUtil.normalizeFile(dir);
0751:                    Map<File, FileInformation> currentDirMap = dirMap.get(dir);
0752:                    turbo.writeEntry(dir, FILE_STATUS_MAP, currentDirMap);
0753:                }
0754:            }
0755:
0756:            // --- Package private contract ------------------------------------------
0757:
0758:            Map<File, FileInformation> getAllModifiedFiles() {
0759:                return cacheProvider.getAllModifiedValues();
0760:            }
0761:
0762:            /**
0763:             * Refreshes given directory and all subdirectories.
0764:             *
0765:             * @param dir directory to refresh
0766:             */
0767:            void directoryContentChanged(File dir) {
0768:                Map originalFiles = (Map) turbo.readEntry(dir, FILE_STATUS_MAP);
0769:                if (originalFiles != null) {
0770:                    for (Iterator i = originalFiles.keySet().iterator(); i
0771:                            .hasNext();) {
0772:                        File file = (File) i.next();
0773:                        refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0774:                    }
0775:                }
0776:            }
0777:
0778:            /**
0779:             * Cleans up the cache by removing or correcting entries that are no longer valid or correct.
0780:             */
0781:            void cleanUp() {
0782:                Map files = cacheProvider.getAllModifiedValues();
0783:                for (Iterator i = files.keySet().iterator(); i.hasNext();) {
0784:                    File file = (File) i.next();
0785:                    FileInformation info = (FileInformation) files.get(file);
0786:                    if ((info.getStatus() & FileInformation.STATUS_LOCAL_CHANGE) != 0) {
0787:                        refresh(file, FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0788:                    } else if (info.getStatus() == FileInformation.STATUS_NOTVERSIONED_EXCLUDED) {
0789:                        // remove entries that were excluded but no longer exist
0790:                        // cannot simply call refresh on excluded files because of 'excluded on server' status
0791:                        if (!exists(file)) {
0792:                            refresh(file,
0793:                                    FileStatusCache.REPOSITORY_STATUS_UNKNOWN);
0794:                        }
0795:                    }
0796:                }
0797:            }
0798:
0799:            // --- Private methods ---------------------------------------------------
0800:
0801:            private boolean isNotManagedByDefault(File dir) {
0802:                return !dir.exists();
0803:            }
0804:
0805:            /**
0806:             * Scans all files in the given folder, computes and stores their CVS status.
0807:             *
0808:             * @param dir directory to scan
0809:             * @return Map map to be included in the status cache (File => FileInformation)
0810:             */
0811:            private Map<File, FileInformation> scanFolder(File dir,
0812:                    Map<File, FileInformation> interestingFiles) {
0813:                File[] files = dir.listFiles();
0814:                if (files == null) {
0815:                    if (interestingFiles == null) {
0816:                        files = new File[0];
0817:                    } else {
0818:                        files = interestingFiles.keySet().toArray(
0819:                                new File[interestingFiles.keySet().size()]);
0820:                    }
0821:                }
0822:                Map<File, FileInformation> folderFiles = new HashMap<File, FileInformation>(
0823:                        files.length);
0824:
0825:                Mercurial.LOG.log(Level.FINE, "scanFolder(): {0}", dir); // NOI18N
0826:                if (hg.isAdministrative(dir)) {
0827:                    folderFiles.put(dir, FILE_INFORMATION_EXCLUDED_DIRECTORY); // Excluded dir
0828:                    return folderFiles;
0829:                }
0830:
0831:                File rootManagedFolder = hg.getTopmostManagedParent(dir);
0832:                if (rootManagedFolder == null) {
0833:                    // Only interested in looking for Hg managed dirs
0834:                    for (File file : files) {
0835:                        if (file.isDirectory()
0836:                                && hg.getTopmostManagedParent(file) != null) {
0837:                            if (hg.isAdministrative(file)
0838:                                    || HgUtils.isIgnored(file)) {
0839:                                Mercurial.LOG
0840:                                        .log(
0841:                                                Level.FINE,
0842:                                                "scanFolder NotMng Ignored Dir {0}: exclude SubDir: {1}", // NOI18N
0843:                                                new Object[] {
0844:                                                        dir.getAbsolutePath(),
0845:                                                        file.getName() });
0846:                                folderFiles.put(file,
0847:                                        FILE_INFORMATION_EXCLUDED_DIRECTORY); // Excluded dir
0848:                            } else {
0849:                                Mercurial.LOG
0850:                                        .log(
0851:                                                Level.FINE,
0852:                                                "scanFolder NotMng Dir {0}: up to date Dir: {1}", // NOI18N
0853:                                                new Object[] {
0854:                                                        dir.getAbsolutePath(),
0855:                                                        file.getName() });
0856:                                folderFiles.put(file,
0857:                                        FILE_INFORMATION_UPTODATE_DIRECTORY);
0858:                            }
0859:                        }
0860:                        // Do NOT put any unmanaged dir's (FILE_INFORMATION_NOTMANAGED_DIRECTORY) or 
0861:                        // files (FILE_INFORMATION_NOTMANAGED) into the folderFiles
0862:                    }
0863:                    return folderFiles;
0864:                }
0865:
0866:                boolean bInIgnoredDir = HgUtils.isIgnored(dir);
0867:                if (bInIgnoredDir) {
0868:                    for (File file : files) {
0869:                        if (HgUtils.isPartOfMercurialMetadata(file))
0870:                            continue;
0871:
0872:                        if (file.isDirectory()) {
0873:                            folderFiles.put(file,
0874:                                    FILE_INFORMATION_EXCLUDED_DIRECTORY); // Excluded dir
0875:                            Mercurial.LOG
0876:                                    .log(
0877:                                            Level.FINE,
0878:                                            "scanFolder Mng Ignored Dir {0}: exclude SubDir: {1}", // NOI18N
0879:                                            new Object[] {
0880:                                                    dir.getAbsolutePath(),
0881:                                                    file.getName() });
0882:                        } else {
0883:                            Mercurial.LOG
0884:                                    .log(
0885:                                            Level.FINE,
0886:                                            "scanFolder Mng Ignored Dir {0}: exclude File: {1}", // NOI18N
0887:                                            new Object[] {
0888:                                                    dir.getAbsolutePath(),
0889:                                                    file.getName() });
0890:                            folderFiles.put(file, FILE_INFORMATION_EXCLUDED);
0891:                        }
0892:                    }
0893:                    return folderFiles;
0894:                }
0895:
0896:                if (!Mercurial.getInstance().isGoodVersion())
0897:                    return folderFiles;
0898:
0899:                if (interestingFiles == null) {
0900:                    try {
0901:                        interestingFiles = HgCommand.getInterestingStatus(
0902:                                rootManagedFolder, dir);
0903:                    } catch (HgException ex) {
0904:                        Mercurial.LOG
0905:                                .log(
0906:                                        Level.FINE,
0907:                                        "scanFolder() getInterestingStatus Exception: dir: {0} {1}",
0908:                                        new Object[] { dir.getAbsolutePath(),
0909:                                                ex.toString() }); // NOI18N
0910:                        return folderFiles;
0911:                    }
0912:                }
0913:
0914:                if (interestingFiles == null)
0915:                    return folderFiles;
0916:
0917:                for (File file : files) {
0918:                    if (HgUtils.isPartOfMercurialMetadata(file))
0919:                        continue;
0920:
0921:                    if (file.isDirectory()) {
0922:                        if (hg.isAdministrative(file)
0923:                                || HgUtils.isIgnored(file)) {
0924:                            Mercurial.LOG.log(Level.FINE,
0925:                                    "scanFolder Mng Dir {0}: exclude Dir: {1}", // NOI18N
0926:                                    new Object[] { dir.getAbsolutePath(),
0927:                                            file.getName() });
0928:                            folderFiles.put(file,
0929:                                    FILE_INFORMATION_EXCLUDED_DIRECTORY); // Excluded dir
0930:                        } else {
0931:                            Mercurial.LOG
0932:                                    .log(
0933:                                            Level.FINE,
0934:                                            "scanFolder Mng Dir {0}: up to date Dir: {1}", // NOI18N
0935:                                            new Object[] {
0936:                                                    dir.getAbsolutePath(),
0937:                                                    file.getName() });
0938:                            folderFiles.put(file,
0939:                                    FILE_INFORMATION_UPTODATE_DIRECTORY);
0940:                        }
0941:                    } else {
0942:                        FileInformation fi = interestingFiles.get(file);
0943:                        if (fi == null) {
0944:                            // We have removed -i from HgCommand.getInterestingFiles
0945:                            // so we might have a file we should be ignoring
0946:                            fi = createFileInformation(file, false);
0947:                        }
0948:                        if (fi != null
0949:                                && fi.getStatus() != FileInformation.STATUS_VERSIONED_UPTODATE)
0950:                            folderFiles.put(file, fi);
0951:                    }
0952:                }
0953:                return folderFiles;
0954:            }
0955:
0956:            private boolean exists(File file) {
0957:                if (!file.exists())
0958:                    return false;
0959:                return file.getAbsolutePath().equals(
0960:                        FileUtil.normalizeFile(file).getAbsolutePath());
0961:            }
0962:
0963:            public synchronized void addPropertyChangeListener(
0964:                    PropertyChangeListener listener) {
0965:                listenerSupport.addPropertyChangeListener(listener);
0966:            }
0967:
0968:            public void removePropertyChangeListener(
0969:                    PropertyChangeListener listener) {
0970:                listenerSupport.removePropertyChangeListener(listener);
0971:            }
0972:
0973:            private void fireFileStatusChanged(File file,
0974:                    FileInformation oldInfo, FileInformation newInfo) {
0975:                listenerSupport.firePropertyChange(PROP_FILE_STATUS_CHANGED,
0976:                        null, new ChangedEvent(file, oldInfo, newInfo));
0977:            }
0978:
0979:            public void refreshDirtyFileSystems() {
0980:                Set<FileSystem> filesystems = getFilesystemsToRefresh();
0981:                FileSystem[] filesystemsToRefresh = new FileSystem[filesystems
0982:                        .size()];
0983:                synchronized (filesystems) {
0984:                    filesystemsToRefresh = filesystems
0985:                            .toArray(new FileSystem[filesystems.size()]);
0986:                    filesystems.clear();
0987:                }
0988:                for (int i = 0; i < filesystemsToRefresh.length; i++) {
0989:                    // don't call refresh() in synchronized (filesystems). It may lead to a deadlock.
0990:                    filesystemsToRefresh[i].refresh(true);
0991:                }
0992:            }
0993:
0994:            private Set<FileSystem> getFilesystemsToRefresh() {
0995:                if (filesystemsToRefresh == null) {
0996:                    filesystemsToRefresh = new HashSet<FileSystem>();
0997:                }
0998:                return filesystemsToRefresh;
0999:            }
1000:
1001:            private static final class NotManagedMap extends
1002:                    AbstractMap<File, FileInformation> {
1003:                public Set<Entry<File, FileInformation>> entrySet() {
1004:                    return Collections.emptySet();
1005:                }
1006:            }
1007:
1008:            public static class ChangedEvent {
1009:
1010:                private File file;
1011:                private FileInformation oldInfo;
1012:                private FileInformation newInfo;
1013:
1014:                public ChangedEvent(File file, FileInformation oldInfo,
1015:                        FileInformation newInfo) {
1016:                    this .file = file;
1017:                    this .oldInfo = oldInfo;
1018:                    this .newInfo = newInfo;
1019:                }
1020:
1021:                public File getFile() {
1022:                    return file;
1023:                }
1024:
1025:                public FileInformation getOldInfo() {
1026:                    return oldInfo;
1027:                }
1028:
1029:                public FileInformation getNewInfo() {
1030:                    return newInfo;
1031:                }
1032:            }
1033:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.