View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at 
7    * 
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software 
11   * distributed under the License is distributed on an "AS IS" BASIS, 
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License.
15   */
16  
17  package org.apache.jdo.impl.enhancer.util;
18  
19  import java.util.Iterator;
20  import java.util.Enumeration;
21  import java.util.List;
22  import java.util.ArrayList;
23  import java.util.Map;
24  import java.util.HashMap;
25  import java.util.Set;
26  import java.util.HashSet;
27  import java.util.Stack;
28  
29  import java.io.PrintWriter;
30  import java.io.StringWriter;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.FileInputStream;
34  import java.io.BufferedInputStream;
35  import java.io.DataInputStream;
36  import java.io.FileNotFoundException;
37  import java.io.ByteArrayOutputStream;
38  import java.io.PrintStream;
39  
40  import org.apache.jdo.impl.enhancer.ClassArgMain;
41  import org.apache.jdo.impl.enhancer.EnhancerFatalError;
42  import org.apache.jdo.impl.enhancer.classfile.ClassFile;
43  
44  
45  
46  
47  /***
48   * Utility class for testing two class files for equal augmentation.
49   *
50   * @author Martin Zaun
51   */
52  public class Disassembler
53      extends ClassArgMain
54  {
55      // return values of internal test methods
56      static public final int AFFIRMATIVE = 1;
57      static public final int NEGATIVE = 0;
58      static public final int ERROR = -1;
59  
60      // ----------------------------------------------------------------------
61  
62      private boolean verbose;
63  
64      public Disassembler(PrintWriter out,
65                          PrintWriter err)
66      {
67          super(out, err);
68      }
69  
70      private int disassemble(PrintWriter out,
71                              String className,
72                              String classFileName)
73      {
74          affirm(className == null ^ classFileName == null);
75          final String name = (className != null ? className : classFileName);
76  
77          DataInputStream dis = null;
78          try {
79              if (className != null) {
80                  dis = new DataInputStream(openClassInputStream(className));
81              } else {
82                  dis = new DataInputStream(openFileInputStream(classFileName));
83              }
84              final boolean allowJDK12ClassFiles = true;
85              final ClassFile classFile
86                  = new ClassFile(dis, allowJDK12ClassFiles);
87              out.println("    +++ parsed class");
88  
89              final ByteArrayOutputStream b = new ByteArrayOutputStream();
90              if (verbose) {
91                  classFile.print(new PrintStream(b), 0);
92                  out.println(b.toString());
93              }
94              out.println("Statistics:");
95              classFile.summarize(new PrintStream(b), 4);
96              out.println(b.toString());
97          } catch (ClassFormatError ex) {
98              out.println("    !!! ERROR: format error when parsing class: "
99                          + name);
100             out.println("        error: " + err);
101             return ERROR;
102         } catch (IOException ex) {
103             out.println("    !!! ERROR: exception while reading class: "
104                         + name);
105             out.println("        exception: " + ex);
106             return ERROR;
107         } finally {
108             closeInputStream(dis);
109         }
110 
111         return AFFIRMATIVE;
112     }
113 
114     protected int disassemble(PrintWriter out,
115                               boolean verbose,
116                               List classNames,
117                               List classFileNames)
118     {
119         affirm(classNames);
120         affirm(classFileNames);
121         this.verbose = verbose;
122 
123         out.println();
124         out.println("Disassembler: Dumps out the java byte-code for classes.");
125 
126         int nofFailed = 0;
127         final int all = classNames.size() + classFileNames.size();
128         for (int i = 0; i < classNames.size(); i++) {
129             out.println("-------------------------------------------------------------------------------");
130             out.println();
131         
132             // parse class
133             final String className = (String)classNames.get(i);
134             final StringWriter s = new StringWriter();
135             if (disassemble(new PrintWriter(s), className, null) < NEGATIVE) {
136                 out.println();
137                 out.println("!!! ERROR: failed disassembling class: "
138                             + className);
139                 out.println(s.toString());
140                 nofFailed++;
141             }
142 
143             out.println("+++ disassembled class: " + className);
144             out.println();
145             out.println(s.toString());
146         }
147         for (int i = 0; i < classFileNames.size(); i++) {
148             out.println("-------------------------------------------------------------------------------");
149             out.println();
150         
151             // parse class
152             final String classFileName = (String)classFileNames.get(i);
153             final StringWriter s = new StringWriter();
154             if (disassemble(new PrintWriter(s), null, classFileName) < NEGATIVE) {
155                 out.println();
156                 out.println("!!! ERROR: failed disassembling class: "
157                             + classFileName);
158                 out.println(s.toString());
159                 nofFailed++;
160             }
161 
162             out.println("+++ disassembled class: " + classFileName);
163             out.println();
164             out.println(s.toString());
165         }
166         final int nofPassed = all - nofFailed;
167 
168         out.println();
169         out.println("Disassembler: Summary:  PROCESSED: " + all
170                     + "  PASSED: " + nofPassed
171                     + "  FAILED: " + nofFailed);
172         return nofFailed;
173     }
174     
175     // ----------------------------------------------------------------------
176 
177     /***
178      * Run the disassembler.
179      */
180     protected int process()
181     {
182         //^olsen: to be extended for zip/jar arguments
183         return disassemble(out, options.verbose.value,
184                            options.classNames, options.classFileNames);
185     }
186 
187     static public void main(String[] args)
188     {
189         final PrintWriter out = new PrintWriter(System.out, true);
190         out.println("--> Disassembler.main()");
191         final Disassembler main = new Disassembler(out, out);
192         int res = main.run(args);
193         out.println("<-- Disassembler.main(): exit = " + res);
194         System.exit(res);
195     }
196 }