KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cruisecontrol > sourcecontrols > UCM


1 /********************************************************************************
2  * CruiseControl, a Continuous Integration Toolkit
3  * Copyright (c) 2001-2003, ThoughtWorks, Inc.
4  * 651 W Washington Ave. Suite 600
5  * Chicago, IL 60661 USA
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * + Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * + Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  *
20  * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
21  * names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior
23  * written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  ********************************************************************************/

37 package net.sourceforge.cruisecontrol.sourcecontrols;
38
39 import net.sourceforge.cruisecontrol.CruiseControlException;
40 import net.sourceforge.cruisecontrol.Modification;
41 import net.sourceforge.cruisecontrol.SourceControl;
42 import net.sourceforge.cruisecontrol.util.Commandline;
43 import net.sourceforge.cruisecontrol.util.StreamPumper;
44 import net.sourceforge.cruisecontrol.util.ValidationHelper;
45 import org.apache.log4j.Logger;
46 import org.jdom.Element;
47
48 import java.io.BufferedReader JavaDoc;
49 import java.io.IOException JavaDoc;
50 import java.io.InputStreamReader JavaDoc;
51 import java.io.PrintWriter JavaDoc;
52 import java.text.DateFormat JavaDoc;
53 import java.text.ParseException JavaDoc;
54 import java.text.SimpleDateFormat JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.Date JavaDoc;
57 import java.util.HashMap JavaDoc;
58 import java.util.Hashtable JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.List JavaDoc;
61 import java.util.Map JavaDoc;
62 import java.util.StringTokenizer JavaDoc;
63
64 /**
65  * This class implements the SourceControlElement methods for ClearCase UCM.
66  *
67  * @author <a HREF="mailto:kevin.lee@buildmeister.com">Kevin Lee</a>
68  * @author Alex Batlin
69  */

