KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > libraries > asm > xml > ASMContentHandler


1 /***
2  * ASM XML Adapter
3  * Copyright (c) 2000,2002,2003 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31 package oracle.toplink.libraries.asm.xml;
32
33 import java.io.IOException JavaDoc;
34 import java.io.OutputStream JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39
40 import oracle.toplink.libraries.asm.ClassWriter;
41 import oracle.toplink.libraries.asm.CodeVisitor;
42 import oracle.toplink.libraries.asm.Constants;
43 import oracle.toplink.libraries.asm.Label;
44
45 import org.xml.sax.Attributes JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import org.xml.sax.helpers.DefaultHandler JavaDoc;
48
49
50 /**
51  * A {@link org.xml.sax.ContentHandler ContentHandler}
52  * that transforms XML document into Java class file. This class can be feeded by any
53  * kind of SAX 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
54  *
55  * @see oracle.toplink.libraries.asm.xml.SAXClassAdapter
56  * @see oracle.toplink.libraries.asm.xml.Processor
57  *
58  * @author Eugene Kuleshov
59  */

60 public class ASMContentHandler extends DefaultHandler JavaDoc implements Constants {
61   /**
62    * Stack of the intermediate processing contexts.
63    */

64   private List JavaDoc stack = new ArrayList JavaDoc();
65   /**
66    * Complete name of the current element.
67    */

68   private String JavaDoc match = "";
69
70   /**
71    * <tt>true</tt> if the maximum stack size and number of local variables must
72    * be automatically computed.
73    */

74   protected boolean computeMax;
75   /**
76    * Output stream to write result bytecode.
77    */

78   protected OutputStream JavaDoc os;
79
80   /**
81    * Current instance of the {@link ClassWriter ClassWriter} used to write class bytecode.
82    */

83   protected ClassWriter cw;
84   /**
85    * Current instance of the {@link CodeVisitor CodeVisitor} used to write method bytecode
86    */

87   protected CodeVisitor mw;
88   /**
89    * Map of the active {@link Label Label} instances for current method.
90    */

91   protected Map JavaDoc labels;
92   
93   private static final String JavaDoc BASE = "class";
94   private final Rule[] RULES = {
95       new ClassRule( BASE),
96       new InterfaceRule( BASE+"/interfaces/interface"),
97       new InterfacesRule( BASE+"/interfaces"),
98       new FieldRule( BASE+"/field"),
99       new MethodRule( BASE+"/method"),
100       new ExceptionRule( BASE+"/method/exceptions/exception"),
101       new ExceptionsRule( BASE+"/method/exceptions"),
102       new InnerClassRule( BASE+"/innerclass"),
103       
104       new OpcodesRule( BASE+"/method/code/"), // opcodes
105

106       new TableSwitchRule( BASE+"/method/code/TABLESWITCH"),
107       new TableSwitchLabelRule( BASE+"/method/code/TABLESWITCH/label"),
108       new LookupSwitchRule( BASE+"/method/code/LOOKUPSWITCH"),
109       new LookupSwitchLabelRule( BASE+"/method/code/LOOKUPSWITCH/label"),
110
111       new LabelRule( BASE+"/method/code/Label"),
112       new TryCatchRule( BASE+"/method/code/TryCatch"),
113       new LineNumberRule( BASE+"/method/code/LineNumber"),
114       new LocalVarRule( BASE+"/method/code/LocalVar"),
115       new MaxRule( BASE+"/method/code/Max")
116     };
117   
118   private static interface OpcodeGroup {
119     public static final int INSN = 0;
120     public static final int INSN_INT = 1;
121     public static final int INSN_VAR = 2;
122     public static final int INSN_TYPE = 3;
123     public static final int INSN_FIELD = 4;
124     public static final int INSN_METHOD = 5;
125     public static final int INSN_JUMP = 6;
126     public static final int INSN_LDC = 7;
127     public static final int INSN_IINC = 8;
128     public static final int INSN_MULTIANEWARRAY = 9;
129   }
130   
131   /**
132    * Map of the opcode names to opcode and opcode group
133    */

134   static final Map JavaDoc OPCODES = new HashMap JavaDoc();
135   static {
136     OPCODES.put( "NOP", new Opcode( NOP, OpcodeGroup.INSN));
137     OPCODES.put( "ACONST_NULL", new Opcode( ACONST_NULL, OpcodeGroup.INSN));
138     OPCODES.put( "ICONST_M1", new Opcode( ICONST_M1, OpcodeGroup.INSN));
139     OPCODES.put( "ICONST_0", new Opcode( ICONST_0, OpcodeGroup.INSN));
140     OPCODES.put( "ICONST_1", new Opcode( ICONST_1, OpcodeGroup.INSN));
141     OPCODES.put( "ICONST_2", new Opcode( ICONST_2, OpcodeGroup.INSN));
142     OPCODES.put( "ICONST_3", new Opcode( ICONST_3, OpcodeGroup.INSN));
143     OPCODES.put( "ICONST_4", new Opcode( ICONST_4, OpcodeGroup.INSN));
144     OPCODES.put( "ICONST_5", new Opcode( ICONST_5, OpcodeGroup.INSN));
145     OPCODES.put( "LCONST_0", new Opcode( LCONST_0, OpcodeGroup.INSN));
146     OPCODES.put( "LCONST_1", new Opcode( LCONST_1, OpcodeGroup.INSN));
147     OPCODES.put( "FCONST_0", new Opcode( FCONST_0, OpcodeGroup.INSN));
148     OPCODES.put( "FCONST_1", new Opcode( FCONST_1, OpcodeGroup.INSN));
149     OPCODES.put( "FCONST_2", new Opcode( FCONST_2, OpcodeGroup.INSN));
150     OPCODES.put( "DCONST_0", new Opcode( DCONST_0, OpcodeGroup.INSN));
151     OPCODES.put( "DCONST_1", new Opcode( DCONST_1, OpcodeGroup.INSN));
152     OPCODES.put( "BIPUSH", new Opcode( BIPUSH, OpcodeGroup.INSN_INT));
153     OPCODES.put( "SIPUSH", new Opcode( SIPUSH, OpcodeGroup.INSN_INT));
154     OPCODES.put( "LDC", new Opcode( LDC, OpcodeGroup.INSN_LDC));
155     OPCODES.put( "ILOAD", new Opcode( ILOAD, OpcodeGroup.INSN_VAR));
156     OPCODES.put( "LLOAD", new Opcode( LLOAD, OpcodeGroup.INSN_VAR));
157     OPCODES.put( "FLOAD", new Opcode( FLOAD, OpcodeGroup.INSN_VAR));
158     OPCODES.put( "DLOAD", new Opcode( DLOAD, OpcodeGroup.INSN_VAR));
159     OPCODES.put( "ALOAD", new Opcode( ALOAD, OpcodeGroup.INSN_VAR));
160     OPCODES.put( "IALOAD", new Opcode( IALOAD, OpcodeGroup.INSN));
161     OPCODES.put( "LALOAD", new Opcode( LALOAD, OpcodeGroup.INSN));
162     OPCODES.put( "FALOAD", new Opcode( FALOAD, OpcodeGroup.INSN));
163     OPCODES.put( "DALOAD", new Opcode( DALOAD, OpcodeGroup.INSN));
164     OPCODES.put( "AALOAD", new Opcode( AALOAD, OpcodeGroup.INSN));
165     OPCODES.put( "BALOAD", new Opcode( BALOAD, OpcodeGroup.INSN));
166     OPCODES.put( "CALOAD", new Opcode( CALOAD, OpcodeGroup.INSN));
167     OPCODES.put( "SALOAD", new Opcode( SALOAD, OpcodeGroup.INSN));
168     OPCODES.put( "ISTORE", new Opcode( ISTORE, OpcodeGroup.INSN_VAR));
169     OPCODES.put( "LSTORE", new Opcode( LSTORE, OpcodeGroup.INSN_VAR));
170     OPCODES.put( "FSTORE", new Opcode( FSTORE, OpcodeGroup.INSN_VAR));
171     OPCODES.put( "DSTORE", new Opcode( DSTORE, OpcodeGroup.INSN_VAR));
172     OPCODES.put( "ASTORE", new Opcode( ASTORE, OpcodeGroup.INSN_VAR));
173     OPCODES.put( "IASTORE", new Opcode( IASTORE, OpcodeGroup.INSN));
174     OPCODES.put( "LASTORE", new Opcode( LASTORE, OpcodeGroup.INSN));
175     OPCODES.put( "FASTORE", new Opcode( FASTORE, OpcodeGroup.INSN));
176     OPCODES.put( "DASTORE", new Opcode( DASTORE, OpcodeGroup.INSN));
177     OPCODES.put( "AASTORE", new Opcode( AASTORE, OpcodeGroup.INSN));
178     OPCODES.put( "BASTORE", new Opcode( BASTORE, OpcodeGroup.INSN));
179     OPCODES.put( "CASTORE", new Opcode( CASTORE, OpcodeGroup.INSN));
180     OPCODES.put( "SASTORE", new Opcode( SASTORE, OpcodeGroup.INSN));
181     OPCODES.put( "POP", new Opcode( POP, OpcodeGroup.INSN));
182     OPCODES.put( "POP2", new Opcode( POP2, OpcodeGroup.INSN));
183     OPCODES.put( "DUP", new Opcode( DUP, OpcodeGroup.INSN));
184     OPCODES.put( "DUP_X1", new Opcode( DUP_X1, OpcodeGroup.INSN));
185     OPCODES.put( "DUP_X2", new Opcode( DUP_X2, OpcodeGroup.INSN));
186     OPCODES.put( "DUP2", new Opcode( DUP2, OpcodeGroup.INSN));
187     OPCODES.put( "DUP2_X1", new Opcode( DUP2_X1, OpcodeGroup.INSN));
188     OPCODES.put( "DUP2_X2", new Opcode( DUP2_X2, OpcodeGroup.INSN));
189     OPCODES.put( "SWAP", new Opcode( SWAP, OpcodeGroup.INSN));
190     OPCODES.put( "IADD", new Opcode( IADD, OpcodeGroup.INSN));
191     OPCODES.put( "LADD", new Opcode( LADD, OpcodeGroup.INSN));
192     OPCODES.put( "FADD", new Opcode( FADD, OpcodeGroup.INSN));
193     OPCODES.put( "DADD", new Opcode( DADD, OpcodeGroup.INSN));
194     OPCODES.put( "ISUB", new Opcode( ISUB, OpcodeGroup.INSN));
195     OPCODES.put( "LSUB", new Opcode( LSUB, OpcodeGroup.INSN));
196     OPCODES.put( "FSUB", new Opcode( FSUB, OpcodeGroup.INSN));
197     OPCODES.put( "DSUB", new Opcode( DSUB, OpcodeGroup.INSN));
198     OPCODES.put( "IMUL", new Opcode( IMUL, OpcodeGroup.INSN));
199     OPCODES.put( "LMUL", new Opcode( LMUL, OpcodeGroup.INSN));
200     OPCODES.put( "FMUL", new Opcode( FMUL, OpcodeGroup.INSN));
201     OPCODES.put( "DMUL", new Opcode( DMUL, OpcodeGroup.INSN));
202     OPCODES.put( "IDIV", new Opcode( IDIV, OpcodeGroup.INSN));
203     OPCODES.put( "LDIV", new Opcode( LDIV, OpcodeGroup.INSN));
204     OPCODES.put( "FDIV", new Opcode( FDIV, OpcodeGroup.INSN));
205     OPCODES.put( "DDIV", new Opcode( DDIV, OpcodeGroup.INSN));
206     OPCODES.put( "IREM", new Opcode( IREM, OpcodeGroup.INSN));
207     OPCODES.put( "LREM", new Opcode( LREM, OpcodeGroup.INSN));
208     OPCODES.put( "FREM", new Opcode( FREM, OpcodeGroup.INSN));
209     OPCODES.put( "DREM", new Opcode( DREM, OpcodeGroup.INSN));
210     OPCODES.put( "INEG", new Opcode( INEG, OpcodeGroup.INSN));
211     OPCODES.put( "LNEG", new Opcode( LNEG, OpcodeGroup.INSN));
212     OPCODES.put( "FNEG", new Opcode( FNEG, OpcodeGroup.INSN));
213     OPCODES.put( "DNEG", new Opcode( DNEG, OpcodeGroup.INSN));
214     OPCODES.put( "ISHL", new Opcode( ISHL, OpcodeGroup.INSN));
215     OPCODES.put( "LSHL", new Opcode( LSHL, OpcodeGroup.INSN));
216     OPCODES.put( "ISHR", new Opcode( ISHR, OpcodeGroup.INSN));
217     OPCODES.put( "LSHR", new Opcode( LSHR, OpcodeGroup.INSN));
218     OPCODES.put( "IUSHR", new Opcode( IUSHR, OpcodeGroup.INSN));
219     OPCODES.put( "LUSHR", new Opcode( LUSHR, OpcodeGroup.INSN));
220     OPCODES.put( "IAND", new Opcode( IAND, OpcodeGroup.INSN));
221     OPCODES.put( "LAND", new Opcode( LAND, OpcodeGroup.INSN));
222     OPCODES.put( "IOR", new Opcode( IOR, OpcodeGroup.INSN));
223     OPCODES.put( "LOR", new Opcode( LOR, OpcodeGroup.INSN));
224     OPCODES.put( "IXOR", new Opcode( IXOR, OpcodeGroup.INSN));
225     OPCODES.put( "LXOR", new Opcode( LXOR, OpcodeGroup.INSN));
226     OPCODES.put( "IINC", new Opcode( IINC, OpcodeGroup.INSN_IINC));
227     OPCODES.put( "I2L", new Opcode( I2L, OpcodeGroup.INSN));
228     OPCODES.put( "I2F", new Opcode( I2F, OpcodeGroup.INSN));
229     OPCODES.put( "I2D", new Opcode( I2D, OpcodeGroup.INSN));
230     OPCODES.put( "L2I", new Opcode( L2I, OpcodeGroup.INSN));
231     OPCODES.put( "L2F", new Opcode( L2F, OpcodeGroup.INSN));
232     OPCODES.put( "L2D", new Opcode( L2D, OpcodeGroup.INSN));
233     OPCODES.put( "F2I", new Opcode( F2I, OpcodeGroup.INSN));
234     OPCODES.put( "F2L", new Opcode( F2L, OpcodeGroup.INSN));
235     OPCODES.put( "F2D", new Opcode( F2D, OpcodeGroup.INSN));
236     OPCODES.put( "D2I", new Opcode( D2I, OpcodeGroup.INSN));
237     OPCODES.put( "D2L", new Opcode( D2L, OpcodeGroup.INSN));
238     OPCODES.put( "D2F", new Opcode( D2F, OpcodeGroup.INSN));
239     OPCODES.put( "I2B", new Opcode( I2B, OpcodeGroup.INSN));
240     OPCODES.put( "I2C", new Opcode( I2C, OpcodeGroup.INSN));
241     OPCODES.put( "I2S", new Opcode( I2S, OpcodeGroup.INSN));
242     OPCODES.put( "LCMP", new Opcode( LCMP, OpcodeGroup.INSN));
243     OPCODES.put( "FCMPL", new Opcode( FCMPL, OpcodeGroup.INSN));
244     OPCODES.put( "FCMPG", new Opcode( FCMPG, OpcodeGroup.INSN));
245     OPCODES.put( "DCMPL", new Opcode( DCMPL, OpcodeGroup.INSN));
246     OPCODES.put( "DCMPG", new Opcode( DCMPG, OpcodeGroup.INSN));
247     OPCODES.put( "IFEQ", new Opcode( IFEQ, OpcodeGroup.INSN_JUMP));
248     OPCODES.put( "IFNE", new Opcode( IFNE, OpcodeGroup.INSN_JUMP));
249     OPCODES.put( "IFLT", new Opcode( IFLT, OpcodeGroup.INSN_JUMP));
250     OPCODES.put( "IFGE", new Opcode( IFGE, OpcodeGroup.INSN_JUMP));
251     OPCODES.put( "IFGT", new Opcode( IFGT, OpcodeGroup.INSN_JUMP));
252     OPCODES.put( "IFLE", new Opcode( IFLE, OpcodeGroup.INSN_JUMP));
253     OPCODES.put( "IF_ICMPEQ", new Opcode( IF_ICMPEQ, OpcodeGroup.INSN_JUMP));
254     OPCODES.put( "IF_ICMPNE", new Opcode( IF_ICMPNE, OpcodeGroup.INSN_JUMP));
255     OPCODES.put( "IF_ICMPLT", new Opcode( IF_ICMPLT, OpcodeGroup.INSN_JUMP));
256     OPCODES.put( "IF_ICMPGE", new Opcode( IF_ICMPGE, OpcodeGroup.INSN_JUMP));
257     OPCODES.put( "IF_ICMPGT", new Opcode( IF_ICMPGT, OpcodeGroup.INSN_JUMP));
258     OPCODES.put( "IF_ICMPLE", new Opcode( IF_ICMPLE, OpcodeGroup.INSN_JUMP));
259     OPCODES.put( "IF_ACMPEQ", new Opcode( IF_ACMPEQ, OpcodeGroup.INSN_JUMP));
260     OPCODES.put( "IF_ACMPNE", new Opcode( IF_ACMPNE, OpcodeGroup.INSN_JUMP));
261     OPCODES.put( "GOTO", new Opcode( GOTO, OpcodeGroup.INSN_JUMP));
262     OPCODES.put( "JSR", new Opcode( JSR, OpcodeGroup.INSN_JUMP));
263     OPCODES.put( "RET", new Opcode( RET, OpcodeGroup.INSN_VAR));
264     // OPCODES.put( "TABLESWITCH", new Opcode( TABLESWITCH, "visiTableSwitchInsn"));
265
// OPCODES.put( "LOOKUPSWITCH", new Opcode( LOOKUPSWITCH, "visitLookupSwitch"));
266
OPCODES.put( "IRETURN", new Opcode( IRETURN, OpcodeGroup.INSN));
267     OPCODES.put( "LRETURN", new Opcode( LRETURN, OpcodeGroup.INSN));
268     OPCODES.put( "FRETURN", new Opcode( FRETURN, OpcodeGroup.INSN));
269     OPCODES.put( "DRETURN", new Opcode( DRETURN, OpcodeGroup.INSN));
270     OPCODES.put( "ARETURN", new Opcode( ARETURN, OpcodeGroup.INSN));
271     OPCODES.put( "RETURN", new Opcode( RETURN, OpcodeGroup.INSN));
272     OPCODES.put( "GETSTATIC", new Opcode( GETSTATIC, OpcodeGroup.INSN_FIELD));
273     OPCODES.put( "PUTSTATIC", new Opcode( PUTSTATIC, OpcodeGroup.INSN_FIELD));
274     OPCODES.put( "GETFIELD", new Opcode( GETFIELD, OpcodeGroup.INSN_FIELD));
275     OPCODES.put( "PUTFIELD", new Opcode( PUTFIELD, OpcodeGroup.INSN_FIELD));
276     OPCODES.put( "INVOKEVIRTUAL", new Opcode( INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD));
277     OPCODES.put( "INVOKESPECIAL", new Opcode( INVOKESPECIAL, OpcodeGroup.INSN_METHOD));
278     OPCODES.put( "INVOKESTATIC", new Opcode( INVOKESTATIC, OpcodeGroup.INSN_METHOD));
279     OPCODES.put( "INVOKEINTERFACE", new Opcode( INVOKEINTERFACE, OpcodeGroup.INSN_METHOD));
280     OPCODES.put( "NEW", new Opcode( NEW, OpcodeGroup.INSN_TYPE));
281     OPCODES.put( "NEWARRAY", new Opcode( NEWARRAY, OpcodeGroup.INSN_INT));
282     OPCODES.put( "ANEWARRAY", new Opcode( ANEWARRAY, OpcodeGroup.INSN_TYPE));
283     OPCODES.put( "ARRAYLENGTH", new Opcode( ARRAYLENGTH, OpcodeGroup.INSN));
284     OPCODES.put( "ATHROW", new Opcode( ATHROW, OpcodeGroup.INSN));
285     OPCODES.put( "CHECKCAST", new Opcode( CHECKCAST, OpcodeGroup.INSN_TYPE));
286     OPCODES.put( "INSTANCEOF", new Opcode( INSTANCEOF, OpcodeGroup.INSN_TYPE));
287     OPCODES.put( "MONITORENTER", new Opcode( MONITORENTER, OpcodeGroup.INSN));
288     OPCODES.put( "MONITOREXIT", new Opcode( MONITOREXIT, OpcodeGroup.INSN));
289     OPCODES.put( "MULTIANEWARRAY", new Opcode( MULTIANEWARRAY, OpcodeGroup.INSN_MULTIANEWARRAY));
290     OPCODES.put( "IFNULL", new Opcode( IFNULL, OpcodeGroup.INSN_JUMP));
291     OPCODES.put( "IFNONNULL", new Opcode( IFNONNULL, OpcodeGroup.INSN_JUMP));
292   }
293
294   /**
295    * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
296    *
297    * @param os output stream to write generated class.
298    * @param computeMax <tt>true</tt> if the maximum stack size and the maximum
299    * number of local variables must be automatically computed.
300    * This value is passed to {@link ClassWriter ClassWriter}
301    * instance.
302    */

303   public ASMContentHandler( OutputStream JavaDoc os, boolean computeMax) {
304     this.os = os;
305     this.computeMax = computeMax;
306   }
307
308   /**
309    * Returns the bytecode of the class that was build with underneath class writer.
310    *
311    * @return the bytecode of the class that was build with underneath class writer or
312    * null if there are no classwriter created.
313    */

314   public byte[] toByteArray() {
315     return cw==null ? null : cw.toByteArray();
316   }
317   
318   /**
319    * Process notification of the start of an XML element being reached.
320    *
321    * @param ns - The Namespace URI, or the empty string if the element has no
322    * Namespace URI or if Namespace processing is not being performed.
323    * @param localName - The local name (without prefix), or the empty string if Namespace
324    * processing is not being performed.
325    * @param qName - The qualified name (with prefix), or the empty string if
326    * qualified names are not available.
327    * @param list - The attributes attached to the element. If there are no
328    * attributes, it shall be an empty Attributes object.
329    * @exception SAXException if a parsing error is to be reported
330    */

331   public final void startElement( String JavaDoc ns, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc list) throws SAXException JavaDoc {
332     // the actual element name is either in localName or qName, depending
333
// on whether the parser is namespace aware
334
String JavaDoc name = localName;
335     if( name==null || name.length()<1) {
336       name = qName;
337     }
338
339     // Compute the current matching rule
340
StringBuffer JavaDoc sb = new StringBuffer JavaDoc( match);
341     if( match.length() > 0) {
342       sb.append( '/');
343     }
344     sb.append( name);
345     match = sb.toString();
346
347     // Fire "begin" events for all relevant rules
348
for( int i = 0; i < RULES.length; i++) {
349       if( RULES[ i].match( match, name)) {
350         RULES[ i].begin( name, list);
351       }
352     }
353   }
354
355   /**
356    * Process notification of the end of an XML element being reached.
357    *
358    * @param ns - The Namespace URI, or the empty string if the
359    * element has no Namespace URI or if Namespace processing is not
360    * being performed.
361    * @param localName - The local name (without prefix), or the empty
362    * string if Namespace processing is not being performed.
363    * @param qName - The qualified XML 1.0 name (with prefix), or the
364    * empty string if qualified names are not available.
365    *
366    * @exception SAXException if a parsing error is to be reported
367    */

368   public final void endElement( String JavaDoc ns, String JavaDoc localName, String JavaDoc qName) throws SAXException JavaDoc {
369     // the actual element name is either in localName or qName, depending
370
// on whether the parser is namespace aware
371
String JavaDoc name = localName;
372     if( name == null || name.length() < 1) {
373       name = qName;
374     }
375
376     // Fire "end" events for all relevant rules in reverse order
377
for( int i = 0; i < RULES.length; i++) {
378       if( RULES[ i].match( match, name)) {
379         RULES[ i].end( name);
380       }
381     }
382
383     // Recover the previous match expression
384
int slash = match.lastIndexOf( '/');
385     if( slash >= 0) {
386       match = match.substring( 0, slash);
387     } else {
388       match = "";
389     }
390   }
391
392   /**
393    * Process notification of the end of a document and write generated bytecode
394    * into output stream.
395    *
396    * @exception SAXException if parsing or writing error is to be reported.
397    */

398   public final void endDocument() throws SAXException JavaDoc {
399     try {
400       os.write( cw.toByteArray());
401     } catch( IOException JavaDoc ex) {
402       throw new SAXException JavaDoc( ex.toString(), ex);
403     }
404   }
405
406
407   /**
408    * Return the top object on the stack without removing it. If there are no
409    * objects on the stack, return <code>null</code>.
410    */

411   final Object JavaDoc peek() {
412     return stack.size()==0 ? null : stack.get( stack.size()-1);
413   }
414
415
416   /**
417    * Return the n'th object down the stack, where 0 is the top element
418    * and [getCount()-1] is the bottom element. If the specified index
419    * is out of range, return <code>null</code>.
420    *
421    * @param n Index of the desired element, where 0 is the top of the stack,
422    * 1 is the next element down, and so on.
423    */

424   final Object JavaDoc peek(int n) {
425     return stack.size()<( n+1) ? null : stack.get( n);
426   }
427
428
429   /**
430    * Pop the top object off of the stack, and return it. If there are
431    * no objects on the stack, return <code>null</code>.
432    */

433   final Object JavaDoc pop() {
434     return stack.size()==0 ? null : stack.remove( stack.size()-1);
435   }
436
437   /**
438    * Push a new object onto the top of the object stack.
439    *
440    * @param object The new object
441    */

442   final void push(Object JavaDoc object) {
443     stack.add( object);
444   }
445
446
447   /**
448    * Rule
449    */

450   private abstract class Rule {
451     protected String JavaDoc path;
452
453     public Rule( String JavaDoc path) {
454       this.path = path;
455     }
456
457     public final String JavaDoc getPath() {
458       return path;
459     }
460
461     public void begin( String JavaDoc name, Attributes JavaDoc attrs) {
462     }
463     
464     public void end( String JavaDoc name) {
465     }
466
467     public boolean match( String JavaDoc match, String JavaDoc element) {
468       return path.equals( match);
469     }
470
471     protected final Object JavaDoc getValue( String JavaDoc desc, String JavaDoc val) {
472       Object JavaDoc value = null;
473       if( val!=null) {
474         if( desc.equals( "Ljava/lang/String;")) {
475           value = decode( val);
476         } else if( desc.equals( "Ljava/lang/Integer;") ||
477             desc.equals( "Z") || desc.equals( "B") || desc.equals( "C") || desc.equals( "I") || desc.equals( "S")) {
478           value = new Integer JavaDoc( val);
479         } else if( desc.equals( "Ljava/lang/Long;") || desc.equals( "J")) {
480           value = new Long JavaDoc( val);
481         } else if( desc.equals( "Ljava/lang/Float;") || desc.equals( "F")) {
482           value = new Float JavaDoc( val);
483         } else if( desc.equals( "Ljava/lang/Double;") || desc.equals( "D")) {
484           value = new Double JavaDoc( val);
485         } else {
486           throw new RuntimeException JavaDoc( "Invalid value:"+val+" desc:"+desc+" ctx:"+this);
487         }
488       }
489       return value;
490     }
491
492     private final String JavaDoc decode( String JavaDoc val) {
493       StringBuffer JavaDoc sb = new StringBuffer JavaDoc( val.length());
494       try {
495         int n = 0;
496         while( n < val.length()) {
497           char c = val.charAt( n);
498           if( c == '\\') {
499             n++;
500             c = val.charAt( n);
501             if( c == '\\') {
502               sb.append( '\\');
503             } else {
504               n++; // skip 'u'
505
sb.append( ( char) Integer.parseInt( val.substring( n, n + 4), 16));
506               n += 3;
507             }
508           } else {
509             sb.append( c);
510           }
511           n++;
512         }
513         
514       } catch( RuntimeException JavaDoc ex) {
515         System.err.println( val+"\n"+ex.toString());
516         ex.printStackTrace();
517         throw ex;
518       }
519       return sb.toString();
520     }
521
522     protected final Label getLabel( Object JavaDoc label) {
523       Label lbl = ( Label) labels.get( label);
524       if( lbl==null) {
525         lbl = new Label();
526         labels.put( label, lbl);
527       }
528       return lbl;
529     }
530     
531     public String JavaDoc toString() {
532       return path;
533     }
534
535     protected final CodeVisitor getCodeVisitor() {
536       if( mw==null) {
537         Map JavaDoc vals = ( Map JavaDoc) pop();
538         int access = Integer.parseInt(( String JavaDoc) vals.get( "access"), 16);
539         String JavaDoc name = ( String JavaDoc) vals.get( "name");
540         String JavaDoc desc = ( String JavaDoc) vals.get( "desc");
541         mw = cw.visitMethod( access, name, desc, null, null);
542       }
543       return mw;
544     }
545
546     protected final int getAccess( String JavaDoc s) {
547       int access = 0;
548       if( s.indexOf( "public")!=-1) access |= Constants.ACC_PUBLIC;
549       if( s.indexOf( "private")!=-1) access |= Constants.ACC_PRIVATE;
550       if( s.indexOf( "protected")!=-1) access |= Constants.ACC_PROTECTED;
551       if( s.indexOf( "static")!=-1) access |= Constants.ACC_STATIC;
552       if( s.indexOf( "final")!=-1) access |= Constants.ACC_FINAL;
553       if( s.indexOf( "super")!=-1) access |= Constants.ACC_SUPER;
554       if( s.indexOf( "synchronized")!=-1) access |= Constants.ACC_SYNCHRONIZED;
555       if( s.indexOf( "volatile")!=-1) access |= Constants.ACC_VOLATILE;
556       if( s.indexOf( "bridge")!=-1) access |= Constants.ACC_BRIDGE;
557       if( s.indexOf( "varargs")!=-1) access |= Constants.ACC_VARARGS;
558       if( s.indexOf( "transient")!=-1) access |= Constants.ACC_TRANSIENT;
559       if( s.indexOf( "native")!=-1) access |= Constants.ACC_NATIVE;
560       if( s.indexOf( "interface")!=-1) access |= Constants.ACC_INTERFACE;
561       if( s.indexOf( "abstract")!=-1) access |= Constants.ACC_ABSTRACT;
562       if( s.indexOf( "strict")!=-1) access |= Constants.ACC_STRICT;
563       if( s.indexOf( "synthetic")!=-1) access |= Constants.ACC_SYNTHETIC;
564       if( s.indexOf( "annotation")!=-1) access |= Constants.ACC_ANNOTATION;
565       if( s.indexOf( "enum")!=-1) access |= Constants.ACC_ENUM;
566       if( s.indexOf( "deprecated")!=-1) access |= Constants.ACC_DEPRECATED;
567       return access;
568     }
569     
570   }
571
572   /**
573    * ClassRule
574    */

575   private final class ClassRule extends Rule {
576
577     public ClassRule( String JavaDoc path) {
578       super( path);
579     }
580     
581     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
582       int major = Integer.parseInt( attrs.getValue( "major"));
583       int minor = Integer.parseInt( attrs.getValue( "minor"));
584       cw = new ClassWriter( computeMax);
585       Map JavaDoc vals = new HashMap JavaDoc();
586       vals.put( "version", new Integer JavaDoc(minor << 16 | major));
587       vals.put( "access", attrs.getValue( "access"));
588       vals.put( "name", attrs.getValue( "name"));
589       vals.put( "parent", attrs.getValue( "parent"));
590       vals.put( "source", attrs.getValue( "source"));
591       vals.put( "interfaces", new ArrayList JavaDoc());
592       push( vals);
593       // values will be extracted in InterfacesRule.end();
594
}
595
596   }
597
598
599   /**
600    * InterfaceRule
601    */

