View Javadoc

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