KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hammurapi > HammurapiArchiver


1 /*
2  * Hammurapi
3  * Automated Java code review system.
4  * Copyright (C) 2004 Hammurapi Group
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * URL: http://www.hammurapi.org
21  * e-Mail: support@hammurapi.biz
22  */

23 package org.hammurapi;
24
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.text.SimpleDateFormat JavaDoc;
30 import java.util.Collection JavaDoc;
31 import java.util.Date JavaDoc;
32 import java.util.HashSet JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.LinkedList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Set JavaDoc;
37 import java.util.zip.ZipEntry JavaDoc;
38 import java.util.zip.ZipOutputStream JavaDoc;
39
40 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
41 import javax.xml.parsers.FactoryConfigurationError JavaDoc;
42 import javax.xml.parsers.ParserConfigurationException JavaDoc;
43 import javax.xml.transform.TransformerException JavaDoc;
44
45 import org.apache.commons.cli.CommandLine;
46 import org.apache.commons.cli.CommandLineParser;
47 import org.apache.commons.cli.HelpFormatter;
48 import org.apache.commons.cli.Option;
49 import org.apache.commons.cli.OptionBuilder;
50 import org.apache.commons.cli.Options;
51 import org.apache.commons.cli.ParseException;
52 import org.apache.commons.cli.PosixParser;
53 import org.apache.tools.ant.BuildException;
54 import org.apache.tools.ant.DirectoryScanner;
55 import org.apache.tools.ant.Project;
56 import org.apache.tools.ant.Task;
57 import org.apache.tools.ant.types.FileSet;
58 import org.apache.tools.ant.types.Path;
59 import org.w3c.dom.Document JavaDoc;
60 import org.w3c.dom.Element JavaDoc;
61
62 import com.pavelvlasov.xml.dom.DOMUtils;
63
64 /**
65  * Packages source files and classpath entries for Hammurapi review.
66  * <section name="Example" suppress-description="yes">
67 If you copy content of Hammurapi lib directory to ant lib directory then you can
68 invoke Hammurapi in the following way:
69  <pre>&lt;taskdef name="har" classname="org.hammurapi.HammurapiArchiver" /&gt;<br/></pre>
70 or, if you didn't copy jar files to Ant lib directory, use this syntax:
71 <pre>&lt;taskdef name="har" classname="org.hammurapi.HammurapiArchiver"&gt;<br/>
72     <tab/>&lt;classpath&gt;<br/>
73         <tab/><tab/>&lt;fileset dir="${hammurapi.home}/lib" includes="*.jar"/&gt;<br/>
74     <tab/>&lt;/classpath&gt;<br/>
75 &lt;/taskdef&gt;<br/></pre>
76 </section>
77  * @ant.element name="har" display-name="Packager for automatic code review task"
78  * @author Pavel Vlasov
79  * @version $Revision: 1.8 $
80  */