602   private final class InterfaceRule extends Rule {
603
604     public InterfaceRule( String JavaDoc path) {
605       super( path);
606     }
607
608     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
609       (( List JavaDoc) (( Map JavaDoc) peek()).get( "interfaces")).add( attrs.getValue( "name"));
610     }
611     
612   }
613   
614   
615   /**
616    * InterfacesRule
617    */

618   private final class InterfacesRule extends Rule {
619
620     public InterfacesRule( String JavaDoc path) {
621       super( path);
622     }
623
624     public final void end( String JavaDoc element) {
625       Map JavaDoc vals = ( Map JavaDoc) pop();
626       int version = (( Integer JavaDoc)vals.get( "version")).intValue();
627       int access = getAccess(( String JavaDoc) vals.get( "access"));
628       String JavaDoc name = ( String JavaDoc) vals.get( "name");
629       String JavaDoc parent = ( String JavaDoc) vals.get( "parent");
630       String JavaDoc source = ( String JavaDoc) vals.get( "source");
631       String JavaDoc[] interfaces = ( String JavaDoc[])(( List JavaDoc) vals.get( "interfaces")).toArray( new String JavaDoc[ 0]);
632       cw.visit( version, access, name, parent, interfaces, source);
633     }
634     
635   }
636
637   
638   /**
639    * FieldRule
640    */

