KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > cvslib > CvsTagDiff


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.taskdefs.cvslib;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.FileOutputStream JavaDoc;
23 import java.io.FileReader JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.OutputStreamWriter JavaDoc;
26 import java.io.PrintWriter JavaDoc;
27 import java.io.UnsupportedEncodingException JavaDoc;
28 import java.util.Vector JavaDoc;
29 import java.util.StringTokenizer JavaDoc;
30
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.Project;
33 import org.apache.tools.ant.taskdefs.AbstractCvsTask;
34 import org.apache.tools.ant.util.DOMElementWriter;
35 import org.apache.tools.ant.util.DOMUtils;
36 import org.apache.tools.ant.util.FileUtils;
37
38 import org.w3c.dom.Document JavaDoc;
39 import org.w3c.dom.Element JavaDoc;
40
41 /**
42  * Examines the output of cvs rdiff between two tags.
43  *
44  * It produces an XML output representing the list of changes.
45  * <PRE>
46  * &lt;!-- Root element --&gt;
47  * &lt;!ELEMENT tagdiff ( entry+ ) &gt;
48  * &lt;!-- Start tag of the report --&gt;
49  * &lt;!ATTLIST tagdiff startTag NMTOKEN #IMPLIED &gt;
50  * &lt;!-- End tag of the report --&gt;
51  * &lt;!ATTLIST tagdiff endTag NMTOKEN #IMPLIED &gt;
52  * &lt;!-- Start date of the report --&gt;
53  * &lt;!ATTLIST tagdiff startDate NMTOKEN #IMPLIED &gt;
54  * &lt;!-- End date of the report --&gt;
55  * &lt;!ATTLIST tagdiff endDate NMTOKEN #IMPLIED &gt;
56  *
57  * &lt;!-- CVS tag entry --&gt;
58  * &lt;!ELEMENT entry ( file ) &gt;
59  * &lt;!-- File added, changed or removed --&gt;
60  * &lt;!ELEMENT file ( name, revision?, prevrevision? ) &gt;
61  * &lt;!-- Name of the file --&gt;
62  * &lt;!ELEMENT name ( #PCDATA ) &gt;
63  * &lt;!-- Revision number --&gt;
64  * &lt;!ELEMENT revision ( #PCDATA ) &gt;
65  * &lt;!-- Previous revision number --&gt;
66  * &lt;!ELEMENT prevrevision ( #PCDATA ) &gt;
67  * </PRE>
68  *
69  * @since Ant 1.5
70  * @ant.task name="cvstagdiff"
71  */