70 public class UCM implements SourceControl {
71
72     private static final Logger LOG = Logger.getLogger(UCM.class);
73
74     private String JavaDoc stream;
75     private String JavaDoc viewPath;
76     private String JavaDoc property;
77     private boolean contributors = true;
78
79     /* Date format required by commands passed to ClearCase */
80     private final SimpleDateFormat JavaDoc inDateFormatter =
81             new SimpleDateFormat JavaDoc("dd-MMMM-yyyy.HH:mm:ss");
82
83     /* Date format returned in the output of ClearCase commands. */
84     private final SimpleDateFormat JavaDoc outDateFormatter =
85             new SimpleDateFormat JavaDoc("yyyyMMdd.HHmmss");
86
87     private Hashtable JavaDoc properties = new Hashtable JavaDoc();
88
89     /**
90      * get the properties created via the sourcecontrol
91      *
92      * @return Hastable containing properties
93      */

94     public Map JavaDoc getProperties() {
95         return properties;
96     }
97
98     /**
99      * validate whether enough attributes have been passed
100      *
101      * @throws CruiseControlException
102      */

103     public void validate() throws CruiseControlException {
104         ValidationHelper.assertIsSet(stream, "stream", this.getClass());
105         ValidationHelper.assertIsSet(viewPath, "viewpath", this.getClass());
106     }
107
108     /**
109      * get which stream is being checked
110      *
111      * @return the name of the stream being checked
112      */

113     public String JavaDoc getStream() {
114         return stream;
115     }
116
117     /**
118      * set the stream to check for changes
119      *
120      * @param stream the stream to be checked (via its underlying branch)
121      */

122     public void setStream(String JavaDoc stream) {
123         this.stream = stream;
124     }
125
126     /**
127      * get the starting point path in a view to check for changes
128      *
129      * @return path inside a view
130      */

131     public String JavaDoc getViewPath() {
132         return viewPath;
133     }
134
135     /**
136      * set the starting point path in a view to check for changes
137      *
138      * @param viewPath path inside a view
139      */

140     public void setViewPath(String JavaDoc viewPath) {
141         this.viewPath = viewPath;
142     }
143
144     /**
145      * get whether contributors are to be found
146      *
147      * @return true, if contributors are to be found, else false
148      */

149     public boolean isContributors() {
150         return contributors;
151     }
152
153     /**
154      * set whether contributors are to be found
155      *
156      * @param contributors boolean indicating whether contributors are to be found
157      */

158     public void setContributors(boolean contributors) {
159         this.contributors = contributors;
160     }
161
162     /**
163      * set the name of the property that will be set if modifications are found
164      *
165      * @param property The name of the property to set
166      */

167     public void setProperty(String JavaDoc property) {
168         this.property = property;
169     }
170
171     /**
172      * get the name of the property that will be set if modifications are found
173      *
174      * @return the property name
175      */

176     public String JavaDoc getProperty() {
177         return this.property;
178     }
179
180     /**
181      * Get a List of modifications detailing all the changes between now and
182      * the last build. Return this as an element. It is not neccessary for
183      * sourcecontrols to acctually do anything other than returning a chunch
184      * of XML data back.
185      *
186      * @param lastBuild time of last build
187      * @param now time this build started
188      * @return a list of XML elements that contains data about the modifications
189      * that took place. If no changes, this method returns an empty list.
190      */

191     public List JavaDoc getModifications(Date JavaDoc lastBuild, Date JavaDoc now) {
192         String JavaDoc lastBuildDate = inDateFormatter.format(lastBuild);
193         String JavaDoc nowDate = inDateFormatter.format(now);
194         properties.put("ucmlastbuild", lastBuildDate);
195         properties.put("ucmnow", nowDate);
196         List JavaDoc mods = new ArrayList JavaDoc();
197         try {
198             HashMap JavaDoc activityNames = collectActivitiesSinceLastBuild(lastBuildDate);
199             if (activityNames.size() == 0) {
200                 return mods;
201             }
202             mods = describeAllActivities(activityNames);
203         } catch (Exception JavaDoc e) {
204             LOG.error("Command failed to execute succesfully", e);
205         }
206
207         // If modifications were found, set the property
208
if (!mods.isEmpty() && getProperty() != null) {
209             properties.put(getProperty(), "true");
210         }
211
212         return mods;
213     }
214
215     /*
216      * get all the activities on the stream since the last build date
217      */

218     private HashMap JavaDoc collectActivitiesSinceLastBuild(String JavaDoc lastBuildDate) {
219
220         LOG.debug("Last build time was: " + lastBuildDate);
221
222         HashMap JavaDoc activityMap = new HashMap JavaDoc();
223
224         Commandline commandLine = buildListStreamCommand(lastBuildDate);
225         LOG.debug("Executing: " + commandLine);
226
227         try {
228             Process JavaDoc p = Runtime.getRuntime().exec(commandLine.getCommandline());
229             StreamPumper errorPumper =
230                     new StreamPumper(p.getErrorStream(), new PrintWriter JavaDoc(System.err, true));
231             new Thread JavaDoc(errorPumper).start();
232             InputStreamReader JavaDoc isr = new InputStreamReader JavaDoc(p.getInputStream());
233             BufferedReader JavaDoc br = new BufferedReader JavaDoc(isr);
234             String JavaDoc line;
235
236             while (((line = br.readLine()) != null) && (!br.equals(""))) {
237                 String JavaDoc[] details = getDetails(line);
238                 if (details[0].equals("mkbranch")) {
239                     // if type is create branch then skip
240
} else {
241                     String JavaDoc activityName = details[1];
242                     String JavaDoc activityDate = details[2];
243                     // assume the latest change for an activity is listed first
244
if (!activityMap.containsKey(activityName)) {
245                         LOG.debug("Found activity name: " + activityName + "; date: " + activityDate);
246                         activityMap.put(activityName, activityDate);
247                     }
248                 }
249             }
250
251             p.waitFor();
252             p.getInputStream().close();
253             p.getOutputStream().close();
254             p.getErrorStream().close();
255         } catch (IOException JavaDoc e) {
256             LOG.error("IO Error executing ClearCase lshistory command", e);
257         } catch (InterruptedException JavaDoc e) {
258             LOG.error("Interrupt Error executing ClearCase lshistory command", e);
259         }
260
261         return activityMap;
262     }
263
264     private String JavaDoc[] getDetails(String JavaDoc line) {
265         // replacing line.split("~#~") for jdk 1.3
266
ArrayList JavaDoc details = new ArrayList JavaDoc();
267         String JavaDoc delimiter = "~#~";
268         int startIndex = 0;
269         int index = 0;
270         while (index != -1) {
271             String JavaDoc detail;
272             index = line.indexOf(delimiter, startIndex);
273             if (index == -1) {
274                 detail = line.substring(startIndex, line.length());
275             } else {
276                 detail = line.substring(startIndex, index);
277             }
278             details.add(detail);
279             startIndex = index + delimiter.length();
280         }
281
282         return (String JavaDoc[]) details.toArray(new String JavaDoc[]{});
283     }
284
285     /*
286      * construct a command to get all the activities on the specified stream
287      */

288     public Commandline buildListStreamCommand(String JavaDoc lastBuildDate) {
289         Commandline commandLine = new Commandline();
290         commandLine.setExecutable("cleartool");
291         commandLine.createArgument().setValue("lshistory");
292         commandLine.createArgument().setValue("-branch");
293         commandLine.createArgument().setValue(getStream());
294         commandLine.createArgument().setValue("-r");
295         commandLine.createArgument().setValue("-nco");
296         commandLine.createArgument().setValue("-since");
297         commandLine.createArgument().setValue(lastBuildDate);
298         commandLine.createArgument().setValue("-fmt");
299         commandLine.createArgument().setValue("%o~#~%[activity]Xp~#~%Nd\n");
300         commandLine.createArgument().setValue(getViewPath());
301         return commandLine;
302     }
303
304     /*
305      * get all the activities on the stream since the last build date
306      */

307     private List JavaDoc describeAllActivities(HashMap JavaDoc activityNames) {
308
309         ArrayList JavaDoc activityList = new ArrayList JavaDoc();
310
311         Iterator JavaDoc it = activityNames.entrySet().iterator();
312         while (it.hasNext()) {
313             Map.Entry JavaDoc activity = (Map.Entry JavaDoc) it.next();
314             String JavaDoc activityID = activity.getKey().toString();
315             String JavaDoc activityDate = activity.getValue().toString();
316             UCMModification activityMod = describeActivity(activityID, activityDate);
317             activityList.add(activityMod);
318
319             // check for contributor activities
320
if (activityMod.comment.startsWith("deliver ") && isContributors()) {
321                 List JavaDoc contribList;
322                 contribList = describeContributors(activityID);
323                 Iterator JavaDoc contribIter = contribList.iterator();
324                 while (contribIter.hasNext()) {
325                     String JavaDoc contribName = contribIter.next().toString();
326                     UCMModification contribMod = describeActivity(contribName, activityDate);
327                     // prefix type to make it stand out in Build Results report
328
contribMod.type = "contributor";
329                     LOG.debug("Found contributor name: " + contribName + "; date: " + activityDate);
330                     activityList.add(contribMod);
331                 }
332             }
333         }
334
335         return activityList;
336     }
337
338     /*
339      * get all the activities on the stream since the last build date
340      */

341     private UCMModification describeActivity(String JavaDoc activityID, String JavaDoc activityDate) {
342
343         UCMModification mod = new UCMModification();
344
345         Commandline commandLine = buildDescribeActivityCommand(activityID);
346         LOG.debug("Executing: " + commandLine);
347
348         try {
349             Process JavaDoc p = Runtime.getRuntime().exec(commandLine.getCommandline());
350             StreamPumper errorPumper =
351                     new StreamPumper(p.getErrorStream(), new PrintWriter JavaDoc(System.err, true));
352             new Thread JavaDoc(errorPumper).start();
353             InputStreamReader JavaDoc isr = new InputStreamReader JavaDoc(p.getInputStream());
354             BufferedReader JavaDoc br = new BufferedReader JavaDoc(isr);
355             String JavaDoc line;
356
357             while (((line = br.readLine()) != null) && (!br.equals(""))) {
358                 String JavaDoc[] details = getDetails(line);
359                 try {
360                     mod.modifiedTime = outDateFormatter.parse(activityDate);
361                 } catch (ParseException JavaDoc e) {
362                     LOG.error("Error parsing modification date");
363                 }
364                 mod.type = "activity";
365                 // counter for UCM without ClearQuest
366
if (details[0].equals("")) {
367                     mod.revision = details[3];
368                 } else {
369                     mod.revision = details[0];
370                 }
371                 mod.crmtype = details[1];
372                 mod.userName = details[2];
373                 mod.comment = details[3];
374             }
375
376             p.waitFor();
377             p.getInputStream().close();
378             p.getOutputStream().close();
379             p.getErrorStream().close();
380         } catch (IOException JavaDoc e) {
381             LOG.error("IO Error executing ClearCase describe command", e);
382         } catch (InterruptedException JavaDoc e) {
383             LOG.error("Interrupt error executing ClearCase describe command", e);
384         }
385
386         return mod;
387     }
388
389
390     /*
391     * construct a command to get all the activities on the specified stream
392     */

393     public Commandline buildDescribeActivityCommand(String JavaDoc activityID) {
394         Commandline commandLine = new Commandline();
395         commandLine.setExecutable("cleartool");
396         commandLine.createArgument().setValue("describe");
397         commandLine.createArgument().setValue("-fmt");
398         commandLine.createArgument().setValue("%[crm_record_id]p~#~%[crm_record_type]p~#~%u~#~%[headline]p~#~");
399         commandLine.createArgument().setValue(activityID);
400         return commandLine;
401     }
402
403     /*
404     * get all the activities on the stream since the last build date
405     */

406     private List JavaDoc describeContributors(String JavaDoc activityName) {
407
408         ArrayList JavaDoc contribList = new ArrayList JavaDoc();
409         Commandline commandLine = buildListContributorsCommand(activityName);
410         LOG.debug("Executing: " + commandLine);
411
412         try {
413             Process JavaDoc p = Runtime.getRuntime().exec(commandLine.getCommandline());
414             StreamPumper errorPumper =
415                     new StreamPumper(p.getErrorStream(), new PrintWriter JavaDoc(System.err, true));
416             new Thread JavaDoc(errorPumper).start();
417
418             InputStreamReader JavaDoc isr = new InputStreamReader JavaDoc(p.getInputStream());
419             BufferedReader JavaDoc br = new BufferedReader JavaDoc(isr);
420             String JavaDoc line;
421
422             while ((line = br.readLine()) != null) {
423                 String JavaDoc[] contribs = splitOnSpace(line);
424                 for (int i = 0; i < contribs.length; i++) {
425                     contribList.add(contribs[i]);
426                 }
427             }
428
429             p.waitFor();
430             p.getInputStream().close();
431             p.getOutputStream().close();
432             p.getErrorStream().close();
433         } catch (IOException JavaDoc e) {
434             LOG.error("IO Error executing ClearCase describe contributors command", e);
435         } catch (InterruptedException JavaDoc e) {
436             LOG.error("Interrupt Error executing ClearCase describe contributors command", e);
437         }
438
439         return contribList;
440     }
441
442     private String JavaDoc[] splitOnSpace(String JavaDoc string) {
443         // replacing line.split(" ") for jdk 1.3
444
ArrayList JavaDoc parts = new ArrayList JavaDoc();
445         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(string, " ");
446         while (tokenizer.hasMoreTokens()) {
447             parts.add(tokenizer.nextToken());
448         }
449         return (String JavaDoc[]) parts.toArray(new String JavaDoc[]{});
450     }
451
452     /*
453       * construct a command to get all the activities on the specified stream
454       */

455     public Commandline buildListContributorsCommand(String JavaDoc activityID) {
456         Commandline commandLine = new Commandline();
457         commandLine.setExecutable("cleartool");
458         commandLine.createArgument().setValue("describe");
459         commandLine.createArgument().setValue("-fmt");
460         commandLine.createArgument().setValue("\"%[contrib_acts]Xp\"");
461         commandLine.createArgument().setValue(activityID);
462         return commandLine;
463     }
464
465     /*
466     * class to hold UCMModifications
467     */

468     private static class UCMModification extends Modification {
469         private static final String JavaDoc TAGNAME_CRMTYPE = "crmtype";
470
471         public String JavaDoc crmtype;
472
473         public int compareTo(Object JavaDoc o) {
474             UCMModification modification = (UCMModification) o;
475             return getActivitityNumber() - modification.getActivitityNumber();
476         }
477
478         public boolean equals(Object JavaDoc o) {
479             if (o == null || !(o instanceof UCMModification)) {
480                 return false;
481             }
482
483             UCMModification modification = (UCMModification) o;
484             return getActivitityNumber() == modification.getActivitityNumber();
485         }
486
487         public int hashCode() {
488             return getActivitityNumber();
489         }
490
491         private int getActivitityNumber() {
492             return Integer.parseInt(revision);
493         }
494
495         UCMModification() {
496             super("ucm");
497         }
498
499         public Element toElement(DateFormat JavaDoc formatter) {
500             Element modificationElement = super.toElement(formatter);
501             Element crmtypeElement = new Element(TAGNAME_CRMTYPE);
502             crmtypeElement.addContent(crmtype);
503             modificationElement.addContent(crmtypeElement);
504             return modificationElement;
505         }
506
507     }
508
509     /**
510      * for testing
511      */

512     public static void main(String JavaDoc[] args) {
513         UCM ucmtest = new UCM();
514         ucmtest.setStream("RatlBankModel_Int");
515         //ucmtest.setViewPath("C:\\Views\\RatlBankModel_int\\RatlBankSources\\model");
516
ucmtest.setViewPath("/view/RatlBankModel_int/vobs/RatlBankSources/model");
517         //ucmtest.setContributors(false);
518
List JavaDoc changes = new ArrayList JavaDoc();
519
520         try {
521             changes = ucmtest.getModifications(new SimpleDateFormat JavaDoc("yyyyMMdd.HHmmss").parse("20050822.095914"),
522                     new Date JavaDoc());
523         } catch (ParseException JavaDoc e) {
524             // TODO Auto-generated catch block
525
e.printStackTrace();
526         }
527
528         System.out.println(changes.toString());
529     }
530
531 }
532
Popular Tags