641   private final class FieldRule extends Rule {
642
643     public FieldRule( String JavaDoc path) {
644       super( path);
645     }
646
647     public final void begin( String JavaDoc element, Attributes JavaDoc attrs) {
648       int access = getAccess( attrs.getValue( "access"));
649       String JavaDoc name = attrs.getValue( "name");
650       String JavaDoc desc = attrs.getValue( "desc");
651       Object JavaDoc value = getValue( desc, attrs.getValue( "value"));
652       cw.visitField( access, name, desc, value, null);
653     }
654
655   }
656   
657   
658   /**
659    * MethodRule
660    */

661   private final class MethodRule extends Rule {
662
663     public MethodRule( String JavaDoc path) {
664       super( path);
665     }
666     
667     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
668       labels = new HashMap JavaDoc();
669       Map JavaDoc vals = new HashMap JavaDoc();
670       vals.put( "access", attrs.getValue( "access"));
671       vals.put( "name", attrs.getValue( "name"));
672       vals.put( "desc", attrs.getValue( "desc"));
673       vals.put( "exceptions", new ArrayList JavaDoc());
674       push( vals);
675       // values will be extracted in ExceptionsRule.end();
676
}
677     
678     public final void end( String JavaDoc name) {
679       mw = null;
680       labels = null;
681     }
682     
683   }
684
685   
686   /**
687    * MethodRule
688    */