72 public class CvsTagDiff extends AbstractCvsTask {
73
74     /**
75      * Used to create the temp file for cvs log
76      */

77     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
78
79     /** stateless helper for writing the XML document */
80     private static final DOMElementWriter DOM_WRITER = new DOMElementWriter();
81
82     /**
83      * Token to identify the word file in the rdiff log
84      */

85     static final String JavaDoc FILE_STRING = "File ";
86     /**
87      * Token to identify the word file in the rdiff log
88      */

89     static final String JavaDoc TO_STRING = " to ";
90     /**
91      * Token to identify a new file in the rdiff log
92      */

93     static final String JavaDoc FILE_IS_NEW = " is new;";
94     /**
95      * Token to identify the revision
96      */

97     static final String JavaDoc REVISION = "revision ";
98
99     /**
100      * Token to identify a modified file in the rdiff log
101      */

102     static final String JavaDoc FILE_HAS_CHANGED = " changed from revision ";
103
104     /**
105      * Token to identify a removed file in the rdiff log
106      */

107     static final String JavaDoc FILE_WAS_REMOVED = " is removed";
108
109     /**
110      * The cvs package/module to analyse
111      */

112     private String JavaDoc mypackage;
113
114     /**
115      * The earliest tag from which diffs are to be included in the report.
116      */

117     private String JavaDoc mystartTag;
118
119     /**
120      * The latest tag from which diffs are to be included in the report.
121      */

122     private String JavaDoc myendTag;
123
124     /**
125      * The earliest date from which diffs are to be included in the report.
126      */

127     private String JavaDoc mystartDate;
128
129     /**
130      * The latest date from which diffs are to be included in the report.
131      */

132     private String JavaDoc myendDate;
133
134     /**
135      * The file in which to write the diff report.
136      */

137     private File JavaDoc mydestfile;
138
139     /**
140      * The package/module to analyze.
141      * @param p the name of the package to analyse
142      */

143     public void setPackage(String JavaDoc p) {
144         mypackage = p;
145     }
146
147     /**
148      * Set the start tag.
149      *
150      * @param s the start tag.
151      */

152     public void setStartTag(String JavaDoc s) {
153         mystartTag = s;
154     }
155
156     /**
157      * Set the start date.
158      *
159      * @param s the start date.
160      */

161     public void setStartDate(String JavaDoc s) {
162         mystartDate = s;
163     }
164
165     /**
166      * Set the end tag.
167      *
168      * @param s the end tag.
169      */

170     public void setEndTag(String JavaDoc s) {
171         myendTag = s;
172     }
173
174     /**
175      * Set the end date.
176      *
177      * @param s the end date.
178      */

179     public void setEndDate(String JavaDoc s) {
180         myendDate = s;
181     }
182
183     /**
184      * Set the output file for the diff.
185      *
186      * @param f the output file for the diff.
187      */

188     public void setDestFile(File JavaDoc f) {
189         mydestfile = f;
190     }
191
192     /**
193      * Execute task.
194      *
195      * @exception BuildException if an error occurs
196      */

197     public void execute() throws BuildException {
198         // validate the input parameters
199
validate();
200
201         // build the rdiff command
202
addCommandArgument("rdiff");
203         addCommandArgument("-s");
204         if (mystartTag != null) {
205             addCommandArgument("-r");
206             addCommandArgument(mystartTag);
207         } else {
208             addCommandArgument("-D");
209             addCommandArgument(mystartDate);
210         }
211         if (myendTag != null) {
212             addCommandArgument("-r");
213             addCommandArgument(myendTag);
214         } else {
215             addCommandArgument("-D");
216             addCommandArgument(myendDate);
217         }
218         // support multiple packages
219
StringTokenizer JavaDoc myTokenizer = new StringTokenizer JavaDoc(mypackage);
220         while (myTokenizer.hasMoreTokens()) {
221             addCommandArgument(myTokenizer.nextToken());
222         }
223         // force command not to be null
224
setCommand("");
225         File JavaDoc tmpFile = null;
226         try {
227             tmpFile = FILE_UTILS.createTempFile("cvstagdiff", ".log", null);
228             tmpFile.deleteOnExit();
229             setOutput(tmpFile);
230
231             // run the cvs command
232
super.execute();
233
234             // parse the rdiff
235
CvsTagEntry[] entries = parseRDiff(tmpFile);
236
237             // write the tag diff
238
writeTagDiff(entries);
239
240         } finally {
241             if (tmpFile != null) {
242                 tmpFile.delete();
243             }
244         }
245     }
246
247     /**
248      * Parse the tmpFile and return and array of CvsTagEntry to be
249      * written in the output.
250      *
251      * @param tmpFile the File containing the output of the cvs rdiff command
252      * @return the entries in the output
253      * @exception BuildException if an error occurs
254      */

255     private CvsTagEntry[] parseRDiff(File JavaDoc tmpFile) throws BuildException {
256         // parse the output of the command
257
BufferedReader JavaDoc reader = null;
258
259         try {
260             reader = new BufferedReader JavaDoc(new FileReader JavaDoc(tmpFile));
261
262             // entries are of the form:
263
//CVS 1.11
264
// File module/filename is new; current revision 1.1
265
//CVS 1.11.9
266
// File module/filename is new; cvstag_2003_11_03_2 revision 1.1
267
// or
268
// File module/filename changed from revision 1.4 to 1.6
269
// or
270
// File module/filename is removed; not included in
271
// release tag SKINLF_12
272
//CVS 1.11.9
273
// File testantoine/antoine.bat is removed; TESTANTOINE_1 revision 1.1.1.1
274
//
275
// get rid of 'File module/"
276
String JavaDoc toBeRemoved = FILE_STRING + mypackage + "/";
277             int headerLength = toBeRemoved.length();
278             Vector JavaDoc entries = new Vector JavaDoc();
279
280             String JavaDoc line = reader.readLine();
281             int index;
282             CvsTagEntry entry = null;
283
284             while (null != line) {
285                 if (line.length() > headerLength) {
286                     if (line.startsWith(toBeRemoved)) {
287                         line = line.substring(headerLength);
288                     } else {
289                         line = line.substring(FILE_STRING.length());
290                     }
291
292                     if ((index = line.indexOf(FILE_IS_NEW)) != -1) {
293                         // it is a new file
294
// set the revision but not the prevrevision
295
String JavaDoc filename = line.substring(0, index);
296                         String JavaDoc rev = null;
297                         int indexrev = -1;
298                         if ((indexrev = line.indexOf(REVISION, index)) != -1) {
299                             rev = line.substring(indexrev + REVISION.length());
300                         }
301                         entry = new CvsTagEntry(filename, rev);
302                         entries.addElement(entry);
303                         log(entry.toString(), Project.MSG_VERBOSE);
304                     } else if ((index = line.indexOf(FILE_HAS_CHANGED)) != -1) {
305                         // it is a modified file
306
// set the revision and the prevrevision
307
String JavaDoc filename = line.substring(0, index);
308                         int revSeparator = line.indexOf(" to ", index);
309                         String JavaDoc prevRevision =
310                             line.substring(index + FILE_HAS_CHANGED.length(),
311                                 revSeparator);
312                         String JavaDoc revision = line.substring(revSeparator + TO_STRING.length());
313                         entry = new CvsTagEntry(filename,
314                             revision,
315                             prevRevision);
316                         entries.addElement(entry);
317                         log(entry.toString(), Project.MSG_VERBOSE);
318                     } else if ((index = line.indexOf(FILE_WAS_REMOVED)) != -1) {
319                         // it is a removed file
320
String JavaDoc filename = line.substring(0, index);
321                         String JavaDoc rev = null;
322                         int indexrev = -1;
323                         if ((indexrev = line.indexOf(REVISION, index)) != -1) {
324                             rev = line.substring(indexrev + REVISION.length());
325                         }
326                         entry = new CvsTagEntry(filename, null, rev);
327                         entries.addElement(entry);
328                         log(entry.toString(), Project.MSG_VERBOSE);
329                     }
330                 }
331                 line = reader.readLine();
332             }
333
334             CvsTagEntry[] array = new CvsTagEntry[entries.size()];
335             entries.copyInto(array);
336
337             return array;
338         } catch (IOException JavaDoc e) {
339             throw new BuildException("Error in parsing", e);
340         } finally {
341             if (reader != null) {
342                 try {
343                     reader.close();
344                 } catch (IOException JavaDoc e) {
345                     log(e.toString(), Project.MSG_ERR);
346                 }
347             }
348         }
349     }
350
351     /**
352      * Write the rdiff log.
353      *
354      * @param entries a <code>CvsTagEntry[]</code> value
355      * @exception BuildException if an error occurs
356      */

357     private void writeTagDiff(CvsTagEntry[] entries) throws BuildException {
358         FileOutputStream JavaDoc output = null;
359         try {
360             output = new FileOutputStream JavaDoc(mydestfile);
361             PrintWriter JavaDoc writer = new PrintWriter JavaDoc(
362                                      new OutputStreamWriter JavaDoc(output, "UTF-8"));
363             writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
364             Document JavaDoc doc = DOMUtils.newDocument();
365             Element JavaDoc root = doc.createElement("tagdiff");
366             if (mystartTag != null) {
367                 root.setAttribute("startTag", mystartTag);
368             } else {
369                 root.setAttribute("startDate", mystartDate);
370             }
371             if (myendTag != null) {
372                 root.setAttribute("endTag", myendTag);
373             } else {
374                 root.setAttribute("endDate", myendDate);
375             }
376
377             root.setAttribute("cvsroot", getCvsRoot());
378             root.setAttribute("package", mypackage);
379             DOM_WRITER.openElement(root, writer, 0, "\t");
380             writer.println();
381             for (int i = 0, c = entries.length; i < c; i++) {
382                 writeTagEntry(doc, writer, entries[i]);
383             }
384             DOM_WRITER.closeElement(root, writer, 0, "\t", true);
385             writer.flush();
386             writer.close();
387         } catch (UnsupportedEncodingException JavaDoc uee) {
388             log(uee.toString(), Project.MSG_ERR);
389         } catch (IOException JavaDoc ioe) {
390             throw new BuildException(ioe.toString(), ioe);
391         } finally {
392             if (null != output) {
393                 try {
394                     output.close();
395                 } catch (IOException JavaDoc ioe) {
396                     log(ioe.toString(), Project.MSG_ERR);
397                 }
398             }
399         }
400     }
401
402     /**
403      * Write a single entry to the given writer.
404      *
405      * @param doc Document used to create elements.
406      * @param writer a <code>PrintWriter</code> value
407      * @param entry a <code>CvsTagEntry</code> value
408      */

409     private void writeTagEntry(Document JavaDoc doc, PrintWriter JavaDoc writer,
410                                CvsTagEntry entry)
411         throws IOException JavaDoc {
412         Element JavaDoc ent = doc.createElement("entry");
413         Element JavaDoc f = DOMUtils.createChildElement(ent, "file");
414         DOMUtils.appendCDATAElement(f, "name", entry.getFile());
415         if (entry.getRevision() != null) {
416             DOMUtils.appendTextElement(f, "revision", entry.getRevision());
417         }
418         if (entry.getPreviousRevision() != null) {
419             DOMUtils.appendTextElement(f, "prevrevision",
420                                        entry.getPreviousRevision());
421         }
422         DOM_WRITER.write(ent, writer, 1, "\t");
423     }
424
425     /**
426      * Validate the parameters specified for task.
427      *
428      * @exception BuildException if a parameter is not correctly set
429      */

430     private void validate() throws BuildException {
431         if (null == mypackage) {
432             throw new BuildException("Package/module must be set.");
433         }
434
435         if (null == mydestfile) {
436             throw new BuildException("Destfile must be set.");
437         }
438
439         if (null == mystartTag && null == mystartDate) {
440             throw new BuildException("Start tag or start date must be set.");
441         }
442
443         if (null != mystartTag && null != mystartDate) {
444             throw new BuildException("Only one of start tag and start date "
445                                      + "must be set.");
446         }
447
448         if (null == myendTag && null == myendDate) {
449             throw new BuildException("End tag or end date must be set.");
450         }
451
452         if (null != myendTag && null != myendDate) {
453             throw new BuildException("Only one of end tag and end date must "
454                                      + "be set.");
455         }
456     }
457 }
458
Popular Tags