Source Code Cross Referenced for UCM.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-2003, 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
009:         * modification, are permitted provided that the following conditions
010:         * are met:
011:         *
012:         *     + Redistributions of source code must retain the above copyright
013:         *       notice, this list of conditions and the following disclaimer.
014:         *
015:         *     + Redistributions in binary form must reproduce the above
016:         *       copyright notice, this list of conditions and the following
017:         *       disclaimer in the documentation and/or other materials provided
018:         *       with the distribution.
019:         *
020:         *     + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
021:         *       names of its contributors may be used to endorse or promote
022:         *       products derived from this software without specific prior
023:         *       written permission.
024:         *
025:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
026:         * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
027:         * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
028:         * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
029:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
030:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
031:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
032:         * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
033:         * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
034:         * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
035:         * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
036:         ********************************************************************************/package net.sourceforge.cruisecontrol.sourcecontrols;
037:
038:        import java.io.BufferedReader;
039:        import java.io.IOException;
040:        import java.io.InputStream;
041:        import java.io.InputStreamReader;
042:        import java.text.DateFormat;
043:        import java.text.ParseException;
044:        import java.text.SimpleDateFormat;
045:        import java.util.ArrayList;
046:        import java.util.Arrays;
047:        import java.util.Date;
048:        import java.util.HashMap;
049:        import java.util.Iterator;
050:        import java.util.List;
051:        import java.util.Map;
052:        import java.util.StringTokenizer;
053:
054:        import net.sourceforge.cruisecontrol.CruiseControlException;
055:        import net.sourceforge.cruisecontrol.Modification;
056:        import net.sourceforge.cruisecontrol.SourceControl;
057:        import net.sourceforge.cruisecontrol.util.Commandline;
058:        import net.sourceforge.cruisecontrol.util.CommandlineUtil;
059:        import net.sourceforge.cruisecontrol.util.ValidationHelper;
060:
061:        import org.apache.log4j.Logger;
062:        import org.jdom.Element;
063:
064:        /**
065:         * This class implements the SourceControlElement methods for ClearCase UCM.
066:         *
067:         * @author <a href="mailto:kevin.lee@buildmeister.com">Kevin Lee</a>
068:         * @author Alex Batlin
069:         */
070:        public class UCM implements  SourceControl {
071:
072:            private static final Logger LOG = Logger.getLogger(UCM.class);
073:
074:            private String stream;
075:            private String viewPath;
076:            private boolean multiVob;
077:            private boolean contributors = true;
078:            private boolean rebases = false;
079:
080:            private SourceControlProperties properties = new SourceControlProperties();
081:
082:            private final SimpleDateFormat inputDateFormat = new SimpleDateFormat(
083:                    "dd-MMMM-yyyy.HH:mm:ss");
084:            private final SimpleDateFormat outputDateFormat = new SimpleDateFormat(
085:                    "yyyyMMdd.HHmmss");
086:
087:            private String pvob;
088:
089:            /**
090:             * Unlikely combination of characters to separate fields in a ClearCase query
091:             */
092:            static final String DELIMITER = "#~#";
093:
094:            /**
095:             * Even more unlikely combination of characters to indicate end of one line in query. Carriage return (\n) can be
096:             * used in comments and so is not available to us.
097:             */
098:            static final String END_OF_STRING_DELIMITER = "@#@#@#@#@#@#@#@#@#@#@#@";
099:
100:            public Map getProperties() {
101:                return properties.getPropertiesAndReset();
102:            }
103:
104:            public void validate() throws CruiseControlException {
105:                ValidationHelper.assertIsSet(stream, "stream", this .getClass());
106:                ValidationHelper.assertIsSet(viewPath, "viewpath", this 
107:                        .getClass());
108:
109:                if (isRebases()) {
110:                    ValidationHelper.assertIsSet(pvob, "pvob", this .getClass());
111:                }
112:            }
113:
114:            /**
115:             * get which stream is being checked
116:             *
117:             * @return the name of the stream being checked
118:             */
119:            public String getStream() {
120:                return stream;
121:            }
122:
123:            /**
124:             * set the stream to check for changes
125:             *
126:             * @param stream
127:             *            the stream to be checked (via its underlying branch)
128:             */
129:            public void setStream(String stream) {
130:                this .stream = stream;
131:            }
132:
133:            /**
134:             * get the starting point path in a view to check for changes
135:             *
136:             * @return path inside a view
137:             */
138:            public String getViewPath() {
139:                return viewPath;
140:            }
141:
142:            /**
143:             * set the starting point path in a view to check for changes
144:             *
145:             * @param viewPath
146:             *            path inside a view
147:             */
148:            public void setViewPath(String viewPath) {
149:                this .viewPath = viewPath;
150:            }
151:
152:            /**
153:             * get whether the view contains multiple vobs
154:             *
155:             * @return true, if the view contains multiple vobs, else false
156:             */
157:            public boolean isMultiVob() {
158:                return this .multiVob;
159:            }
160:
161:            /**
162:             * set whether the view contains multiple vobs
163:             *
164:             * @param multiVob boolean indicating whether the view contains multiple vobs
165:             */
166:            public void setMultiVob(boolean multiVob) {
167:                this .multiVob = multiVob;
168:            }
169:
170:            /**
171:             * Set the name of the pvob to use for queries.
172:             *
173:             * @param pvob
174:             *            the pvob
175:             */
176:            public void setPvob(String pvob) {
177:                this .pvob = pvob;
178:            }
179:
180:            /**
181:             * Get the name of the pvob to use for queries.
182:             *
183:             * @return The name of the pvob
184:             */
185:            public String getPvob() {
186:                return this .pvob;
187:            }
188:
189:            /**
190:             * Gets whether rebases are to be reported as changes.
191:             *
192:             * @return true, if rebases are to be reported, else false
193:             */
194:            public boolean isRebases() {
195:                return this .rebases;
196:            }
197:
198:            /**
199:             * Sets whether rebases of the integration stream are reported as changes.
200:             *
201:             * @param rebases
202:             *            boolean indicating whether rebases are to be reported as changes
203:             */
204:            public void setRebases(boolean rebases) {
205:                this .rebases = rebases;
206:            }
207:
208:            /**
209:             * get whether contributors are to be found
210:             *
211:             * @return true, if contributors are to be found, else false
212:             */
213:            public boolean isContributors() {
214:                return contributors;
215:            }
216:
217:            /**
218:             * set whether contributors are to be found
219:             *
220:             * @param contributors
221:             *            boolean indicating whether contributors are to be found
222:             */
223:            public void setContributors(boolean contributors) {
224:                this .contributors = contributors;
225:            }
226:
227:            /**
228:             * set the name of the property that will be set if modifications are found
229:             *
230:             * @param property
231:             *            The name of the property to set
232:             */
233:            public void setProperty(String property) {
234:                properties.assignPropertyName(property);
235:            }
236:
237:            /**
238:             * Get a List of modifications detailing all the changes between now and the last build. Return this as an element.
239:             * It is not necessary for sourcecontrols to actually do anything other than returning a chunk of XML data back.
240:             *
241:             * @param lastBuild
242:             *            time of last build
243:             * @param now
244:             *            time this build started
245:             * @return a list of XML elements that contains data about the modifications that took place. If no changes, this
246:             *         method returns an empty list.
247:             */
248:            public List getModifications(Date lastBuild, Date now) {
249:                String lastBuildDate = inputDateFormat.format(lastBuild);
250:                String nowDate = inputDateFormat.format(now);
251:                properties.put("ucmlastbuild", lastBuildDate);
252:                properties.put("ucmnow", nowDate);
253:                List mods = new ArrayList();
254:                try {
255:                    HashMap activityNames = collectActivitiesSinceLastBuild(lastBuildDate);
256:                    if (activityNames.size() == 0) {
257:                        return mods;
258:                    }
259:                    mods = describeAllActivities(activityNames);
260:                } catch (Exception e) {
261:                    LOG.error("Command failed to execute succesfully", e);
262:                }
263:
264:                if (this .isRebases()) {
265:                    try {
266:                        Commandline commandline = buildDetectRebasesCommand(lastBuildDate);
267:                        commandline.setWorkingDirectory(viewPath);
268:                        InputStream cmdStream = CommandlineUtil
269:                                .streamOutput(commandline);
270:
271:                        try {
272:                            mods.addAll(parseRebases(cmdStream));
273:                        } finally {
274:                            cmdStream.close();
275:                        }
276:                    } catch (Exception e) {
277:                        LOG.error(
278:                                "Error in executing the Clear Case command : ",
279:                                e);
280:                    }
281:                }
282:
283:                // If modifications were found, set the property
284:                if (!mods.isEmpty()) {
285:                    properties.modificationFound();
286:                }
287:
288:                return mods;
289:            }
290:
291:            /**
292:             * get all the activities on the stream since the last build date
293:             */
294:            private HashMap collectActivitiesSinceLastBuild(String lastBuildDate) {
295:
296:                LOG.debug("Last build time was: " + lastBuildDate);
297:
298:                HashMap activityMap = new HashMap();
299:
300:                Commandline commandLine = buildListStreamCommand(lastBuildDate);
301:                LOG.debug("Executing: " + commandLine);
302:
303:                try {
304:                    commandLine.setWorkingDirectory(viewPath);
305:                    InputStream cmdStream = CommandlineUtil
306:                            .streamOutput(commandLine);
307:
308:                    try {
309:                        InputStreamReader isr = new InputStreamReader(cmdStream);
310:                        BufferedReader br = new BufferedReader(isr);
311:                        String line;
312:
313:                        while (((line = br.readLine()) != null)
314:                                && (!br.equals(""))) {
315:                            String[] details = getDetails(line);
316:                            if (details[0].equals("mkbranch")
317:                                    || details[0].equals("rmbranch")
318:                                    || details[0].equals("rmver")) {
319:                                // if type is create/remove branch then skip
320:                            } else {
321:                                String activityName = details[1];
322:                                String activityDate = details[2];
323:                                // assume the latest change for an activity is listed first
324:                                if (!activityMap.containsKey(activityName)) {
325:                                    LOG.debug("Found activity name: "
326:                                            + activityName + "; date: "
327:                                            + activityDate);
328:                                    activityMap.put(activityName, activityDate);
329:                                }
330:                            }
331:                        }
332:                    } finally {
333:                        cmdStream.close();
334:                    }
335:                } catch (IOException e) {
336:                    LOG.error("IO Error executing ClearCase lshistory command",
337:                            e);
338:                } catch (CruiseControlException e) {
339:                    LOG
340:                            .error(
341:                                    "Interrupt Error executing ClearCase lshistory command",
342:                                    e);
343:                }
344:
345:                return activityMap;
346:            }
347:
348:            private String[] getDetails(String line) {
349:                // replacing line.split("~#~") for jdk 1.3
350:                ArrayList details = new ArrayList();
351:                String delimiter = "~#~";
352:                int startIndex = 0;
353:                int index = 0;
354:                while (index != -1) {
355:                    String detail;
356:                    index = line.indexOf(delimiter, startIndex);
357:                    if (index == -1) {
358:                        detail = line.substring(startIndex, line.length());
359:                    } else {
360:                        detail = line.substring(startIndex, index);
361:                    }
362:                    details.add(detail);
363:                    startIndex = index + delimiter.length();
364:                }
365:
366:                return (String[]) details.toArray(new String[] {});
367:            }
368:
369:            /**
370:             * construct a command to get all the activities on the specified stream
371:             */
372:            public Commandline buildListStreamCommand(String lastBuildDate) {
373:                Commandline commandLine = new Commandline();
374:                if (isMultiVob()) {
375:                    try {
376:                        commandLine.setWorkingDirectory(getViewPath());
377:                    } catch (CruiseControlException e) {
378:                        LOG.error("Error in setting workdirectory", e);
379:                    }
380:                }
381:                commandLine.setExecutable("cleartool");
382:                commandLine.createArgument("lshistory");
383:                commandLine.createArguments("-branch", getStream());
384:                if (isMultiVob()) {
385:                    commandLine.createArgument("-avobs");
386:                } else {
387:                    commandLine.createArgument("-r");
388:                }
389:                commandLine.createArgument("-nco");
390:                commandLine.createArguments("-since", lastBuildDate);
391:                commandLine.createArguments("-fmt",
392:                        "%o~#~%[activity]Xp~#~%Nd\n");
393:                if (!isMultiVob()) {
394:                    commandLine.createArgument(getViewPath());
395:                }
396:                return commandLine;
397:            }
398:
399:            /**
400:             * get all the activities on the stream since the last build date
401:             */
402:            private List describeAllActivities(HashMap activityNames) {
403:
404:                ArrayList activityList = new ArrayList();
405:
406:                Iterator it = activityNames.entrySet().iterator();
407:                while (it.hasNext()) {
408:                    Map.Entry activity = (Map.Entry) it.next();
409:                    String activityID = activity.getKey().toString();
410:                    String activityDate = activity.getValue().toString();
411:                    UCMModification activityMod = describeActivity(activityID,
412:                            activityDate);
413:                    activityList.add(activityMod);
414:
415:                    // check for contributor activities
416:                    if (activityMod.comment.startsWith("deliver ")
417:                            && isContributors()) {
418:                        List contribList;
419:                        contribList = describeContributors(activityID);
420:                        Iterator contribIter = contribList.iterator();
421:                        while (contribIter.hasNext()) {
422:                            String contribName = contribIter.next().toString();
423:                            UCMModification contribMod = describeActivity(
424:                                    contribName, activityDate);
425:                            // prefix type to make it stand out in Build Results report
426:                            contribMod.type = "contributor";
427:                            LOG.debug("Found contributor name: " + contribName
428:                                    + "; date: " + activityDate);
429:                            activityList.add(contribMod);
430:                        }
431:                    }
432:                }
433:
434:                return activityList;
435:            }
436:
437:            /**
438:             * get all the activities on the stream since the last build date
439:             */
440:            private UCMModification describeActivity(String activityID,
441:                    String activityDate) {
442:
443:                UCMModification mod = new UCMModification();
444:
445:                Commandline commandLine = buildDescribeActivityCommand(activityID);
446:                LOG.debug("Executing: " + commandLine);
447:
448:                try {
449:                    commandLine.setWorkingDirectory(viewPath);
450:                    InputStream cmdStream = CommandlineUtil
451:                            .streamOutput(commandLine);
452:
453:                    try {
454:                        InputStreamReader isr = new InputStreamReader(cmdStream);
455:                        BufferedReader br = new BufferedReader(isr);
456:                        String line;
457:
458:                        while (((line = br.readLine()) != null)
459:                                && (!br.equals(""))) {
460:                            String[] details = getDetails(line);
461:                            try {
462:                                mod.modifiedTime = outputDateFormat
463:                                        .parse(activityDate);
464:                            } catch (ParseException e) {
465:                                LOG.error("Error parsing modification date");
466:                                mod.modifiedTime = new Date();
467:                            }
468:                            mod.type = "activity";
469:                            // counter for UCM without ClearQuest
470:                            if (details[0].equals("")) {
471:                                mod.revision = details[3];
472:                            } else {
473:                                mod.revision = details[0];
474:                            }
475:                            mod.crmtype = details[1];
476:                            mod.userName = details[2];
477:                            mod.comment = details[3];
478:                        }
479:                    } finally {
480:                        cmdStream.close();
481:                    }
482:                } catch (IOException e) {
483:                    LOG.error("IO Error executing ClearCase describe command",
484:                            e);
485:                } catch (CruiseControlException e) {
486:                    LOG
487:                            .error(
488:                                    "Interrupt error executing ClearCase describe command",
489:                                    e);
490:                }
491:
492:                return mod;
493:            }
494:
495:            /**
496:             * construct a command to get all the activities on the specified stream
497:             */
498:            public Commandline buildDescribeActivityCommand(String activityID) {
499:                Commandline commandLine = new Commandline();
500:                commandLine.setExecutable("cleartool");
501:                commandLine.createArgument("describe");
502:                commandLine
503:                        .createArguments("-fmt",
504:                                "%[crm_record_id]p~#~%[crm_record_type]p~#~%u~#~%[headline]p~#~");
505:                commandLine.createArgument(activityID);
506:                return commandLine;
507:            }
508:
509:            /**
510:             * get all the activities on the stream since the last build date
511:             */
512:            private List describeContributors(String activityName) {
513:
514:                ArrayList contribList = new ArrayList();
515:                Commandline commandLine = buildListContributorsCommand(activityName);
516:                LOG.debug("Executing: " + commandLine);
517:
518:                try {
519:                    commandLine.setWorkingDirectory(viewPath);
520:                    InputStream cmdStream = CommandlineUtil
521:                            .streamOutput(commandLine);
522:
523:                    try {
524:                        InputStreamReader isr = new InputStreamReader(cmdStream);
525:                        BufferedReader br = new BufferedReader(isr);
526:                        String line;
527:
528:                        while ((line = br.readLine()) != null) {
529:                            String[] contribs = splitOnSpace(line);
530:                            for (int i = 0; i < contribs.length; i++) {
531:                                contribList.add(contribs[i]);
532:                            }
533:                        }
534:                    } finally {
535:                        cmdStream.close();
536:                    }
537:                } catch (IOException e) {
538:                    LOG
539:                            .error(
540:                                    "IO Error executing ClearCase describe contributors command",
541:                                    e);
542:                } catch (CruiseControlException e) {
543:                    LOG
544:                            .error(
545:                                    "Interrupt Error executing ClearCase describe contributors command",
546:                                    e);
547:                }
548:
549:                return contribList;
550:            }
551:
552:            private String[] splitOnSpace(String string) {
553:                return string.split(" ");
554:            }
555:
556:            /**
557:             * construct a command to get all the activities on the specified stream
558:             */
559:            public Commandline buildListContributorsCommand(String activityID) {
560:                Commandline commandLine = new Commandline();
561:                commandLine.setExecutable("cleartool");
562:                commandLine.createArgument("describe");
563:                commandLine.createArguments("-fmt", "\"%[contrib_acts]Xp\"");
564:                commandLine.createArgument(activityID);
565:                return commandLine;
566:            }
567:
568:            protected Commandline buildDetectRebasesCommand(String lastBuildDate) {
569:                Commandline commandLine = new Commandline();
570:                commandLine.setExecutable("cleartool");
571:                commandLine.createArgument().setValue("lshistory");
572:                commandLine.createArgument().setValue("-since");
573:                commandLine.createArgument().setValue(lastBuildDate);
574:                commandLine.createArgument().setValue("-minor");
575:                commandLine.createArgument().setValue("-fmt");
576:                String format = "%u" + DELIMITER + "%Nd" + DELIMITER + "%o"
577:                        + DELIMITER + "%Nc" + END_OF_STRING_DELIMITER + "\\n";
578:                commandLine.createArgument().setValue(format);
579:                commandLine.createArgument().setValue(
580:                        "stream:" + stream + "@" + pvob);
581:                return commandLine;
582:            }
583:
584:            /**
585:             * Parses the given input stream to construct the modifications list. The stream is expected to be the result of
586:             * listing the history of a UCM stream. Rebases are then detected by delegating to
587:             * {@link #parseRebaseEntry(String)}.
588:             * Package-private to make it available to the unit test.
589:             *
590:             * @param input
591:             *            the stream to parse
592:             * @return a list of modification elements
593:             * @exception IOException
594:             */
595:            List parseRebases(InputStream input) throws IOException {
596:                ArrayList modifications = new ArrayList();
597:                BufferedReader reader = new BufferedReader(
598:                        new InputStreamReader(input));
599:                String ls = System.getProperty("line.separator");
600:
601:                String line;
602:                StringBuffer lines = new StringBuffer();
603:
604:                while ((line = reader.readLine()) != null) {
605:                    if (lines.length() != 0) {
606:                        lines.append(ls);
607:                    }
608:                    lines.append(line);
609:                    Modification mod = null;
610:
611:                    if (lines.indexOf(END_OF_STRING_DELIMITER) > -1) {
612:                        mod = parseRebaseEntry(lines.substring(0, lines
613:                                .indexOf(END_OF_STRING_DELIMITER)));
614:                        lines = new StringBuffer();
615:                    }
616:
617:                    if (mod != null) {
618:                        modifications.add(mod);
619:                    }
620:                }
621:
622:                return modifications;
623:            }
624:
625:            /**
626:             * Parses a single line from the reader. Each line contains a signe revision with the format : <br>
627:             * username#~#date_of_revision#~#operation_type#~#comments <br>
628:             * <p>
629:             * This method looks for operations of type rmhlink and mkhlink where the hyperlink name begins with "UseBaseline".
630:             * These represent changes in the baseline dependencies of the stream.
631:             * </p>
632:             *
633:             * @param line
634:             *            the line to parse
635:             * @return a modification element corresponding to the given line
636:             */
637:            Modification parseRebaseEntry(String line) {
638:                LOG.debug("parsing entry: " + line);
639:                String[] tokens = tokenizeEntry(line);
640:                if (tokens == null) {
641:                    return null;
642:                }
643:                String username = tokens[0].trim();
644:                String timeStamp = tokens[1].trim();
645:                String operationType = tokens[2].trim();
646:                String comment = tokens[3].trim();
647:
648:                Modification mod = null;
649:
650:                // Rebases show up as mkhlink and rmhlink operations
651:                if (operationType.equals("mkhlink")
652:                        || operationType.equals("rmhlink")) {
653:                    // Parse the hyperlink name out of the comment field, then
654:                    // get more information on that hyperlink
655:                    mod = new Modification();
656:                    String linkName = parseLinkName(comment);
657:
658:                    // If this isn't a "UseBaseline" hyperlink, we're not interested
659:                    if (!linkName.startsWith("UseBaseline")) {
660:                        return null;
661:                    }
662:
663:                    Hyperlink link = getHyperlink(linkName);
664:                    StringBuffer modComment = new StringBuffer();
665:                    mod.type = "ucmdependency";
666:
667:                    if (operationType.equals("mkhlink")) {
668:                        modComment.append("Added dependency");
669:                    } else {
670:                        modComment.append("Removed dependency");
671:                    }
672:
673:                    if (link.getFrom().length() > 0) {
674:                        modComment.append(" of ");
675:                        modComment.append(link.getFrom());
676:                    }
677:
678:                    if (link.getTo().length() > 0) {
679:                        modComment.append(" on ");
680:                        modComment.append(link.getTo());
681:                        mod.revision = link.getTo();
682:                    } else {
683:                        // Don't know what the revision was to
684:                        mod.revision = "";
685:                    }
686:
687:                    mod.comment = modComment.toString();
688:                    mod.userName = username;
689:
690:                    try {
691:                        mod.modifiedTime = outputDateFormat.parse(timeStamp);
692:                    } catch (ParseException e) {
693:                        LOG.error("Error parsing modification date", e);
694:                        mod.modifiedTime = new Date();
695:                    }
696:
697:                    properties.modificationFound();
698:                }
699:
700:                return mod;
701:            }
702:
703:            private Hyperlink getHyperlink(String linkName) {
704:                Commandline commandline = buildGetHyperlinkCommandline(linkName);
705:
706:                try {
707:                    commandline.setWorkingDirectory(viewPath);
708:                    InputStream cmdStream = CommandlineUtil
709:                            .streamOutput(commandline);
710:                    Hyperlink link = null;
711:
712:                    try {
713:                        link = parseHyperlinkDescription(cmdStream);
714:                    } finally {
715:                        cmdStream.close();
716:                    }
717:
718:                    return link;
719:                } catch (Exception e) {
720:                    LOG
721:                            .error(
722:                                    "Error in executing the Clear Case command : ",
723:                                    e);
724:                    return new Hyperlink();
725:                }
726:            }
727:
728:            protected Commandline buildGetHyperlinkCommandline(String linkName) {
729:                Commandline commandline = new Commandline();
730:                commandline.setExecutable("cleartool");
731:                commandline.createArgument().setValue("describe");
732:                commandline.createArgument().setValue(
733:                        "hlink:" + linkName + "@" + pvob);
734:                return commandline;
735:            }
736:
737:            Hyperlink parseHyperlinkDescription(InputStream input)
738:                    throws IOException {
739:                BufferedReader reader = new BufferedReader(
740:                        new InputStreamReader(input));
741:
742:                String lastLine = "";
743:                String line = reader.readLine();
744:
745:                // If the hyperlink wasn't found, cleartool will return no output, giving
746:                // us an empty stream. This will end up returning an empty string.
747:                while (line != null) {
748:                    lastLine = line;
749:                    line = reader.readLine();
750:                }
751:
752:                Hyperlink link = new Hyperlink();
753:                StringTokenizer tokens = new StringTokenizer(lastLine, " ");
754:
755:                if (!tokens.hasMoreTokens()) {
756:                    return link;
757:                }
758:
759:                // Discard the first one, that's the link name
760:                tokens.nextToken();
761:
762:                if (!tokens.hasMoreTokens()) {
763:                    return link;
764:                }
765:
766:                link.setFrom(tokens.nextToken());
767:
768:                // Discard "->"
769:                if (!tokens.hasMoreTokens()) {
770:                    return link;
771:                }
772:
773:                tokens.nextToken();
774:
775:                if (!tokens.hasMoreTokens()) {
776:                    return link;
777:                }
778:
779:                link.setTo(tokens.nextToken());
780:
781:                return link;
782:            }
783:
784:            String parseLinkName(String comment) {
785:                // Parse on spaces and quotes (to eliminate them)
786:                StringTokenizer tokens = new StringTokenizer(comment, " \"");
787:                String link = "";
788:                String token = "";
789:
790:                // The next-to-last token should contain the hyperlink name
791:                while (tokens.hasMoreTokens()) {
792:                    link = token;
793:                    token = tokens.nextToken();
794:                }
795:
796:                int index = link.lastIndexOf('@');
797:
798:                if (index != -1) {
799:                    // Remove the VOB-qualifier from the end. We'll add it back ourselves
800:                    return link.substring(0, link.lastIndexOf('@'));
801:                } else {
802:                    // Return it unmodified
803:                    return link;
804:                }
805:            }
806:
807:            private String[] tokenizeEntry(String line) {
808:                int maxTokens = 4;
809:                int minTokens = maxTokens - 1; // comment may be absent.
810:                String[] tokens = new String[maxTokens];
811:                Arrays.fill(tokens, "");
812:                int tokenIndex = 0;
813:                for (int oldIndex = 0, i = line.indexOf(DELIMITER, 0); true; oldIndex = i
814:                        + DELIMITER.length(), i = line.indexOf(DELIMITER,
815:                        oldIndex), tokenIndex++) {
816:                    if (tokenIndex > maxTokens) {
817:                        LOG.debug("Too many tokens; skipping entry");
818:                        return null;
819:                    }
820:                    if (i == -1) {
821:                        tokens[tokenIndex] = line.substring(oldIndex);
822:                        break;
823:                    } else {
824:                        tokens[tokenIndex] = line.substring(oldIndex, i);
825:                    }
826:                }
827:                if (tokenIndex < minTokens) {
828:                    LOG.debug("Not enough tokens; skipping entry");
829:                    return null;
830:                }
831:                return tokens;
832:            }
833:
834:            /**
835:             * Class to represent ClearCase hyperlinks.
836:             */
837:            class Hyperlink {
838:                private String from = "";
839:                private String to = "";
840:
841:                public String getFrom() {
842:                    return this .from;
843:                }
844:
845:                public void setFrom(String from) {
846:                    this .from = from;
847:                }
848:
849:                public String getTo() {
850:                    return this .to;
851:                }
852:
853:                public void setTo(String to) {
854:                    this .to = to;
855:                }
856:            }
857:
858:            /**
859:             * class to hold UCMModifications
860:             */
861:            private static class UCMModification extends Modification {
862:                private static final String TAGNAME_CRMTYPE = "crmtype";
863:
864:                public String crmtype;
865:
866:                public int compareTo(Object o) {
867:                    UCMModification modification = (UCMModification) o;
868:                    return getActivitityNumber()
869:                            - modification.getActivitityNumber();
870:                }
871:
872:                public boolean equals(Object o) {
873:                    if (o == null || !(o instanceof  UCMModification)) {
874:                        return false;
875:                    }
876:
877:                    UCMModification modification = (UCMModification) o;
878:                    return getActivitityNumber() == modification
879:                            .getActivitityNumber();
880:                }
881:
882:                public int hashCode() {
883:                    return getActivitityNumber();
884:                }
885:
886:                private int getActivitityNumber() {
887:                    return Integer.parseInt(revision);
888:                }
889:
890:                UCMModification() {
891:                    super ("ucm");
892:                }
893:
894:                public Element toElement(DateFormat formatter) {
895:                    Element modificationElement = super .toElement(formatter);
896:                    Element crmtypeElement = new Element(TAGNAME_CRMTYPE);
897:                    crmtypeElement.addContent(crmtype);
898:                    modificationElement.addContent(crmtypeElement);
899:                    return modificationElement;
900:                }
901:
902:            }
903:
904:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.