689   private final class InnerClassRule extends Rule {
690
691     public InnerClassRule( String JavaDoc path) {
692       super( path);
693     }
694     
695     public final void begin( String JavaDoc element, Attributes JavaDoc attrs) {
696       int access = getAccess( attrs.getValue( "access"));
697       String JavaDoc name = attrs.getValue( "name");
698       String JavaDoc outerName = attrs.getValue( "outerName");
699       String JavaDoc innerName = attrs.getValue( "innerName");
700       cw.visitInnerClass( name, outerName, innerName, access);
701     }
702     
703     public final void end( String JavaDoc name) {
704       mw = null;
705       labels = null;
706     }
707     
708   }
709
710   
711   /**
712    * ExceptionRule
713    */

714   private final class ExceptionRule extends Rule {
715
716     public ExceptionRule( String JavaDoc path) {
717       super( path);
718     }
719
720     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
721       (( List JavaDoc) (( Map JavaDoc) peek()).get( "exceptions")).add( attrs.getValue( "name"));
722     }
723     
724   }
725   
726   
727   /**
728    * ExceptionsRule
729    */

730   private final class ExceptionsRule extends Rule {
731
732     public ExceptionsRule( String JavaDoc path) {
733       super( path);
734     }
735
736     public final void end( String JavaDoc element) {
737       Map JavaDoc vals = ( Map JavaDoc) pop();
738       int access = getAccess(( String JavaDoc) vals.get( "access"));
739       String JavaDoc name = ( String JavaDoc) vals.get( "name");
740       String JavaDoc desc = ( String JavaDoc) vals.get( "desc");
741       String JavaDoc[] exceptions = ( String JavaDoc[])(( List JavaDoc) vals.get( "exceptions")).toArray( new String JavaDoc[ 0]);
742       
743       mw = cw.visitMethod( access, name, desc, exceptions, null);
744     }
745     
746   }
747
748   
749   /**
750    * TableSwitchRule
751    */

