KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.BufferedReader JavaDoc;
40 import java.io.File JavaDoc;
41 import java.io.FileReader JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.text.ParseException JavaDoc;
44 import java.text.SimpleDateFormat JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Date JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.List JavaDoc;
49 import java.util.Map JavaDoc;
50 import java.util.StringTokenizer JavaDoc;
51
52 import net.sourceforge.cruisecontrol.CruiseControlException;
53 import net.sourceforge.cruisecontrol.Modification;
54 import net.sourceforge.cruisecontrol.SourceControl;
55 import net.sourceforge.cruisecontrol.util.StreamPumper;
56 import net.sourceforge.cruisecontrol.util.ValidationHelper;
57
58 import org.apache.log4j.Logger;
59
60 /**
61  * This class implements the SourceControlElement methods for a PVCS repository.
62  *
63  * @author <a HREF="mailto:Richard.Wagner@alltel.com">Richard Wagner</a>
64  * @version $Id: PVCS.java,v 1.32 2006/04/24 01:34:50 jfredrick Exp $
65  */

66 public class PVCS implements SourceControl {
67
68     private static final Logger LOG = Logger.getLogger(PVCS.class);
69     private static final String JavaDoc DOUBLE_QUOTE = "\"";
70
71     private Map JavaDoc properties = new HashMap JavaDoc();
72     private Date JavaDoc lastBuild;
73
74     private String JavaDoc archiveFileSuffix = "-arc";
75     private String JavaDoc pvcsbin;
76     private String JavaDoc pvcsExecCommand;
77     private String JavaDoc pvcsProject;
78     // i.e. "esa";
79
// i.e. "esa/uihub2";
80
private String JavaDoc pvcsSubProject;
81     private String JavaDoc pvcsVersionLabel;
82     private String JavaDoc loginId;
83
84     /**
85      * Date format required by commands passed to PVCS
86      */

87     private SimpleDateFormat JavaDoc inDateFormat = new SimpleDateFormat JavaDoc("MM/dd/yyyy h:mma");
88     private SimpleDateFormat JavaDoc outDateFormatSub = new SimpleDateFormat JavaDoc("dd MMM yyyy HH:mm:ss");
89
90     /**
91      * Date format returned in the output of PVCS commands.
92      */

93     private SimpleDateFormat JavaDoc outDateFormat = new SimpleDateFormat JavaDoc("MMM dd yyyy HH:mm:ss");
94
95     private static final String JavaDoc PVCS_RESULTS_FILE = "vlog.txt";
96
97     /**
98      * Get name of the PVCS bin directory
99      * @return String
100      */

101     public String JavaDoc getPvcsbin() {
102         return pvcsbin;
103     }
104
105     public void setPvcsExecCommand(String JavaDoc command) {
106         pvcsExecCommand = command;
107     }
108
109     public String JavaDoc getPvcsExecCommand() {
110         return pvcsExecCommand;
111     }
112
113     /**
114      * Specifies the location of the PVCS bin directory
115      * @param bin Specifies the location of the PVCS bin directory
116      */

117     public void setPvcsbin(String JavaDoc bin) {
118         this.pvcsbin = bin;
119     }
120
121     public void setPvcsproject(String JavaDoc project) {
122         pvcsProject = project;
123     }
124
125     public void setPvcssubproject(String JavaDoc subproject) {
126         pvcsSubProject = subproject;
127     }
128
129     public void setPvcsversionlabel(String JavaDoc versionlabel) {
130         pvcsVersionLabel = versionlabel;
131     }
132
133     public void setInDateFormat(String JavaDoc inDateFormat) {
134         this.inDateFormat = new SimpleDateFormat JavaDoc(inDateFormat);
135     }
136
137     public void setOutDateFormat(String JavaDoc outDateFormat) {
138         this.outDateFormat = new SimpleDateFormat JavaDoc(outDateFormat);
139     }
140
141     public Map JavaDoc getProperties() {
142         return properties;
143     }
144
145     public void validate() throws CruiseControlException {
146         ValidationHelper.assertIsSet(pvcsProject, "pvcsproject", this.getClass());
147         ValidationHelper.assertIsSet(pvcsSubProject, "pvcssubproject", this.getClass());
148     }
149
150     /**
151      * Returns an {@link java.util.List List} of {@link Modification}s detailing all the changes between now
152      * and the last build.
153      *
154      *@param lastBuild the last build time
155      *@param now time now, or time to check
156      *@return the list of modifications, an empty (not null) list if no
157      * modifications or if developer had checked in files since quietPeriod seconds ago.
158      *
159      * Note: Internally uses external filesystem for files CruiseControlPVCS.pcli, files.tmp, vlog.txt
160      */

161     public List JavaDoc getModifications(Date JavaDoc lastBuild, Date JavaDoc now) {
162         this.lastBuild = lastBuild;
163         // build file of PVCS command line instructions
164
String JavaDoc lastBuildDate = inDateFormat.format(lastBuild);
165         String JavaDoc nowDate = inDateFormat.format(now);
166
167         try {
168             setPvcsExecCommand(getExecutable("pcli") + " " + buildExecCommand(lastBuildDate, nowDate));
169             exec(pvcsExecCommand);
170         } catch (Exception JavaDoc e) {
171             LOG.error("Error in executing the PVCS command : ", e);
172             return new ArrayList JavaDoc();
173         }
174
175         return makeModificationsList(new File JavaDoc(PVCS_RESULTS_FILE));
176     }
177
178     String JavaDoc getExecutable(String JavaDoc exe) {
179         StringBuffer JavaDoc correctedExe = new StringBuffer JavaDoc();
180         if (getPvcsbin() != null) {
181             if (getPvcsbin().endsWith(File.separator)) {
182                 correctedExe.append(getPvcsbin());
183             } else {
184                 correctedExe.append(getPvcsbin()).append(File.separator);
185             }
186         }
187         return correctedExe.append(exe).toString();
188     }
189
190     protected void exec(String JavaDoc command) throws IOException JavaDoc, InterruptedException JavaDoc {
191         LOG.debug("Command to execute: " + command);
192         Process JavaDoc p = Runtime.getRuntime().exec(command);
193         StreamPumper errorPumper = new StreamPumper(p.getErrorStream());
194         new Thread JavaDoc(errorPumper).start();
195         p.getInputStream();
196         p.waitFor();
197         p.getOutputStream();
198         p.getInputStream();
199         p.getErrorStream();
200     }
201
202     /**
203      * Read the file produced by PCLI listing all changes to the source repository
204      * Once we've read the file, produce a list of changes.
205      * @param inputFile TODO
206      */

207     List JavaDoc makeModificationsList(File JavaDoc inputFile) {
208         List JavaDoc theList;
209         BufferedReader JavaDoc brIn;
210         ModificationBuilder modificationBuilder = new ModificationBuilder(pvcsProject);
211         try {
212             brIn = new BufferedReader JavaDoc(new FileReader JavaDoc(inputFile));
213             String JavaDoc line;
214             while ((line = brIn.readLine()) != null) {
215                 modificationBuilder.addLine(line);
216             }
217             brIn.close();
218         } catch (IOException JavaDoc e) {
219             LOG.error("Error in reading vlog file of PVCS modifications : ", e);
220         }
221         theList = modificationBuilder.getList();
222
223         if (theList == null) {
224             theList = new ArrayList JavaDoc();
225         }
226
227         return theList;
228     }
229
230     /**
231      * Returns the command to be ran to check for repository changes
232      * run -ns -q -xo"vlog.txt" -xe"vlog.txt" vlog -id"SomeUser"
233      * -ds"11/23/2004 8:00AM"-de"11/23/2004 1:00PM" -pr"C:/PVCS-Repos/TestProject"
234      * -v"Test Version Label" -z /TestProject
235      *
236      * @return the command to be executed to check for repository changes
237      */

238     String JavaDoc buildExecCommand(String JavaDoc lastBuild, String JavaDoc now) {
239         String JavaDoc command =
240             "run -ns -q -xo" + DOUBLE_QUOTE + PVCS_RESULTS_FILE + DOUBLE_QUOTE
241             + " -xe" + DOUBLE_QUOTE + PVCS_RESULTS_FILE + DOUBLE_QUOTE
242             + " vlog ";
243         
244         if (loginId != null && !loginId.trim().equals("")) {
245             command += "-id" + DOUBLE_QUOTE + loginId + DOUBLE_QUOTE + " ";
246         }
247         
248         command += "-ds" + DOUBLE_QUOTE + lastBuild + DOUBLE_QUOTE
249             + " -de" + DOUBLE_QUOTE + now + DOUBLE_QUOTE
250             + " -pr" + DOUBLE_QUOTE + pvcsProject + DOUBLE_QUOTE;
251
252         if (pvcsVersionLabel != null && !pvcsVersionLabel.equals("")) {
253             command += " -v" + DOUBLE_QUOTE + pvcsVersionLabel + DOUBLE_QUOTE;
254          }
255
256         command += " -z " + pvcsSubProject;
257         return command;
258     }
259
260     /**
261      * Inner class to build Modifications and verify the order of the lines
262      * used to build them.
263      */

264     class ModificationBuilder {
265         private String JavaDoc proj;
266         private Modification modification;
267         private ArrayList JavaDoc modificationList;
268         private boolean firstModifiedTime = true;
269         private boolean firstUserName = true;
270         private boolean nextLineIsComment = false;
271         private boolean waitingForNextValidStart = false;
272
273         public ModificationBuilder(String JavaDoc proj) {
274             this.proj = proj;
275         }
276
277         public ArrayList JavaDoc getList() {
278             return modificationList;
279         }
280
281         private void initializeModification() {
282             if (modificationList == null) {
283                 modificationList = new ArrayList JavaDoc();
284             }
285             modification = new Modification("pvcs");
286             firstModifiedTime = true;
287             firstUserName = true;
288             nextLineIsComment = false;
289             waitingForNextValidStart = false;
290         }
291
292         public void addLine(String JavaDoc line) {
293             if (line.startsWith("Archive:")) {
294                 initializeModification();
295                 String JavaDoc fileName;
296
297                 int startIndex = (line.indexOf(proj) + proj.length());
298                 int endIndex = line.indexOf(archiveFileSuffix);
299                 if (endIndex == -1) {
300                     endIndex = line.length();
301                 }
302                 fileName = line.substring(startIndex, endIndex);
303                 if (fileName.startsWith("/") || fileName.startsWith("\\")) {
304                      fileName = fileName.substring(1);
305                 }
306                 if (fileName.startsWith("archives")) {
307                      fileName = fileName.substring("archives".length());
308                 }
309
310
311                 modification.createModifiedFile(fileName, null);
312
313             } else if (waitingForNextValidStart) {
314                 // we're in this state after we've got the last useful line
315
// from the previous item, but haven't yet started a new one
316
// -- we should just skip these lines till we start a new one
317
//return
318
} else if (line.startsWith("Workfile:")) {
319                 modification.createModifiedFile(line.substring(18), null);
320             } else if (line.startsWith("Archive created:")) {
321                 try {
322                     String JavaDoc createdDate = line.substring(18);
323                     Date JavaDoc createTime;
324                     try {
325                         createTime = outDateFormat.parse(createdDate);
326                     } catch (ParseException JavaDoc e) {
327                         createTime = outDateFormatSub.parse(createdDate);
328                     }
329                     if (createTime.after(lastBuild)) {
330                         modification.type = "added";
331                     } else {
332                         modification.type = "modified";
333                     }
334                 } catch (ParseException JavaDoc e) {
335                     LOG.error("Error parsing create date: " + e.getMessage(), e);
336                 }
337             } else if (line.startsWith("Last modified:")) {
338                 // if this is the newest revision...
339
if (firstModifiedTime) {
340                     firstModifiedTime = false;
341                     String JavaDoc lastMod = null;
342                     try {
343                         lastMod = line.substring(16);
344                         modification.modifiedTime = outDateFormat.parse(lastMod);
345                     } catch (ParseException JavaDoc e) {
346                         try {
347                             modification.modifiedTime = outDateFormatSub.parse(lastMod);
348                         } catch (ParseException JavaDoc pe) {
349                             modification.modifiedTime = null;
350                             LOG.error("Error parsing modification time : ", e);
351                           }
352                     }
353                 }
354             } else if (nextLineIsComment) {
355                 // used boolean because don't know what comment will startWith....
356
modification.comment = line;
357                 // comment is last line we need, so add this mod to list,
358
// then set indicator to ignore future lines till next new item
359
modificationList.add(modification);
360                 waitingForNextValidStart = true;
361             } else if (line.startsWith("Author id:")) {
362                 // if this is the newest revision...
363
if (firstUserName) {
364                     String JavaDoc sub = line.substring(11);
365                     StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(sub, " ");
366                     modification.userName = st.nextToken().trim();
367                     firstUserName = false;
368                     nextLineIsComment = true;
369                 }
370             } // end of Author id
371

372         } // end of addLine
373

374     } // end of class ModificationBuilder
375

376    /**
377     * @return loginId
378     */

379    public String JavaDoc getLoginid() {
380       return loginId;
381    }
382
383    /**
384     * @param loginId
385     */

386    public void setLoginid(String JavaDoc loginId) {
387       this.loginId = loginId;
388    }
389
390     void setLastBuild(Date JavaDoc date) {
391         this.lastBuild = date;
392     }
393
394     public void setArchiveFileSuffix(String JavaDoc archiveSuffix) {
395         this.archiveFileSuffix = archiveSuffix;
396     }
397
398 } // end class PVCSElement
399
Popular Tags