Source Code Cross Referenced for CVSEntry.java in  » Source-Control » jcvsweb » com » ice » cvsc » Java Source Code / Java DocumentationJava Source Code and Java Documentation

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


0001:        /*
0002:         ** Java cvs client library package.
0003:         ** Copyright (c) 1997-2002 by Timothy Gerard Endres
0004:         ** 
0005:         ** This program is free software.
0006:         ** 
0007:         ** You may redistribute it and/or modify it under the terms of the GNU
0008:         ** Library General Public License (LGPL) as published by the Free Software
0009:         ** Foundation.
0010:         **
0011:         ** Version 2 of the license should be included with this distribution in
0012:         ** the file LICENSE.txt, as well as License.html. If the license is not
0013:         ** included	with this distribution, you may find a copy at the FSF web
0014:         ** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the Free
0015:         ** Software Foundation at 59 Temple Place - Suite 330, Boston, MA 02111 USA.
0016:         **
0017:         ** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
0018:         ** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
0019:         ** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
0020:         ** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
0021:         ** REDISTRIBUTION OF THIS SOFTWARE. 
0022:         ** 
0023:         */
0024:
0025:        package com.ice.cvsc;
0026:
0027:        import java.io.*;
0028:        import java.lang.*;
0029:        import java.text.*;
0030:        import java.util.*;
0031:
0032:        /**
0033:         * CVSEntry implements the concept of a CVS Entry. Traditionally,
0034:         * a CVS Entry is a line in an 'Entries' file in a 'CVS' admin
0035:         * directory. A CVSEntry represents a CVS file that is checked
0036:         * in or being checked in.
0037:         *
0038:         * CVSEntry objects contain all of the relavent information about
0039:         * a CVS file, such as its name, check-out time, modification status,
0040:         * local pathname, repository, etc.
0041:         *
0042:         * @version $Revision: 2.11 $
0043:         * @author Timothy Gerard Endres, <a href="mailto:time@ice.com">time@ice.com</a>.
0044:         * @see CVSClient
0045:         * @see CVSProject
0046:         * @see CVSEntryVector
0047:         */
0048:
0049:        public class CVSEntry extends Object implements  Cloneable {
0050:            static public final String RCS_ID = "$Id: CVSEntry.java,v 2.11 2003/07/27 01:08:32 time Exp $";
0051:            static public final String RCS_REV = "$Revision: 2.11 $";
0052:
0053:            /**
0054:             * True if this entry is valid.
0055:             */
0056:            private boolean valid;
0057:
0058:            /**
0059:             * True if this entry is a directory entry.
0060:             */
0061:            private boolean isDir;
0062:
0063:            /**
0064:             * If this entry is a directory entry, then this is
0065:             * the entry vector for the entries in that directory.
0066:             */
0067:            private CVSEntryVector entryList;
0068:
0069:            /**
0070:             * The full path of the repository as it comes from the
0071:             * 'Repository' file in the 'CVS' administration directory.
0072:             */
0073:            private String repository;
0074:
0075:            /**
0076:             * This is the entry's 'local directory'. This is the
0077:             * local directory that is sent as the 'pathname' of many
0078:             * responses, and is sent with 'Directory' requests.
0079:             */
0080:            private String localDirectory;
0081:
0082:            private boolean isNoUserFile;
0083:            private boolean isNewUserFile;
0084:            private boolean isToBeRemoved;
0085:            private boolean isDirty;
0086:
0087:            /**
0088:             * If this is set, then when the getServerEntryLine() is
0089:             * called, we will ignore the file's modification status
0090:             * and mark the entry as "/modified/". This was added to
0091:             * support jcvsweb, but is currently unused.
0092:             */
0093:            private boolean forceModified;
0094:
0095:            /**
0096:             * If this is set, then when the getServerEntryLine() is
0097:             * called, we will ignore the "exists" flag and pretend
0098:             * that the file does NOT exist. This was added to support
0099:             * jcvsweb's need for updates of existing files for viewing
0100:             * purposes.
0101:             */
0102:            private boolean forceNoExistence;
0103:
0104:            private CVSMode mode;
0105:
0106:            private CVSTimestamp tsCache;
0107:            private CVSTimestamp cfCache;
0108:
0109:            private String name;
0110:            private String version;
0111:            private String timestamp;
0112:            private String conflict;
0113:            private String options;
0114:            private String tag;
0115:            private String date;
0116:
0117:            private Vector childListeners;
0118:
0119:            public CVSEntry() {
0120:                super ();
0121:
0122:                this .valid = false;
0123:                this .isDir = false;
0124:
0125:                this .repository = null;
0126:                this .localDirectory = null;
0127:                this .entryList = null;
0128:
0129:                this .isNoUserFile = false;
0130:                this .isNewUserFile = false;
0131:                this .isToBeRemoved = false;
0132:                this .isDirty = false;
0133:                this .forceModified = false;
0134:                this .forceNoExistence = false;
0135:
0136:                this .mode = null;
0137:                this .tsCache = null;
0138:                this .cfCache = null;
0139:
0140:                this .name = "";
0141:                this .version = "";
0142:                this .timestamp = "";
0143:                this .conflict = null;
0144:                this .options = null;
0145:                this .tag = null;
0146:                this .date = null;
0147:
0148:                this .childListeners = new Vector();
0149:            }
0150:
0151:            public boolean isValid() {
0152:                return this .valid;
0153:            }
0154:
0155:            public void setValid(boolean valid) {
0156:                this .valid = valid;
0157:            }
0158:
0159:            public boolean isDirty() {
0160:                return this .isDirty;
0161:            }
0162:
0163:            public void setDirty(boolean dirty) {
0164:                this .isDirty = dirty;
0165:            }
0166:
0167:            public boolean isForceModified() {
0168:                return this .forceModified;
0169:            }
0170:
0171:            public void setForceModified(boolean forceModified) {
0172:                this .forceModified = forceModified;
0173:            }
0174:
0175:            public boolean isForceNoExistence() {
0176:                return this .forceNoExistence;
0177:            }
0178:
0179:            public void setForceNoExistence(boolean forceNoExistence) {
0180:                this .forceNoExistence = forceNoExistence;
0181:            }
0182:
0183:            public String getName() {
0184:                return this .name;
0185:            }
0186:
0187:            public void setName(String name) {
0188:                this .name = name;
0189:            }
0190:
0191:            public String getRepository() {
0192:                return this .repository;
0193:            }
0194:
0195:            public void setRepository(String repository) {
0196:                this .repository = CVSCUtilities.stripFinalSlash(repository);
0197:            }
0198:
0199:            // 'LocalDirectory' here is in the sense of the
0200:            // local-directory returned with cvs server responses!
0201:            public String getLocalDirectory() {
0202:                return this .localDirectory;
0203:            }
0204:
0205:            public void setLocalDirectory(String directory) {
0206:                this .localDirectory = CVSCUtilities.ensureFinalSlash(directory);
0207:            }
0208:
0209:            public String getFullName() {
0210:                if (this .isDirectory())
0211:                    return this .getLocalDirectory();
0212:                else
0213:                    return (this .getLocalDirectory() + this .getName());
0214:            }
0215:
0216:            private String stripDotSlashPrefix(String path) {
0217:                if (path.startsWith("./"))
0218:                    path = path.substring(2);
0219:                return path;
0220:            }
0221:
0222:            /**
0223:             * This method was added when we finally decided to bite the
0224:             * bullet and change the naming scheme to work "correctly".
0225:             * This will return the same string as getFullName(), except
0226:             * that the "./" prefix is removed. This is preferable for
0227:             * building file path names, hence the name.
0228:             */
0229:            public String getFullPathName() {
0230:                return this .stripDotSlashPrefix(this .getFullName());
0231:            }
0232:
0233:            /**
0234:             * This method was added when we finally decided to bite the
0235:             * bullet and change the naming scheme to work "correctly".
0236:             * This will return the same string as getLocalDirectory(),
0237:             * except that the "./" prefix is removed. This is preferable
0238:             * for building file path names, hence the name.
0239:             */
0240:            public String getLocalPathName() {
0241:                return this .stripDotSlashPrefix(this .getLocalDirectory());
0242:            }
0243:
0244:            public String getRepositoryName() {
0245:                return (this .getRepository() + this .getName());
0246:            }
0247:
0248:            public String getArgumentName() {
0249:                return this .getFullName();
0250:            }
0251:
0252:            /**
0253:             * Provides the directory-ness of this entry.
0254:             *
0255:             * @return True if this entry is a directory, else false.
0256:             */
0257:            public boolean isDirectory() {
0258:                return this .isDir;
0259:            }
0260:
0261:            public void appendEntry(CVSEntry entry) {
0262:                this .entryList.appendEntry(entry);
0263:                this .fireChildAddedEvent(this .new ChildEvent(this .entryList
0264:                        .size() - 1, entry));
0265:            }
0266:
0267:            public boolean removeEntry(CVSEntry entry) {
0268:                boolean result = false;
0269:
0270:                int index = this .entryList.indexOf(entry);
0271:                if (index != -1) {
0272:                    result = true;
0273:                    this .isDirty = true;
0274:                    CVSEntry child = this .entryList.entryAt(index);
0275:                    this .entryList.removeElementAt(index);
0276:                    this 
0277:                            .fireChildRemovedEvent(this .new ChildEvent(index,
0278:                                    child));
0279:                }
0280:
0281:                return result;
0282:            }
0283:
0284:            public boolean removeEntry(String entryName) {
0285:                boolean result = false;
0286:
0287:                for (int i = 0, sz = this .entryList.size(); i < sz; ++i) {
0288:                    CVSEntry entry = this .entryList.entryAt(i);
0289:                    if (entryName.equals(entry.getName())) {
0290:                        result = true;
0291:                        this .isDirty = true;
0292:                        this .entryList.removeElementAt(i);
0293:                        this 
0294:                                .fireChildRemovedEvent(this .new ChildEvent(i,
0295:                                        entry));
0296:                        break;
0297:                    }
0298:                }
0299:
0300:                return result;
0301:            }
0302:
0303:            public void removeAllEntries() {
0304:                if (this .isDirectory()) {
0305:                    if (this .entryList != null) {
0306:                        this .entryList.removeAllEntries();
0307:                        this 
0308:                                .fireChildRemovedEvent(this .new ChildEvent(-1,
0309:                                        null));
0310:                    }
0311:                }
0312:            }
0313:
0314:            public CVSEntry locateEntry(String name) {
0315:                return this .entryList.locateEntry(name);
0316:            }
0317:
0318:            public CVSEntryVector getEntryList() {
0319:                return this .entryList;
0320:            }
0321:
0322:            /**
0323:             * This method will make this entry a directory entry
0324:             * and establish its entry list with the list passed
0325:             * in the parameter. This is the <strong>only</strong> means of making
0326:             * a CVSEntry become a <em>directory entry</em>.
0327:             *
0328:             * @param entryList The directory's entry list.
0329:             */
0330:            public void setDirectoryEntryList(CVSEntryVector entryList) {
0331:                if (entryList != null) {
0332:                    this .isDir = true;
0333:                    this .entryList = entryList;
0334:                }
0335:            }
0336:
0337:            public String getVersion() {
0338:                return this .version;
0339:            }
0340:
0341:            public void setVersion(String version) {
0342:                this .isNoUserFile = false;
0343:                this .isNewUserFile = false;
0344:                this .isToBeRemoved = false;
0345:
0346:                if (version == null || version.length() == 0) {
0347:                    this .isNoUserFile = true;
0348:                    this .version = "";
0349:                } else if (version.startsWith("-")) {
0350:                    this .isToBeRemoved = true;
0351:                    this .version = version.substring(1);
0352:                } else if (version.startsWith("0")) // that's a zero
0353:                {
0354:                    this .isNewUserFile = true;
0355:                    this .version = version.substring(1);
0356:                } else {
0357:                    this .version = version;
0358:                }
0359:            }
0360:
0361:            public void markForRemoval(boolean markState) {
0362:                this .isToBeRemoved = markState;
0363:            }
0364:
0365:            private CVSTimestamp parseTimestamp(String stampStr) {
0366:                CVSTimestamp result = new CVSTimestamp(0);
0367:
0368:                if (stampStr != null) {
0369:                    CVSTimestampFormat stamper = CVSTimestampFormat
0370:                            .getInstance();
0371:
0372:                    try {
0373:                        result = stamper.parse(stampStr);
0374:                    } catch (ParseException ex) {
0375:                        result = new CVSTimestamp(0);
0376:                        CVSTracer.traceWithStack("CVSEntry.parseTimestamp: "
0377:                                + "could not parse timestamp: '" + stampStr
0378:                                + "' - " + ex.getMessage());
0379:                    }
0380:                }
0381:
0382:                return result;
0383:            }
0384:
0385:            /**
0386:             * The cached CVSTimestamp (a subclass of Date), or null.
0387:             */
0388:            public CVSTimestamp getCVSTime() {
0389:                return this .tsCache;
0390:            }
0391:
0392:            public String getTimestamp() {
0393:                return this .timestamp;
0394:            }
0395:
0396:            public String completeTimestamp() {
0397:                return this .timestamp
0398:                        + (this .conflict == null ? "" : ("+" + this .conflict));
0399:            }
0400:
0401:            public String getTerseTimestamp() {
0402:                if (this .tsCache == null) {
0403:                    this .tsCache = this .parseTimestamp(this .timestamp);
0404:                }
0405:
0406:                if (this .tsCache == null) {
0407:                    return this .timestamp; // punt!
0408:                } else {
0409:                    CVSTimestampFormat stamper = CVSTimestampFormat
0410:                            .getInstance();
0411:
0412:                    return stamper.formatTerse(this .tsCache);
0413:                }
0414:            }
0415:
0416:            /**
0417:             * Set the timestamp of this entry to that of the modification
0418:             * time of the file passed to this method.
0419:             *
0420:             * <b>NOTE</b> There is an issue with timestamps between Java
0421:             * and CVS. Specifically, Java time uses millisecond resolution
0422:             * and CVS time uses second resolution. The problem arises when
0423:             * a file is "sync-ed" with the CVS/Entries timestamp and the
0424:             * file's modtime is stored with non-zero milliseconds. When we
0425:             * later compare the file's modtime to that of the CVSEntry's
0426:             * timestamp, they will differ by the milliseconds quantity.
0427:             * To solve this problem, we strip milliseconds from any file
0428:             * timestamp coming into jCVS. This forces all of the timestamps
0429:             * to have zero millisecond digits, which will compare properly
0430:             * with the CVS timestamps.
0431:             */
0432:
0433:            public void setTimestamp(File entryFile) {
0434:                // FIRST strip the millisecond digits and make them zero!
0435:                long mTime = entryFile.lastModified();
0436:                mTime = (mTime / 1000) * 1000;
0437:
0438:                CVSTimestamp stamp = new CVSTimestamp(mTime);
0439:
0440:                CVSTimestampFormat stamper = CVSTimestampFormat.getInstance();
0441:
0442:                String stampStr = stamper.format(stamp);
0443:
0444:                this .setTimestamp(stampStr);
0445:            }
0446:
0447:            public void setTimestamp(String timeStamp) {
0448:                // REVIEW
0449:                if (timeStamp == null) {
0450:                    CVSTracer.traceWithStack("NULL TIMESTAMP!!!");
0451:                    timeStamp = "";
0452:                }
0453:
0454:                String tstamp = new String(timeStamp);
0455:
0456:                this .cfCache = null;
0457:                this .conflict = null;
0458:
0459:                if (tstamp.length() < 1) {
0460:                    this .timestamp = "";
0461:                    this .tsCache = null;
0462:                } else if (tstamp.startsWith("+")) {
0463:                    // REVIEW - leave the timestamp in place...
0464:                    // We have received a "+conflict" format, which
0465:                    // typically only comes from the server.
0466:                    this .conflict = tstamp.substring(1);
0467:                    if (this .conflict.equals("=")) {
0468:                        // In this case, the server is indicating that the
0469:                        // file is "going to be equal" once the 'Merged' handling
0470:                        // is completed. To retain the "inConflict" nature of
0471:                        // the entry, we will simply set the conflict to an
0472:                        // empty string (not null), as the conflict will be
0473:                        // set very shortly as a result of the 'Merged' handling.
0474:                        //
0475:                        this .conflict = "";
0476:                    }
0477:                } else {
0478:                    int index = tstamp.indexOf('+');
0479:                    if (index < 0) {
0480:                        // Only the timestamp is provided (no '+').
0481:                        if (tstamp.startsWith("Initial ")) {
0482:                            // This file was "added" but not committed,
0483:                            // timestamp is irrelevant
0484:                            this .timestamp = "";
0485:                            this .tsCache = null;
0486:                        } else if (tstamp.equals("Result of merge")) {
0487:                            // This file was "merged" timestamp must show modified
0488:                            this .timestamp = "";
0489:                            this .tsCache = null;
0490:                        } else if (!tstamp.equals(this .timestamp)) {
0491:                            // Only update these if it is different
0492:                            this .tsCache = null; // signal need to parse!
0493:                            this .timestamp = tstamp;
0494:                        }
0495:                    } else {
0496:                        // The "timestamp+conflict" case.
0497:                        // This should <em>only</em> comes from an Entries
0498:                        // file, and should never come from the server.
0499:                        this .conflict = tstamp.substring(index + 1);
0500:                        tstamp = tstamp.substring(0, index);
0501:                        if (!tstamp.equals(this .timestamp)) {
0502:                            // Only update these if it is different
0503:                            this .tsCache = null; // signal need to parse!
0504:                            //
0505:                            // REVIEW
0506:                            // UNDONE
0507:                            // This next check really should be more "generic"
0508:                            // in the sense of "if ( ! validTimestamp( tstamp ) )".
0509:                            //
0510:                            if (tstamp.equals("Result of merge")) {
0511:                                // REVIEW should we always set to conflict?
0512:                                // If timestamp is empty, use the conflict...
0513:                                if ((this .timestamp == null || this .timestamp
0514:                                        .length() == 0)
0515:                                        && this .conflict.length() > 0) {
0516:                                    this .timestamp = this .conflict;
0517:                                }
0518:                            } else {
0519:                                this .timestamp = tstamp;
0520:                            }
0521:                        }
0522:                    }
0523:                }
0524:
0525:                CVSTimestampFormat stamper = CVSTimestampFormat.getInstance();
0526:
0527:                // If tsCache is set to null, we need to update it...
0528:                if (this .tsCache == null && this .timestamp.length() > 0) {
0529:                    try {
0530:                        this .tsCache = stamper.parse(this .timestamp);
0531:                    } catch (ParseException ex) {
0532:                        this .tsCache = null;
0533:                        if (false) // in normal operations, this is ok
0534:                            CVSTracer
0535:                                    .traceWithStack("could not parse entries timestamp (cache): '"
0536:                                            + this .timestamp
0537:                                            + "' - "
0538:                                            + ex.getMessage());
0539:                    }
0540:                }
0541:
0542:                // If conflict is not null, we need to update cfCache...
0543:                if (this .conflict != null && this .conflict.length() > 0) {
0544:                    try {
0545:                        this .cfCache = stamper.parse(this .conflict);
0546:                    } catch (ParseException ex) {
0547:                        this .cfCache = null;
0548:                        if (false) // in normal operations, this is ok
0549:                            CVSTracer
0550:                                    .traceWithStack("could not parse entries conflict (cache): '"
0551:                                            + this .conflict
0552:                                            + "' - "
0553:                                            + ex.getMessage());
0554:                    }
0555:                }
0556:                if (false)
0557:                    CVSTracer.traceIf(true,
0558:                            "CVSEntry.setTimestamp: '"
0559:                                    + this .getName()
0560:                                    + "' - '"
0561:                                    + timeStamp
0562:                                    + "'\n   timestamp '"
0563:                                    + this .timestamp
0564:                                    + "' tsCache '"
0565:                                    + (this .tsCache == null ? "(not set)"
0566:                                            : "(set)")
0567:                                    + "'\n   conflict  '"
0568:                                    + (this .conflict == null ? "(null)"
0569:                                            : this .conflict)
0570:                                    + "' cfCache '"
0571:                                    + (this .cfCache == null ? "(not set)"
0572:                                            : "(set)") + "'");
0573:            }
0574:
0575:            /**
0576:             * <b>NOTE</b>Refer to note under setTimestamp( File ) pertaining
0577:             * to the resolution of file times and CVS timestamps.
0578:             */
0579:            public void setConflict(File entryFile) {
0580:                // FIRST strip the millisecond digits and make them zero!
0581:                long mTime = entryFile.lastModified();
0582:                mTime = (mTime / 1000) * 1000;
0583:
0584:                this .cfCache = new CVSTimestamp(mTime);
0585:
0586:                CVSTimestamp stamp = new CVSTimestamp(this .cfCache.getTime());
0587:
0588:                CVSTimestampFormat stamper = CVSTimestampFormat.getInstance();
0589:
0590:                String stampStr = stamper.format(stamp);
0591:
0592:                this .conflict = stampStr;
0593:            }
0594:
0595:            public String getOptions() {
0596:                return this .options;
0597:            }
0598:
0599:            public void setOptions(String options) {
0600:                this .options = options;
0601:            }
0602:
0603:            public boolean isBinary() {
0604:                return (this .options.indexOf("-kb") != -1);
0605:            }
0606:
0607:            public String getTag() {
0608:                return this .tag;
0609:            }
0610:
0611:            public void setTag(String tag) {
0612:                this .tag = tag;
0613:                this .date = null;
0614:            }
0615:
0616:            public String getDate() {
0617:                return this .date;
0618:            }
0619:
0620:            public void setDate(String date) {
0621:                this .tag = null;
0622:                this .date = date;
0623:            }
0624:
0625:            public CVSMode getMode() {
0626:                return this .mode;
0627:            }
0628:
0629:            public void setMode(CVSMode mode) {
0630:                this .mode = mode;
0631:            }
0632:
0633:            public String getModeLine() {
0634:                return (this .mode == null ? "u=rw,g=r,o=r" // UNDONE - better idea?
0635:                        : this .mode.getModeLine());
0636:            }
0637:
0638:            public boolean isNoUserFile() {
0639:                return this .isNoUserFile;
0640:            }
0641:
0642:            public void setNoUserFile(boolean isNo) {
0643:                this .isNoUserFile = isNo;
0644:            }
0645:
0646:            public boolean isInConflict() {
0647:                return (this .conflict != null);
0648:            }
0649:
0650:            private String getConflict() {
0651:                return this .conflict;
0652:            }
0653:
0654:            public boolean isNewUserFile() {
0655:                return this .isNewUserFile;
0656:            }
0657:
0658:            public void setNewUserFile(boolean isNew) {
0659:                this .isNewUserFile = isNew;
0660:            }
0661:
0662:            public boolean isToBeRemoved() {
0663:                return this .isToBeRemoved;
0664:            }
0665:
0666:            public void setToBeRemoved(boolean toBe) {
0667:                this .isToBeRemoved = toBe;
0668:            }
0669:
0670:            public boolean isLocalFileModified(File localFile) {
0671:                if (this .forceModified) {
0672:                    System.err.println("CVSENTRY: force MOD? "
0673:                            + this .forceModified);
0674:                    return true;
0675:                }
0676:
0677:                // REVIEW is this the best return value for this case?
0678:                if (this .tsCache == null)
0679:                    return true;
0680:
0681:                return !this .tsCache.equalsTime(localFile.lastModified());
0682:            }
0683:
0684:            // UNDONE - all of the "ParseException( , offset's" are zero!
0685:
0686:            private String parseAToken(StringTokenizer toker) {
0687:                String token = null;
0688:
0689:                try {
0690:                    token = toker.nextToken();
0691:                } catch (NoSuchElementException ex) {
0692:                    token = null;
0693:                }
0694:
0695:                return token;
0696:            }
0697:
0698:            public boolean parseEntryLine(String parseLine, boolean fromServer)
0699:                    throws ParseException {
0700:                String token = null;
0701:                String nameToke = null;
0702:                String versionToke = null;
0703:                String conflictToke = null;
0704:                String optionsToke = null;
0705:                String tagToke = null;
0706:
0707:                this .valid = false;
0708:
0709:                String entryLine = parseLine;
0710:
0711:                // Strip the 'D' from 'Directory' entries
0712:                if (entryLine.startsWith("D/")) {
0713:                    this .isDir = true;
0714:                    entryLine = entryLine.substring(1);
0715:                }
0716:
0717:                StringTokenizer toker = new StringTokenizer(entryLine, "/",
0718:                        true);
0719:
0720:                int tokeCount = toker.countTokens();
0721:
0722:                if (tokeCount < 6) {
0723:                    throw new ParseException(
0724:                            "not enough tokens in entries line "
0725:                                    + "(min 6, parsed " + tokeCount + ")", 0);
0726:                }
0727:
0728:                token = this .parseAToken(toker);
0729:                if (token == null || !token.equals("/"))
0730:                    throw new ParseException(
0731:                            "could not parse name's starting slash", 0);
0732:
0733:                nameToke = this .parseAToken(toker);
0734:                if (nameToke == null) {
0735:                    throw new ParseException("could not parse entry name", 0);
0736:                } else if (nameToke.equals("/")) {
0737:                    throw new ParseException("entry has an empty name", 0);
0738:                } else {
0739:                    token = this .parseAToken(toker);
0740:                    if (token == null || !token.equals("/"))
0741:                        throw new ParseException(
0742:                                "could not parse version's starting slash", 0);
0743:                }
0744:
0745:                versionToke = this .parseAToken(toker);
0746:                if (versionToke == null) {
0747:                    throw new ParseException(
0748:                            "out of tokens getting version field", 0);
0749:                } else if (versionToke.equals("/")) {
0750:                    versionToke = "";
0751:                } else {
0752:                    token = this .parseAToken(toker);
0753:                    if (token == null || !token.equals("/"))
0754:                        throw new ParseException(
0755:                                "could not parse conflict's starting slash", 0);
0756:                }
0757:
0758:                conflictToke = this .parseAToken(toker);
0759:                if (conflictToke == null) {
0760:                    throw new ParseException(
0761:                            "out of tokens getting conflict field", 0);
0762:                } else if (conflictToke.equals("/")) {
0763:                    conflictToke = "";
0764:                } else {
0765:                    token = this .parseAToken(toker);
0766:                    if (token == null || !token.equals("/"))
0767:                        throw new ParseException(
0768:                                "could not parse options' starting slash", 0);
0769:                }
0770:
0771:                optionsToke = this .parseAToken(toker);
0772:                if (optionsToke == null) {
0773:                    throw new ParseException(
0774:                            "out of tokens getting options field", 0);
0775:                } else if (optionsToke.equals("/")) {
0776:                    optionsToke = "";
0777:                } else {
0778:                    token = this .parseAToken(toker);
0779:                    if (token == null || !token.equals("/"))
0780:                        throw new ParseException(
0781:                                "could not parse tag's starting slash", 0);
0782:                }
0783:
0784:                tagToke = this .parseAToken(toker);
0785:                if (tagToke == null || tagToke.equals("/")) {
0786:                    tagToke = "";
0787:                }
0788:
0789:                this .valid = true;
0790:
0791:                if (fromServer && conflictToke.length() > 0
0792:                        && !conflictToke.startsWith("+")) {
0793:                    // We silently ignore conflicts that don't start with '+'
0794:                    // when they come from the server.
0795:                    conflictToke = "";
0796:                }
0797:
0798:                this .setName(nameToke);
0799:                this .setVersion(versionToke);
0800:                this .setTimestamp(conflictToke);
0801:                this .setOptions(optionsToke);
0802:
0803:                if (tagToke == null || tagToke.length() < 1) {
0804:                    this .setTag(null);
0805:                } else {
0806:                    if (tagToke.startsWith("D")) {
0807:                        this .setDate(tagToke.substring(1));
0808:                    } else {
0809:                        this .setTag(tagToke.substring(1));
0810:                    }
0811:                }
0812:
0813:                return this .valid;
0814:            }
0815:
0816:            public String padString(String str, int width) {
0817:                int i;
0818:                StringBuffer result = new StringBuffer(width);
0819:
0820:                result.append(str);
0821:                for (i = result.length() - 1; i < width; ++i)
0822:                    result.append(" ");
0823:
0824:                return result.toString();
0825:            }
0826:
0827:            public String getAdminEntryLine() {
0828:                if (this .isDirectory()) {
0829:                    // REVIEW should we be carrying along options & tags?!
0830:                    return "D/" + this .name + "////";
0831:                }
0832:
0833:                StringBuffer result = new StringBuffer("");
0834:
0835:                result.append("/" + this .name + "/");
0836:
0837:                if (!this .isNoUserFile()) {
0838:                    if (this .isNewUserFile()) {
0839:                        result.append("0"); // that's a zero
0840:                    } else {
0841:                        if (this .isToBeRemoved())
0842:                            result.append("-");
0843:
0844:                        if (this .version != null)
0845:                            result.append(this .version);
0846:                    }
0847:                }
0848:
0849:                result.append("/");
0850:
0851:                if (this .isNewUserFile()) {
0852:                    result.append("Initial " + this .getName());
0853:                } else {
0854:                    result.append(this .timestamp);
0855:
0856:                    if (this .isInConflict()) {
0857:                        result.append("+" + this .conflict);
0858:                    }
0859:                }
0860:
0861:                result.append("/");
0862:
0863:                if (this .options != null)
0864:                    result.append(this .options);
0865:
0866:                result.append("/");
0867:
0868:                if (this .tag != null) {
0869:                    result.append("T" + this .tag);
0870:                } else if (this .date != null) {
0871:                    result.append("D" + this .date);
0872:                }
0873:
0874:                return result.toString();
0875:            }
0876:
0877:            public String getServerEntryLine(boolean exists, boolean isModified) {
0878:                if (this .isDirectory()) {
0879:                    // REVIEW should we be carrying along options & tags?!
0880:                    return "/" + this .name + "////";
0881:                }
0882:
0883:                StringBuffer result = new StringBuffer("");
0884:
0885:                result.append("/" + this .name + "/");
0886:
0887:                if (!this .isNoUserFile()) {
0888:                    if (this .isNewUserFile()) {
0889:                        result.append("0"); // that's a zero
0890:                    } else {
0891:                        if (this .isToBeRemoved())
0892:                            result.append("-");
0893:
0894:                        if (this .version != null && !this .forceNoExistence)
0895:                            result.append(this .version);
0896:                    }
0897:                }
0898:
0899:                result.append("/");
0900:
0901:                if (this .isNewUserFile()) {
0902:                    result.append("Initial " + this .getName());
0903:                } else if (exists && !this .forceNoExistence) {
0904:                    if (this .isInConflict()) {
0905:                        result.append("+");
0906:                    }
0907:
0908:                    if (isModified || forceModified)
0909:                        result.append("modified");
0910:                    else
0911:                        result.append("=");
0912:                }
0913:
0914:                result.append("/");
0915:
0916:                if (this .options != null)
0917:                    result.append(this .options);
0918:
0919:                result.append("/");
0920:
0921:                if (this .tag != null && !this .forceNoExistence)
0922:                    result.append("T" + this .tag);
0923:                else if (this .date != null && !this .forceNoExistence)
0924:                    result.append("D" + this .date);
0925:
0926:                CVSTracer.traceIf(false, "getServerEntryLine: '"
0927:                        + result.toString() + "'");
0928:
0929:                return result.toString();
0930:            }
0931:
0932:            public String toString() {
0933:                return "[ " + this .getFullName() + ","
0934:                        + this .getAdminEntryLine() + " ]";
0935:            }
0936:
0937:            /**
0938:             * Adds all of the file entries in this directory entry to the vector supplied.
0939:             *
0940:             * @param vector The vector to add the file entries to.
0941:             */
0942:
0943:            public void addFileEntries(CVSEntryVector vector) {
0944:                CVSEntryVector entries = this .getEntryList();
0945:                for (int idx = 0; idx < entries.size(); ++idx) {
0946:                    CVSEntry entry = entries.entryAt(idx);
0947:                    if (!entry.isDirectory())
0948:                        vector.appendEntry(entry);
0949:                }
0950:            }
0951:
0952:            /**
0953:             * Adds all of the file entries in this directory entry, as well as every
0954:             * file entry in every subdirectory entry recursively.
0955:             *
0956:             * @param vector The vector to add the file entries to.
0957:             */
0958:
0959:            public void addAllSubTreeEntries(CVSEntryVector vector) {
0960:                CVSEntryVector dirs = new CVSEntryVector();
0961:                CVSEntryVector list = this .getEntryList();
0962:
0963:                // First, append all of the files, caching directories...
0964:                for (int idx = 0; idx < list.size(); ++idx) {
0965:                    CVSEntry entry = list.entryAt(idx);
0966:                    if (entry.isDirectory())
0967:                        dirs.appendEntry(entry);
0968:                    else
0969:                        vector.appendEntry(entry);
0970:                }
0971:
0972:                // Now, process all of the cached directories...
0973:                for (int idx = 0; idx < dirs.size(); ++idx) {
0974:                    CVSEntry entry = dirs.entryAt(idx);
0975:                    entry.addAllSubTreeEntries(vector);
0976:                }
0977:            }
0978:
0979:            public class ChildEvent {
0980:                CVSEntry entry;
0981:                CVSEntry childEntry;
0982:                int childIndex;
0983:
0984:                /**
0985:                 * The source is the CVSEntry that parent's the child.
0986:                 * The index is the index of the affected child.
0987:                 */
0988:
0989:                public ChildEvent(int index, CVSEntry child) {
0990:                    this .childIndex = index;
0991:                    this .childEntry = child;
0992:                }
0993:
0994:                public CVSEntry getCVSEntry() {
0995:                    return CVSEntry.this ;
0996:                }
0997:
0998:                public int getChildIndex() {
0999:                    return this .childIndex;
1000:                }
1001:
1002:                public CVSEntry getChildEntry() {
1003:                    return this .childEntry;
1004:                }
1005:
1006:            }
1007:
1008:            public interface ChildEventListener {
1009:                public void cvsEntryAddedChild(CVSEntry.ChildEvent event);
1010:
1011:                public void cvsEntryRemovedChild(CVSEntry.ChildEvent event);
1012:            }
1013:
1014:            protected void fireChildAddedEvent(ChildEvent event) {
1015:                // Process the listeners last to first, notifying
1016:                // those that are interested in this event
1017:                for (int i = this .childListeners.size() - 1; i >= 0; --i) {
1018:                    ((ChildEventListener) this .childListeners.elementAt(i))
1019:                            .cvsEntryAddedChild(event);
1020:                }
1021:            }
1022:
1023:            protected void fireChildRemovedEvent(ChildEvent event) {
1024:                // Process the listeners last to first, notifying
1025:                // those that are interested in this event
1026:                for (int i = this .childListeners.size() - 1; i >= 0; --i) {
1027:                    ((ChildEventListener) this .childListeners.elementAt(i))
1028:                            .cvsEntryRemovedChild(event);
1029:                }
1030:            }
1031:
1032:            public void addChildEventListener(ChildEventListener l) {
1033:                this .childListeners.addElement(l);
1034:            }
1035:
1036:            public void removeChildEventListener(ChildEventListener l) {
1037:                this .childListeners.removeElement(l);
1038:            }
1039:
1040:            public String dumpString() {
1041:                return this .dumpString("");
1042:            }
1043:
1044:            public String dumpString(String prefix) {
1045:                return prefix + "CVSEntry: " + super .toString() + "\n" + prefix
1046:                        + "   Name: " + this .getName() + "\n" + prefix
1047:                        + "   FullName: " + this .getFullName() + "\n" + prefix
1048:                        + "   LocalDir: " + this .getLocalDirectory() + "\n"
1049:                        + prefix + "   Repository: " + this .getRepository()
1050:                        + "\n" + prefix + "   Timestamp: "
1051:                        + this .getTimestamp() + "\n" + prefix + "   Conflict: "
1052:                        + this.getConflict();
1053:            }
1054:
1055:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.