752   private class TableSwitchRule extends Rule {
753
754     public TableSwitchRule( String JavaDoc path) {
755       super( path);
756     }
757
758     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
759       Map JavaDoc vals = new HashMap JavaDoc();
760       vals.put( "min", attrs.getValue( "min"));
761       vals.put( "max", attrs.getValue( "max"));
762       vals.put( "dflt", attrs.getValue( "dflt"));
763       vals.put( "labels", new ArrayList JavaDoc());
764       push( vals);
765     }
766     
767     public final void end( String JavaDoc name) {
768       Map JavaDoc vals = ( Map JavaDoc) pop();
769       int min = Integer.parseInt(( String JavaDoc) vals.get( "min"));
770       int max = Integer.parseInt(( String JavaDoc) vals.get( "max"));
771       Label dflt = getLabel( vals.get( "dflt"));
772       Label[] lbls = ( Label[])(( List JavaDoc) vals.get( "labels")).toArray( new Label[ 0]);
773       getCodeVisitor().visitTableSwitchInsn( min, max, dflt, lbls);
774     }
775     
776   }
777
778   
779   /**
780    * TableSwitchLabelRule
781    */

782   private final class TableSwitchLabelRule extends Rule {
783
784     public TableSwitchLabelRule( String JavaDoc path) {
785       super( path);
786     }
787   
788     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
789       (( List JavaDoc) (( Map JavaDoc) peek()).get( "labels")).add( getLabel( attrs.getValue( "name")));
790     }
791     
792   }
793
794   
795   /**
796    * LookupSwitchRule
797    */