81 public class HammurapiArchiver extends Task {
82     static final String JavaDoc DATE_FORMAT="yyyy/MM/dd HH:mm:ss";
83     
84     private Boolean JavaDoc force;
85     
86     /**
87      * Force review even if the file is not changed
88      * @param force
89      * @ant.non-required
90      */

91     public void setForce(boolean force) {
92         this.force=force ? Boolean.TRUE : Boolean.FALSE;
93     }
94     
95     private Boolean JavaDoc forceOnWarnings;
96     
97     /**
98      * Force review of files with warnings, even if the file is not changed.
99      * @ant.non-required
100      */

101     public void setForceOnWarnings(boolean forceOnWarnings) {
102         this.forceOnWarnings=forceOnWarnings ? Boolean.TRUE : Boolean.FALSE;
103     }
104     
105     private String JavaDoc title;
106     
107     /**
108      * Review title
109      * @ant.non-required
110      * @param title
111      */

112     public void setTitle(String JavaDoc title) {
113         this.title=title;
114     }
115     
116     private File JavaDoc output;
117     
118     /**
119      * Output archive
120      * @ant.required
121      * @param output
122      */

123     public void setOutput(File JavaDoc output) {
124         this.output=output;
125     }
126         
127     /**
128      * Classpath for loading classes. Classes and jars from the classpath
129      * are packaged into archive to be used during review.
130      * @ant:non-required
131      */

132     private Path classPath;
133     
134     public void setClassPath(Path classPath) {
135         if (this.classPath == null) {
136             this.classPath = classPath;
137         } else {
138             this.classPath.append(classPath);
139         }
140     }
141
142     private Date JavaDoc baseLine;
143     
144     /**
145      * Date of baseline report
146      * @ant.non-required
147      * @param baseLine
148      */

149     public void setBaseLine(Date JavaDoc baseLine) {
150         this.baseLine=baseLine;
151     }
152
153     private String JavaDoc hostId;
154
155     /**
156      * Host id to differentiate archives created on different machines.
157      * @ant.non-required
158      */

159     public void setHostId(String JavaDoc hostId) {
160         this.hostId=hostId;
161     }
162     
163     //Anu 20050701 start : Added for baselining attribute
164
private String JavaDoc baselining;
165     
166     public void setBaselining(String JavaDoc baselining){
167         this.baselining=baselining;
168     }
169         
170     /**
171      * Maybe creates a nested classpath element.
172      * @ant:non-required
173      */

174     public Path createClasspath() {
175         if (classPath == null) {
176             classPath = new Path(project);
177         }
178         return classPath.createPath();
179     }
180     
181     private String JavaDoc uniquilize(String JavaDoc name, Set JavaDoc names) {
182         int idx=name.lastIndexOf('.');
183         String JavaDoc newName = name;
184         String JavaDoc ext="";
185         if (idx!=-1) {
186             ext=name.substring(idx);
187             name=name.substring(0, idx);
188         }
189                 
190         for (int i=0; names.contains(newName.toLowerCase()); i++) {
191             newName=name+"_"+Integer.toString(i, Character.MAX_RADIX)+ext;
192         }
193         names.add(newName.toLowerCase());
194         return newName;
195     }
196     
197     private int zipFile(File JavaDoc in, ZipOutputStream JavaDoc out, String JavaDoc entryName) throws IOException JavaDoc {
198         if (in.isFile()) {
199             log("Zipping file "+in.getAbsolutePath()+" as "+entryName, Project.MSG_VERBOSE);
200             out.putNextEntry(new ZipEntry JavaDoc(entryName));
201             byte[] buf=new byte[4096];
202             int l;
203             FileInputStream JavaDoc fis=new FileInputStream JavaDoc(in);
204             while ((l=fis.read(buf))!=-1) {
205                 out.write(buf, 0, l);
206             }
207             fis.close();
208             out.closeEntry();
209             return 1;
210         } else if (in.isDirectory()) {
211             int ret=0;
212             File JavaDoc[] entries=in.listFiles();
213             if (entries!=null && entries.length>0) {
214                 log("Zipping directory "+in.getAbsolutePath()+" as "+entryName+"/", Project.MSG_VERBOSE);
215                 out.putNextEntry(new ZipEntry JavaDoc(entryName+"/"));
216                 for (int i=0; i<entries.length; i++) {
217                     ret+=zipFile(entries[i], out, entryName+"/"+entries[i].getName());
218                 }
219                 out.closeEntry();
220             }
221             return ret;
222         }
223         
224         return 0;
225     }
226     
227     public void execute() throws BuildException {
228         try {
229             ZipOutputStream JavaDoc zos=new ZipOutputStream JavaDoc(new FileOutputStream JavaDoc(output));
230             Set JavaDoc entryNames=new HashSet JavaDoc();
231             
232             Document JavaDoc config=DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
233             Element JavaDoc root=config.createElement("hammurapi-archive");
234             config.appendChild(root);
235             
236             if (force!=null) {
237                 root.setAttribute("force", force.booleanValue() ? "yes" : "no");
238             }
239             
240             if (forceOnWarnings!=null) {
241                 root.setAttribute("force-on-warnings", forceOnWarnings.booleanValue() ? "yes" : "no");
242             }
243             
244             if (title!=null) {
245                 root.setAttribute("title", title);
246             }
247             
248             if (reviewDescription!=null) {
249                 root.setAttribute("review-description", reviewDescription);
250             }
251             
252             if (baseLine!=null) {
253                 root.setAttribute("baseline", new SimpleDateFormat JavaDoc(DATE_FORMAT).format(baseLine));
254             }
255             
256             if (hostId!=null) {
257                 root.setAttribute("host-id", hostId);
258             }
259             
260             //Anu 20060701 : Baselining added
261
if (baselining!=null) {
262                 root.setAttribute("baselining", baselining);
263             }
264             
265             Element JavaDoc classPathElement=config.createElement("classpath");
266             root.appendChild(classPathElement);
267             
268             if (classPath!=null) {
269                 String JavaDoc[] path=classPath.list();
270                 for (int i=0; i<path.length; i++) {
271                     File JavaDoc cpEntry=new File JavaDoc(path[i]);
272                     if (cpEntry.exists() && (cpEntry.isFile() || cpEntry.isDirectory())) {
273                         String JavaDoc name=uniquilize("lib/"+cpEntry.getName(), entryNames);
274                         if (zipFile(cpEntry, zos, name)>0) {
275                             Element JavaDoc pathElement=config.createElement("path");
276                             classPathElement.appendChild(pathElement);
277                             pathElement.appendChild(config.createTextNode(name));
278                         }
279                     } else {
280                         log("Classpath entry "+cpEntry.getAbsolutePath()+" does not exist", Project.MSG_VERBOSE);
281                     }
282                 }
283             }
284             
285             Element JavaDoc sourcesElement=config.createElement("sources");
286             root.appendChild(sourcesElement);
287             
288             Iterator JavaDoc it=srcFileSets.iterator();
289             while (it.hasNext()) {
290                 HammurapiFileSet fs=(HammurapiFileSet) it.next();
291                 fs.setDefaultIncludes();
292                 DirectoryScanner scanner=fs.getDirectoryScanner(project);
293                 String JavaDoc name=uniquilize("source/"+scanner.getBasedir().getName(), entryNames);
294                 Element JavaDoc sourceElement=config.createElement("source");
295                 sourcesElement.appendChild(sourceElement);
296                 sourceElement.appendChild(config.createTextNode(name));
297                 String JavaDoc[] files=scanner.getIncludedFiles();
298                 for (int i=0; i<files.length; i++) {
299                     zipFile(new File JavaDoc(scanner.getBasedir(), files[i]), zos, name+"/"+files[i].replace(File.separatorChar, '/'));
300                 }
301             }
302             
303             /**
304              * For command-line interface
305              */

306             it=srcFiles.iterator();
307             while (it.hasNext()) {
308                 String JavaDoc name=uniquilize("source/source", entryNames);
309                 File JavaDoc file = (File JavaDoc) it.next();
310                 String JavaDoc entryName = name+"/"+file.getName();
311                 Element JavaDoc sourceElement=config.createElement("source");
312                 sourcesElement.appendChild(sourceElement);
313                 sourceElement.appendChild(config.createTextNode(entryName));
314                 zipFile(file, zos, entryName);
315             }
316             
317             ZipEntry JavaDoc configEntry=new ZipEntry JavaDoc("config.xml");
318             zos.putNextEntry(configEntry);
319             DOMUtils.serialize(config, zos);
320             zos.closeEntry();
321             
322             zos.close();
323         } catch (IOException JavaDoc e) {
324             throw new BuildException(e.getMessage(), e);
325         } catch (ParserConfigurationException JavaDoc e) {
326             throw new BuildException(e.getMessage(), e);
327         } catch (FactoryConfigurationError JavaDoc e) {
328             throw new BuildException(e.getMessage(), e);
329         } catch (TransformerException JavaDoc e) {
330             throw new BuildException(e.getMessage(), e);
331         }
332     }
333         
334     /**
335      * Source files fileset.
336      * @ant.non-required
337      */

338     public FileSet createSrc() {
339         FileSet ret=new HammurapiFileSet("**/*.java");
340         srcFileSets.add(ret);
341         return ret;
342     }
343
344     private List JavaDoc srcFileSets = new LinkedList JavaDoc();
345         
346     private Collection JavaDoc srcFiles=new LinkedList JavaDoc();
347     
348     private static void printHelpAndExit(Options options) {
349         HelpFormatter formatter=new HelpFormatter();
350         formatter.printHelp("Usage: har [options] <output file> <source files/dirs>", options, false);
351         System.exit(1);
352     }
353     
354     /**
355      * Use it for inspector debugging
356      * @param args
357      */

358     public static void main(String JavaDoc[] args) {
359         System.out.println("Hammurapi 3 Copyright (C) 2004 Hammurapi Group");
360         
361         Options options=new Options();
362                 
363         Option classPathOption=OptionBuilder
364         .withArgName("classpath")
365         .hasArg()
366         .withDescription("ClassPath")
367         .isRequired(false)
368         .create("c");
369         
370         options.addOption(classPathOption);
371                 
372         Option hostIdOption=OptionBuilder
373         .withArgName("hostId")
374         .hasArg()
375         .withDescription("Host id")
376         .isRequired(false)
377         .create("H");
378         
379         options.addOption(hostIdOption);
380         
381         Option titleOption=OptionBuilder
382         .withArgName("title")
383         .hasArg()
384         .withDescription("Report title")
385         .isRequired(false)
386         .create("T");
387         
388         options.addOption(titleOption);
389         
390         Option baseLineOption=OptionBuilder
391         .withDescription("Baseline date")
392         .withArgName("date")
393         .hasArg()
394         .isRequired(false)
395         .create("n");
396         
397         options.addOption(baseLineOption);
398         
399         Option forceOption=OptionBuilder
400         .withDescription("Force reviews on unchanged files")
401         .isRequired(false)
402         .create("f");
403         
404         options.addOption(forceOption);
405         
406         Option forceOnWarningsOption=OptionBuilder
407         .withDescription("Do not force reviews of files with warnings")
408         .isRequired(false)
409         .create("k");
410         
411         options.addOption(forceOnWarningsOption);
412         
413         Option descriptionOption=OptionBuilder
414         .withDescription("Review description")
415         .withArgName("description")
416         .hasArg()
417         .isRequired(false)
418         .create("y");
419         options.addOption(descriptionOption);
420         
421         //Anu :20050701 Added baselining parameter
422
Option baseliningOption=OptionBuilder
423         .withArgName("off|on|set")
424         .hasArg()
425         .withDescription("Baselining mode")
426         .isRequired(false)
427         .create("B");
428         
429         options.addOption(descriptionOption);
430         
431         Option helpOption=OptionBuilder.withDescription("Print this message").isRequired(false).create("h");
432         options.addOption(helpOption);
433         
434         CommandLineParser parser=new PosixParser();
435         CommandLine line=null;
436         try {
437             line=parser.parse(options, args);
438         } catch (ParseException e) {
439             System.err.println(e.getMessage());
440             System.err.flush();
441             printHelpAndExit(options);
442         }
443                 
444         if (line.hasOption("h")) {
445             printHelpAndExit(options);
446         }
447
448         HammurapiArchiver task=new HammurapiArchiver();
449         Project project = new Project();
450         task.setProject(project);
451         project.setCoreLoader(task.getClass().getClassLoader());
452         
453         String JavaDoc[] values=line.getOptionValues('c');
454         for (int i=0; values!=null && i<values.length; i++) {
455             task.createClasspath().append(new Path(project, values[i]));
456         }
457         
458         String JavaDoc[] largs=line.getArgs();
459         if (largs.length==0) {
460             System.out.println("Output file has to be provided");
461             printHelpAndExit(options);
462         }
463         
464         if (line.hasOption('f')) {
465             task.setForce(true);
466         }
467         
468         if (line.hasOption('k')) {
469             task.setForceOnWarnings(false);
470         }
471         
472         if (line.hasOption('n')) {
473             task.setBaseLine(new Date JavaDoc(line.getOptionValue('n')));
474         }
475         
476         if (line.hasOption('H')) {
477             task.setHostId(line.getOptionValue('H'));
478         }
479                 
480         if (line.hasOption('y')) {
481             task.setReviewDescription(line.getOptionValue('y'));
482         }
483          
484         if (line.hasOption('T')) {
485             task.setTitle(line.getOptionValue('T'));
486         }
487         
488         //Anu :20050701 Added for Baselining attribute
489
if (line.hasOption('B')) {
490             task.setBaselining(line.getOptionValue('B'));
491         }
492
493         task.setOutput(new File JavaDoc(largs[0]));
494         
495         for (int i=1; i<largs.length; i++) {
496             File JavaDoc file = new File JavaDoc(largs[i]);
497             if (file.isFile()) {
498                 task.srcFiles.add(file);
499             } else if (file.isDirectory()) {
500                 task.createSrc().setDir(file);
501             }
502         }
503         
504         task.setTaskName("har");
505         
506         try {
507             task.execute();
508             System.exit(0);
509         } catch (Exception JavaDoc e) {
510             e.printStackTrace();
511             System.exit(2);
512         }
513     }
514     
515     private String JavaDoc reviewDescription;
516
517     /**
518      * Description of review, e.g. release number. Appears in history annotation.
519      * @ant.non-required
520      */

521     public void setReviewDescription(String JavaDoc reviewDescription) {
522         this.reviewDescription=reviewDescription;
523     }
524     
525 }
526
Popular Tags