View Javadoc

1   /*
2    * org.osjava.jardiff.Main
3    *
4    * $Id: IOThread.java 1952 2005-08-28 18:03:41Z cybertiger $
5    * $URL: https://svn.osjava.org/svn/osjava/trunk/osjava-nio/src/java/org/osjava/nio/IOThread.java $
6    * $Rev: 1952 $
7    * $Date: 2005-08-28 18:03:41 +0000 (Sun, 28 Aug 2005) $
8    * $Author: cybertiger $
9    *
10   * Copyright (c) 2005, Antony Riley
11   * All rights reserved.
12   *
13   * Redistribution and use in source and binary forms, with or without
14   * modification, are permitted provided that the following conditions are met:
15   *
16   * + Redistributions of source code must retain the above copyright notice,
17   *   this list of conditions and the following disclaimer.
18   *
19   * + Redistributions in binary form must reproduce the above copyright notice,
20   *   this list of conditions and the following disclaimer in the documentation
21   *   and/or other materials provided with the distribution.
22   *
23   * + Neither the name JarDiff nor the names of its contributors may
24   *   be used to endorse or promote products derived from this software without
25   *   specific prior written permission.
26   *
27   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30   * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37   * POSSIBILITY OF SUCH DAMAGE.
38   */
39  package org.osjava.jardiff;
40  
41  import java.io.File;
42  import java.io.FileOutputStream;
43  import java.io.IOException;
44  import java.io.InputStream;
45  import java.io.OutputStream;
46  import java.net.URL;
47  import java.util.HashSet;
48  import java.util.Set;
49  
50  import javax.xml.transform.ErrorListener;
51  import javax.xml.transform.Transformer;
52  import javax.xml.transform.TransformerException;
53  import javax.xml.transform.TransformerFactory;
54  import javax.xml.transform.sax.SAXTransformerFactory;
55  import javax.xml.transform.sax.TransformerHandler;
56  import javax.xml.transform.stream.StreamResult;
57  import javax.xml.transform.stream.StreamSource;
58  
59  import org.apache.commons.cli.CommandLine;
60  import org.apache.commons.cli.GnuParser;
61  import org.apache.commons.cli.HelpFormatter;
62  import org.apache.commons.cli.Option;
63  import org.apache.commons.cli.Parser;
64  import org.apache.commons.cli.ParseException;
65  import org.apache.commons.cli.Options;
66  
67  /***
68   * A static entry point for use from the command line.
69   */
70  public class Main {
71  
72      /***
73       * Private constructor to prevent this class being instantiated.
74       */
75      private Main() {
76      }
77  
78      /***
79       * Define set of valid formats.
80       * This is here to make maintenance more easy.
81       */
82      private final static Set FORMATS = new HashSet();
83  
84      /***
85       * Can you javadoc static code, I think not, but lets try anyway.
86       */
87      static {
88          FORMATS.add("html");
89          FORMATS.add("xhtml");
90          FORMATS.add("text");
91      }
92  
93      /***
94       * Utility function for showing help using commons-cli.
95       * @param options Command line options.
96       * @param msg Optional message to show.
97       */
98      private static void showHelp(Options options, String msg) {
99          if(msg != null) {
100             System.out.println(msg);
101         }
102         HelpFormatter hf = new HelpFormatter();
103         hf.printHelp("JarDiff -f <from jar> -t <to jar> [-F <from name>] [-T <to name>] [[-o <xml|html|xhtml|text>]|[-x <xsl file>]] [-O <file>] [-s <href>] [-fa <href>] [-ta <href>]", options);
104     }
105 
106     /***
107      * Main method to allow this to be run from the command line.
108      * This needs work, currently only takes two arguments, which are
109      * the old jar file and the new jar file.
110      *
111      * @param args A string array of length two containing the filenames of
112      *             two jar files, the first of which being the older of the
113      *             two.
114      * @throws Exception when there is an underlying exception, e.g.
115      *                   writing to a file caused an IOException
116      */
117     public static void main(String[] args) throws Exception {
118         try {
119             Options options = new Options();
120             Option tmp;
121             tmp = new Option("f","from",true,"from jar file");
122             options.addOption(tmp);
123             tmp = new Option("t","to",true,"to jar file");
124             options.addOption(tmp);
125             tmp = new Option("F","from-name",true,"from name");
126             options.addOption(tmp);
127             tmp = new Option("T","to-name",true,"to name");
128             options.addOption(tmp);
129             //tmp = new Option("d","dep",true,"dependency path");
130             //options.addOption(tmp);
131             tmp = new Option("o","output-format",true,"output format, xml or html");
132             options.addOption(tmp);
133             tmp = new Option("O","out",true,"output file");
134             options.addOption(tmp);
135             tmp = new Option("h","help",false,"print help on command line arguments");
136             options.addOption(tmp);
137             tmp = new Option("x","xsl",true,"custom xsl sheet to format output with");
138             options.addOption(tmp);
139             tmp = new Option("s","stylesheet",true,"stylesheet to link to when generating html");
140             options.addOption(tmp);
141             tmp = new Option("fa","from-api",true,"relative location of from api");
142             options.addOption(tmp);
143             tmp = new Option("ta","to-api",true,"relative location of to api");
144             options.addOption(tmp);
145             Parser parser = new GnuParser();
146             CommandLine cli = null;
147             try {
148                 cli = parser.parse(options, args);
149             } catch (ParseException pe) {
150                 showHelp(options, pe.getMessage());
151                 return;
152             }
153             args = cli.getArgs();
154             if(cli.hasOption('h'))
155             {
156                 showHelp(options, null);
157                 return;
158             }
159             if(args.length > 0) {
160                 showHelp(options, "Additional arguments specified");
161                 return;
162             }
163             if(!cli.hasOption('f')) {
164                 showHelp(options, "Missing required argument: -f");
165                 return;
166             }
167             if(!cli.hasOption('t')) {
168                 showHelp(options, "Missing required argument: -t");
169                 return;
170             }
171 
172             TransformerFactory tf = TransformerFactory.newInstance();
173             tf.setErrorListener(
174                     new ErrorListener() {
175                         public void warning(TransformerException te) {
176                             System.err.println("xslt warning: "+te.getMessageAndLocation());
177                         }
178                         public void error(TransformerException te) {
179                             System.err.println("xslt error: "+te.getMessageAndLocation());
180                         }
181                         public void fatalError(TransformerException te) {
182                             System.err.println("xslt fatal error: "+te.getMessageAndLocation());
183                         }
184                     });
185             Transformer ot;
186             if(cli.hasOption('o')) {
187                 if(cli.hasOption('x')) {
188                     showHelp(options, "Cannot use both -x and -o");
189                     return;
190                 }
191                 String val = cli.getOptionValue('o');
192                 if("xml".equals(val)) {
193                     ot = tf.newTransformer();
194                 } else if(FORMATS.contains(val)) {
195                     URL url = JarDiff.class.getClassLoader()
196                         .getResource("style/jardiff-"+val+".xsl");
197                     ot = tf.newTransformer(
198                             new StreamSource( url.toString() )
199                             );
200                 } else {
201                     showHelp(options, "Invalid output format: "+val);
202                     return;
203                 }
204             } else if(cli.hasOption('x')) {
205                 File xsl = new File(cli.getOptionValue('x'));
206                 ot = tf.newTransformer(new StreamSource(xsl));
207             } else {
208                 ot = tf.newTransformer();
209             }
210             if(cli.hasOption("s")) {
211                 ot.setParameter("stylesheet", cli.getOptionValue("s"));
212             }
213             if(cli.hasOption("fa")) {
214                 ot.setParameter("from-api", cli.getOptionValue("fa"));
215             }
216             if(cli.hasOption("ta")) {
217                 ot.setParameter("to-api", cli.getOptionValue("ta"));
218             }
219             OutputStream out;
220             if(cli.hasOption('O')) {
221                 out = new FileOutputStream(cli.getOptionValue('O'));
222             } else {
223                 out = System.out;
224             }
225             JarDiff jd = new JarDiff();
226             File oldFile = new File(cli.getOptionValue('f'));
227             File newFile = new File(cli.getOptionValue('t'));
228             if(cli.hasOption('F')) {
229                 jd.setOldVersion(cli.getOptionValue('F'));
230             } else {
231                 jd.setOldVersion(oldFile.getName());
232             }
233             if(cli.hasOption('T')) {
234                 jd.setNewVersion(cli.getOptionValue('T'));
235             } else {
236                 jd.setNewVersion(newFile.getName());
237             }
238             jd.loadOldClasses(oldFile);
239             jd.loadNewClasses(newFile);
240             jd.diff(
241                     new DOMDiffHandler(ot, new StreamResult(out)), 
242                     new SimpleDiffCriteria()
243                     );
244             out.close();
245         } catch (Exception e) {
246             e.printStackTrace(System.err);
247         }
248     }
249 }