Source Code Cross Referenced for Vss.java in  » Build » cruisecontrol » net » sourceforge » cruisecontrol » sourcecontrols » 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 » Build » cruisecontrol » net.sourceforge.cruisecontrol.sourcecontrols 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /***********************************************************************************************************************
002:         * CruiseControl, a Continuous Integration Toolkit
003:         * Copyright (c) 2001, ThoughtWorks, Inc.
004:         * 200 E. Randolph, 25th Floor
005:         * Chicago, IL 60601 USA
006:         * All rights reserved.
007:         *
008:         * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
009:         * following conditions are met:
010:         *
011:         *      Redistributions of source code must retain the above copyright notice, this list of conditions and the
012:         *      following disclaimer.
013:         *
014:         *      Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
015:         *      following disclaimer in the documentation and/or other materials provided with the distribution.
016:         *
017:         *      Neither the name of ThoughtWorks, Inc., CruiseControl, nor the names of its contributors may be used to endorse
018:         *      or promote products derived from this software without specific prior written permission.
019:         *
020:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
021:         * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022:         * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024:         * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
025:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027:         **********************************************************************************************************************/package net.sourceforge.cruisecontrol.sourcecontrols;
028:
029:        import java.io.BufferedReader;
030:        import java.io.File;
031:        import java.io.FileReader;
032:        import java.io.IOException;
033:        import java.io.InputStream;
034:        import java.text.ParseException;
035:        import java.text.SimpleDateFormat;
036:        import java.util.ArrayList;
037:        import java.util.Collections;
038:        import java.util.Date;
039:        import java.util.Iterator;
040:        import java.util.List;
041:        import java.util.Locale;
042:        import java.util.Map;
043:
044:        import net.sourceforge.cruisecontrol.CruiseControlException;
045:        import net.sourceforge.cruisecontrol.Modification;
046:        import net.sourceforge.cruisecontrol.SourceControl;
047:        import net.sourceforge.cruisecontrol.util.Commandline;
048:        import net.sourceforge.cruisecontrol.util.ValidationHelper;
049:        import net.sourceforge.cruisecontrol.util.IO;
050:        import net.sourceforge.cruisecontrol.util.StreamLogger;
051:
052:        import org.apache.log4j.Logger;
053:
054:        /**
055:         * This class handles all VSS-related aspects of determining the modifications since the last good build.
056:         *
057:         * @author <a href="mailto:alden@thoughtworks.com">alden almagro</a>
058:         * @author Eli Tucker
059:         * @author <a href="mailto:jcyip@thoughtworks.com">Jason Yip</a>
060:         * @author Arun Aggarwal
061:         */
062:        public class Vss implements  SourceControl {
063:
064:            private static final Logger LOG = Logger.getLogger(Vss.class);
065:
066:            private SimpleDateFormat vssDateTimeFormat;
067:            private String ssDir;
068:            private String vssPath;
069:            private String serverPath;
070:            private String login;
071:            private String dateFormat = "MM/dd/yy";
072:            private String timeFormat = "hh:mma";
073:            private SourceControlProperties properties = new SourceControlProperties();
074:
075:            public Vss() {
076:                constructVssDateTimeFormat();
077:            }
078:
079:            /**
080:             * Set the project to get history from
081:             *
082:             * @param vsspath
083:             */
084:            public void setVsspath(String vsspath) {
085:                this .vssPath = "$" + vsspath;
086:            }
087:
088:            /**
089:             * Set the path to the ss executable
090:             *
091:             * @param ssdir
092:             */
093:            public void setSsDir(String ssdir) {
094:                this .ssDir = ssdir;
095:            }
096:
097:            /**
098:             * Set the path to the directory containing the srcsafe.ini file.
099:             *
100:             * @param dirWithSrcsafeIni
101:             */
102:            public void setServerPath(String dirWithSrcsafeIni) {
103:                serverPath = dirWithSrcsafeIni;
104:            }
105:
106:            /**
107:             * Login for vss
108:             *
109:             * @param usernameCommaPassword
110:             */
111:            public void setLogin(String usernameCommaPassword) {
112:                login = usernameCommaPassword;
113:            }
114:
115:            /**
116:             * Choose a property to be set if the project has modifications if we have a change that only requires repackaging,
117:             * i.e. jsp, we don't need to recompile everything, just rejar.
118:             *
119:             * @param propertyName
120:             */
121:            public void setProperty(String propertyName) {
122:                properties.assignPropertyName(propertyName);
123:            }
124:
125:            /**
126:             * Choose a property to be set if the project has deletions
127:             *
128:             * @param propertyName
129:             */
130:            public void setPropertyOnDelete(String propertyName) {
131:                properties.assignPropertyOnDeleteName(propertyName);
132:            }
133:
134:            /**
135:             * Sets the date format to use for querying VSS and processing reports. The default date format is
136:             * <code>MM/dd/yy</code> . If your computer is set to a different region, you may wish to use a format such as
137:             * <code>dd/MM/yy</code> .
138:             *
139:             * @see java.text.SimpleDateFormat
140:             */
141:            public void setDateFormat(String format) {
142:                dateFormat = format;
143:                constructVssDateTimeFormat();
144:            }
145:
146:            /**
147:             * Sets the time format to use for querying VSS and processing reports. The default time format is
148:             * <code>hh:mma</code> . If your computer is set to a different region, you may wish to use a format such as
149:             * <code>HH:mm</code> .
150:             *
151:             * @see java.text.SimpleDateFormat
152:             */
153:            public void setTimeFormat(String format) {
154:                timeFormat = format;
155:                constructVssDateTimeFormat();
156:            }
157:
158:            public Map getProperties() {
159:                return properties.getPropertiesAndReset();
160:            }
161:
162:            public void validate() throws CruiseControlException {
163:                ValidationHelper.assertIsSet(vssPath, "vsspath", this 
164:                        .getClass());
165:                ValidationHelper.assertIsSet(login, "login", this .getClass());
166:            }
167:
168:            /**
169:             * Calls "ss history [dir] -R -Vd[now]~[lastBuild] -Y[login] -I-N -O[tempFileName]" Results written to a file since
170:             * VSS will start wrapping lines if read directly from the stream.
171:             *
172:             * @param lastBuild
173:             * @param now
174:             * @return List of modifications
175:             */
176:            public List getModifications(Date lastBuild, Date now) {
177:                List modifications = new ArrayList();
178:
179:                Process p = null;
180:                try {
181:                    LOG.info("Getting modifications for " + vssPath);
182:                    p = Runtime.getRuntime().exec(
183:                            getCommandLine(lastBuild, now),
184:                            VSSHelper.loadVSSEnvironment(serverPath));
185:                    p.getOutputStream().close();
186:                    Thread stderr = logErrorStream(p.getErrorStream());
187:
188:                    p.waitFor();
189:                    stderr.join();
190:
191:                    parseTempFile(modifications);
192:                } catch (Exception e) {
193:                    // TODO: Revisit this when ThreadQueue is more stable.  Would prefer throwing a RuntimeException.
194:                    LOG
195:                            .error(
196:                                    "Problem occurred while attempting to get VSS modifications.  Returning empty modifications.",
197:                                    e);
198:                    return Collections.EMPTY_LIST;
199:                } finally {
200:                    IO.close(p);
201:                }
202:
203:                if (modifications.size() > 0) {
204:                    properties.modificationFound();
205:                }
206:
207:                return modifications;
208:            }
209:
210:            private Thread logErrorStream(InputStream is) {
211:                Thread stderr = new Thread(StreamLogger.getWarnPumper(LOG, is));
212:                stderr.start();
213:                return stderr;
214:            }
215:
216:            void parseTempFile(List modifications) throws IOException,
217:                    CruiseControlException {
218:                File tempFile = getTempFile();
219:                if (!getTempFile().isFile()) {
220:                    throw new CruiseControlException(
221:                            "vss failed to create output file "
222:                                    + tempFile.getPath());
223:                }
224:
225:                if (LOG.isDebugEnabled()) {
226:                    logVSSTempFile();
227:                }
228:
229:                final BufferedReader reader = new BufferedReader(
230:                        new FileReader(tempFile));
231:                try {
232:                    parseHistoryEntries(modifications, reader);
233:                } finally {
234:                    // need to close the InputStream before delete(), otherwise fails on windows
235:                    IO.close(reader);
236:                }
237:                tempFile.delete();
238:            }
239:
240:            private void logVSSTempFile() throws IOException {
241:                BufferedReader reader = new BufferedReader(new FileReader(
242:                        getTempFile()));
243:                String currLine = reader.readLine();
244:                LOG.debug(" ");
245:                while (currLine != null) {
246:                    LOG.debug(getTempFile().getName() + ": " + currLine);
247:                    currLine = reader.readLine();
248:                }
249:                LOG.debug(" ");
250:                reader.close();
251:            }
252:
253:            private File getTempFile() {
254:                return new File(createFileNameFromVssPath());
255:            }
256:
257:            String createFileNameFromVssPath() {
258:                // don't include the leading $
259:                String filename = vssPath.substring(1).replace('/', '_')
260:                        + ".tmp";
261:                while (filename.charAt(0) == '_') {
262:                    filename = filename.substring(1);
263:                }
264:                return filename;
265:            }
266:
267:            void parseHistoryEntries(List modifications, BufferedReader reader)
268:                    throws IOException {
269:                String currLine = reader.readLine();
270:
271:                while (currLine != null) {
272:                    if (isRelevantVssEntryHeader(currLine)) {
273:                        List vssEntry = new ArrayList();
274:                        vssEntry.add(currLine);
275:                        currLine = reader.readLine();
276:                        while (currLine != null
277:                                && !isRelevantVssEntryHeader(currLine)) {
278:                            vssEntry.add(currLine);
279:                            currLine = reader.readLine();
280:                        }
281:                        Modification mod = handleEntry(vssEntry);
282:                        if (mod != null) {
283:                            modifications.add(mod);
284:                        }
285:                    } else {
286:                        currLine = reader.readLine();
287:                    }
288:                }
289:            }
290:
291:            /**
292:             * Most relevant VSS entry headers will be 5 asterisks, 2 spaces, file name, 2 spaces, 5 asterisks. However, if
293:             * adding to the root, there are apparently 17 asterisks, 2 spaces, version name, 2 spaces, 17 asterisks.
294:             */
295:            private boolean isRelevantVssEntryHeader(String line) {
296:                // This can still fail if the entry has a comment containing something of the form '***** some text *****' but
297:                // is probably not worth handling at this point. If it does come up, we may need to look at implementing some
298:                // form of state machine.
299:
300:                return line.matches("\\*+ {2}.+ {2}\\*+");
301:            }
302:
303:            protected String[] getCommandLine(Date lastBuild, Date now)
304:                    throws IOException {
305:                Commandline commandline = new Commandline();
306:                String execCommand = (ssDir != null) ? new File(ssDir, "ss.exe")
307:                        .getCanonicalPath()
308:                        : "ss.exe";
309:
310:                commandline.setExecutable(execCommand);
311:                commandline.createArgument("history");
312:                commandline.createArgument(vssPath);
313:                commandline.createArgument("-R");
314:                commandline.createArgument("-Vd" + formatDateForVSS(now) + "~"
315:                        + formatDateForVSS(lastBuild));
316:                commandline.createArgument("-Y" + login);
317:                commandline.createArgument("-I-N");
318:                commandline.createArgument("-O" + getTempFile().getName());
319:
320:                LOG.info("Command line to execute: " + commandline);
321:
322:                return commandline.getCommandline();
323:            }
324:
325:            /**
326:             * Format a date for vss in the format specified by the dateFormat. By default, this is in the form
327:             * <code>12/21/2000;8:14A</code> (vss doesn't like the m in am or pm). This format can be changed with
328:             * <code>setDateFormat()</code>
329:             *
330:             * @param date
331:             *            Date to format.
332:             * @return String of date in format that VSS requires.
333:             * @see #setDateFormat
334:             */
335:            private String formatDateForVSS(Date date) {
336:                String vssFormattedDate = new SimpleDateFormat(dateFormat + ";"
337:                        + timeFormat, Locale.US).format(date);
338:                if (timeFormat.endsWith("a")) {
339:                    return vssFormattedDate.substring(0, vssFormattedDate
340:                            .length() - 1);
341:                }
342:
343:                return vssFormattedDate;
344:            }
345:
346:            /**
347:             * Parse individual VSS history entry
348:             *
349:             * @param entry
350:             */
351:            protected Modification handleEntry(List entry) {
352:                LOG.debug("VSS history entry BEGIN");
353:                for (Iterator i = entry.iterator(); i.hasNext();) {
354:                    LOG.debug("entry: " + i.next());
355:                }
356:                LOG.debug("VSS history entry END");
357:
358:                final String labelDelimiter = "**********************";
359:                boolean isLabelEntry = labelDelimiter.equals(entry.get(0));
360:
361:                if (isLabelEntry) {
362:                    LOG.debug("this is a label; ignoring this entry");
363:                    return null;
364:                }
365:
366:                // but need to adjust for cases where Label: line exists
367:                //
368:                // ***** DateChooser.java *****
369:                // Version 8
370:                // Label: "Completely new version!"
371:                // User: Arass Date: 10/21/02 Time: 12:48p
372:                // Checked in $/code/development/src/org/ets/cbtidg/common/gui
373:                // Comment: This is where I add a completely new, but alot nicer
374:                // version of the date chooser.
375:                // Label comment:
376:
377:                int nameAndDateIndex = 2;
378:                if (((String) entry.get(0)).startsWith("***************** ")) {
379:                    nameAndDateIndex = 1;
380:                }
381:                String nameAndDateLine = (String) entry.get(nameAndDateIndex);
382:                if (nameAndDateLine.startsWith("Label:")) {
383:                    nameAndDateIndex++;
384:                    nameAndDateLine = (String) entry.get(nameAndDateIndex);
385:                    LOG.debug("adjusting for the line that starts with Label");
386:                }
387:
388:                Modification modification = new Modification("vss");
389:                modification.userName = parseUser(nameAndDateLine);
390:                modification.modifiedTime = parseDate(nameAndDateLine);
391:
392:                String folderLine = (String) entry.get(0);
393:                int fileIndex = nameAndDateIndex + 1;
394:                String fileLine = (String) entry.get(fileIndex);
395:                LOG.debug("File line is: " + fileLine);
396:
397:                if (fileLine.startsWith("Checked in")) {
398:                    LOG.debug("this is a checkin");
399:                    int commentIndex = fileIndex + 1;
400:                    modification.comment = parseComment(entry, commentIndex);
401:                    String fileName = folderLine.substring(7, folderLine
402:                            .indexOf("  *"));
403:                    String folderName = fileLine.substring(12);
404:
405:                    Modification.ModifiedFile modfile = modification
406:                            .createModifiedFile(fileName, folderName);
407:                    modfile.action = "checkin";
408:                } else if (fileLine.endsWith("Created")) {
409:                    modification.type = "create";
410:                    LOG.debug("this folder was created");
411:                } else {
412:                    String fileName;
413:                    String folderName;
414:
415:                    if (nameAndDateIndex == 1) {
416:                        folderName = vssPath;
417:                    } else {
418:                        folderName = vssPath
419:                                + "\\"
420:                                + folderLine.substring(7, folderLine
421:                                        .indexOf("  *"));
422:                    }
423:                    int lastSpace = fileLine.lastIndexOf(" ");
424:                    if (lastSpace != -1) {
425:                        fileName = fileLine.substring(0, lastSpace);
426:                    } else {
427:                        fileName = fileLine;
428:                        if (fileName.equals("Branched")) {
429:                            LOG
430:                                    .debug("Branched file, ignoring as branch directory is handled separately");
431:                            return null;
432:                        }
433:                    }
434:
435:                    Modification.ModifiedFile modfile = modification
436:                            .createModifiedFile(fileName, folderName);
437:
438:                    if (fileLine.endsWith("added")) {
439:                        modfile.action = "add";
440:                    } else if (fileLine.endsWith("deleted")) {
441:                        modfile.action = "delete";
442:                        properties.deletionFound();
443:                    } else if (fileLine.endsWith("destroyed")) {
444:                        modfile.action = "destroy";
445:                        properties.deletionFound();
446:                    } else if (fileLine.endsWith("recovered")) {
447:                        modfile.action = "recover";
448:                    } else if (fileLine.endsWith("shared")) {
449:                        modfile.action = "share";
450:                    } else if (fileLine.endsWith("branched")) {
451:                        modfile.action = "branch";
452:                    } else if (fileLine.indexOf(" renamed to ") != -1) {
453:                        modfile.fileName = fileLine;
454:                        modfile.action = "rename";
455:                        properties.deletionFound();
456:                    } else if (fileLine.startsWith("Labeled")) {
457:                        return null;
458:                    } else {
459:                        LOG.warn("Don't know how to handle this line: "
460:                                + fileLine);
461:                        return null;
462:                    }
463:                }
464:
465:                return modification;
466:            }
467:
468:            /**
469:             * Parse comment from VSS history (could be multi-line)
470:             *
471:             * @param commentList
472:             * @return the comment
473:             */
474:            private String parseComment(List commentList, int commentIndex) {
475:                StringBuffer comment = new StringBuffer();
476:                comment.append(commentList.get(commentIndex)).append(" ");
477:                for (int i = commentIndex + 1; i < commentList.size(); i++) {
478:                    comment.append(commentList.get(i)).append(" ");
479:                }
480:
481:                return comment.toString().trim();
482:            }
483:
484:            /**
485:             * Parse date/time from VSS file history The nameAndDateLine will look like <br>
486:             * <code>User: Etucker      Date:  6/26/01   Time: 11:53a</code><br>
487:             * Sometimes also this<br>
488:             * <code>User: Aaggarwa     Date:  6/29/:1   Time:  3:40p</code><br>
489:             * Note the ":" instead of a "0"
490:             *
491:             * @param nameAndDateLine
492:             * @return Date in form "'Date: 'MM/dd/yy 'Time: 'hh:mma", or a different form based on dateFormat
493:             * @see #setDateFormat
494:             */
495:            public Date parseDate(String nameAndDateLine) {
496:                String dateAndTime = nameAndDateLine.substring(nameAndDateLine
497:                        .indexOf("Date: "));
498:
499:                int indexOfColon = dateAndTime.indexOf("/:");
500:                if (indexOfColon != -1) {
501:                    dateAndTime = dateAndTime.substring(0, indexOfColon)
502:                            + dateAndTime.substring(indexOfColon,
503:                                    indexOfColon + 2).replace(':', '0')
504:                            + dateAndTime.substring(indexOfColon + 2);
505:                }
506:
507:                try {
508:                    Date lastModifiedDate;
509:                    if (timeFormat.endsWith("a")) {
510:                        lastModifiedDate = vssDateTimeFormat.parse(dateAndTime
511:                                .trim()
512:                                + "m");
513:                    } else {
514:                        lastModifiedDate = vssDateTimeFormat.parse(dateAndTime
515:                                .trim());
516:                    }
517:
518:                    return lastModifiedDate;
519:                } catch (ParseException pe) {
520:                    LOG.warn("Could not parse date", pe);
521:                    return null;
522:                }
523:            }
524:
525:            /**
526:             * Parse username from VSS file history
527:             *
528:             * @param userLine
529:             * @return the user name who made the modification
530:             */
531:            public String parseUser(String userLine) {
532:                final int userIndex = "User: ".length();
533:
534:                return userLine.substring(userIndex,
535:                        userLine.indexOf("Date: ") - 1).trim();
536:            }
537:
538:            /**
539:             * Constructs the vssDateTimeFormat based on the dateFormat for this element.
540:             *
541:             * @see #setDateFormat
542:             */
543:            private void constructVssDateTimeFormat() {
544:                vssDateTimeFormat = new SimpleDateFormat("'Date: '"
545:                        + dateFormat + "   'Time: '" + timeFormat, Locale.US);
546:            }
547:
548:            protected SimpleDateFormat getVssDateTimeFormat() {
549:                return vssDateTimeFormat;
550:            }
551:
552:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.