798   private final class LookupSwitchRule extends Rule {
799
800     public LookupSwitchRule( String JavaDoc path) {
801       super( path);
802     }
803
804     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
805       Map JavaDoc vals = new HashMap JavaDoc();
806       vals.put( "dflt", attrs.getValue( "dflt"));
807       vals.put( "labels", new ArrayList JavaDoc());
808       vals.put( "keys", new ArrayList JavaDoc());
809       push( vals);
810     }
811     
812     public final void end( String JavaDoc name) {
813       Map JavaDoc vals = ( Map JavaDoc) pop();
814       Label dflt = getLabel( vals.get( "dflt"));
815       List JavaDoc keyList = ( List JavaDoc) vals.get( "keys");
816       Label[] lbls = ( Label[])(( List JavaDoc) vals.get( "labels")).toArray( new Label[ 0]);
817       int[] keys = new int[ keyList.size()];
818       for( int i = 0; i < keys.length; i++) {
819         keys[ i] = Integer.parseInt(( String JavaDoc) keyList.get( i));
820       }
821       getCodeVisitor().visitLookupSwitchInsn( dflt, keys, lbls);
822     }
823     
824   }
825
826   
827   /**
828    * LookupSwitchLabelRule
829    */

830   private final class LookupSwitchLabelRule extends Rule {
831
832     public LookupSwitchLabelRule( String JavaDoc path) {
833       super( path);
834     }
835   
836     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
837       Map JavaDoc vals = ( Map JavaDoc) peek();
838       (( List JavaDoc) vals.get( "labels")).add( getLabel( attrs.getValue( "name")));
839       (( List JavaDoc) vals.get( "keys")).add( attrs.getValue( "key"));
840     }
841     
842   }
843   
844   
845   /**
846    * LabelRule
847    */

848   private final class LabelRule extends Rule {
849
850     public LabelRule( String JavaDoc path) {
851       super( path);
852     }
853
854     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
855       getCodeVisitor().visitLabel( getLabel( attrs.getValue( "name")));
856     }
857
858   }
859   
860   
861   /**
862    * TryCatchRule
863    */

864   private final class TryCatchRule extends Rule {
865
866     public TryCatchRule( String JavaDoc path) {
867       super( path);
868     }
869
870     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
871       Label start = getLabel( attrs.getValue( "start"));
872       Label end = getLabel( attrs.getValue( "end"));
873       Label handler = getLabel( attrs.getValue( "handler"));
874       String JavaDoc type = attrs.getValue( "type");
875       getCodeVisitor().visitTryCatchBlock( start, end, handler, type);
876     }
877
878   }
879   
880
881   /**
882    * LineNumberRule
883    */

884   private final class LineNumberRule extends Rule {
885
886     public LineNumberRule( String JavaDoc path) {
887       super( path);
888     }
889
890     public final void begin( String JavaDoc name, Attributes JavaDoc attrs) {
891       int line = Integer.parseInt( attrs.getValue( "line"));
892       Label start = getLabel( attrs.getValue( "start"));
893       getCodeVisitor().visitLineNumber( line, start);
894     }
895
896   }
897   
898
899   /**
900    * LocalVarRule
901    */

902   private final class LocalVarRule extends Rule {
903
904     public LocalVarRule( String JavaDoc path) {
905       super( path);
906     }
907
908     public final void begin( String JavaDoc element, Attributes JavaDoc attrs) {
909       String JavaDoc name = attrs.getValue( "name");
910       String JavaDoc desc = attrs.getValue( "desc");
911       Label start = getLabel( attrs.getValue( "start"));
912       Label end = getLabel( attrs.getValue( "end"));
913       int var = Integer.parseInt( attrs.getValue( "var"));
914       getCodeVisitor().visitLocalVariable( name, desc, start, end, var);
915     }
916
917   }
918   
919
920   /**
921    * OpcodesRule
922    */

923   private final class OpcodesRule extends Rule {
924
925     public OpcodesRule( String JavaDoc path) {
926       super( path);
927     }
928
929     public boolean match( String JavaDoc match, String JavaDoc element) {
930       return match.startsWith( path) && OPCODES.containsKey( element);
931     }
932     
933     public final void begin( String JavaDoc element, Attributes JavaDoc attrs) {
934       Opcode o = (( Opcode) OPCODES.get( element));
935       if( o==null) return;
936         
937       switch( o.type) {
938         case OpcodeGroup.INSN:
939           getCodeVisitor().visitInsn( o.opcode);
940           break;
941           
942         case OpcodeGroup.INSN_FIELD:
943           getCodeVisitor().visitFieldInsn( o.opcode, attrs.getValue( "owner"), attrs.getValue( "name"), attrs.getValue( "desc"));
944           break;
945         
946         case OpcodeGroup.INSN_INT:
947           getCodeVisitor().visitIntInsn( o.opcode, Integer.parseInt( attrs.getValue( "value")));
948           break;
949         
950         case OpcodeGroup.INSN_JUMP:
951           getCodeVisitor().visitJumpInsn( o.opcode, getLabel( attrs.getValue( "label")));
952           break;
953         
954         case OpcodeGroup.INSN_METHOD:
955           getCodeVisitor().visitMethodInsn( o.opcode, attrs.getValue( "owner"), attrs.getValue( "name"), attrs.getValue( "desc"));
956           break;
957         
958         case OpcodeGroup.INSN_TYPE:
959           getCodeVisitor().visitTypeInsn( o.opcode, attrs.getValue( "desc"));
960           break;
961         
962         case OpcodeGroup.INSN_VAR:
963           getCodeVisitor().visitVarInsn( o.opcode, Integer.parseInt( attrs.getValue( "var")));
964           break;
965
966         case OpcodeGroup.INSN_IINC:
967           getCodeVisitor().visitIincInsn( Integer.parseInt( attrs.getValue( "var")), Integer.parseInt( attrs.getValue( "inc")));
968           break;
969         
970         case OpcodeGroup.INSN_LDC:
971           getCodeVisitor().visitLdcInsn( getValue( attrs.getValue( "desc"), attrs.getValue( "cst")));
972           break;
973         
974         case OpcodeGroup.INSN_MULTIANEWARRAY:
975           getCodeVisitor().visitMultiANewArrayInsn( attrs.getValue( "desc"), Integer.parseInt( attrs.getValue( "dims")));
976           break;
977           
978         default:
979           throw new RuntimeException JavaDoc( "Invalid element: "+element+" at "+match);
980         
981       }
982     }
983   }
984   
985
986   /**
987    * MaxRule
988    */

989   private final class MaxRule extends Rule {
990
991     public MaxRule( String JavaDoc path) {
992       super( path);
993     }
994
995     public final void begin( String JavaDoc element, Attributes JavaDoc attrs) {
996       int maxStack = Integer.parseInt( attrs.getValue( "maxStack"));
997       int maxLocals = Integer.parseInt( attrs.getValue( "maxLocals"));
998       getCodeVisitor().visitMaxs( maxStack, maxLocals);
999     }
1000
1001  }
1002
1003
1004  /**
1005   * Opcode
1006   */

1007  private final static class Opcode {
1008    public int opcode;
1009    public int type;
1010    
1011    public Opcode( int opcode, int type) {
1012      this.opcode = opcode;
1013      this.type = type;
1014    }
1015
1016  }
1017  
1018}
1019
1020
Popular Tags