0001: /***
0002: * ASM XML Adapter
0003: * Copyright (c) 2004, Eugene Kuleshov
0004: * All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions
0008: * are met:
0009: * 1. Redistributions of source code must retain the above copyright
0010: * notice, this list of conditions and the following disclaimer.
0011: * 2. Redistributions in binary form must reproduce the above copyright
0012: * notice, this list of conditions and the following disclaimer in the
0013: * documentation and/or other materials provided with the distribution.
0014: * 3. Neither the name of the copyright holders nor the names of its
0015: * contributors may be used to endorse or promote products derived from
0016: * this software without specific prior written permission.
0017: *
0018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0028: * THE POSSIBILITY OF SUCH DAMAGE.
0029: */package org.ejb3unit.asm.xml;
0030:
0031: import java.io.IOException;
0032: import java.io.OutputStream;
0033: import java.util.ArrayList;
0034: import java.util.HashMap;
0035: import java.util.Iterator;
0036: import java.util.List;
0037:
0038: import org.ejb3unit.asm.AnnotationVisitor;
0039: import org.ejb3unit.asm.ClassVisitor;
0040: import org.ejb3unit.asm.ClassWriter;
0041: import org.ejb3unit.asm.FieldVisitor;
0042: import org.ejb3unit.asm.Label;
0043: import org.ejb3unit.asm.MethodVisitor;
0044: import org.ejb3unit.asm.Opcodes;
0045: import org.ejb3unit.asm.Type;
0046:
0047: import org.xml.sax.Attributes;
0048: import org.xml.sax.SAXException;
0049: import org.xml.sax.helpers.DefaultHandler;
0050:
0051: /**
0052: * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
0053: * document into Java class file. This class can be feeded by any kind of SAX
0054: * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
0055: *
0056: * @see org.ejb3unit.asm.xml.SAXClassAdapter
0057: * @see org.ejb3unit.asm.xml.Processor
0058: *
0059: * @author Eugene Kuleshov
0060: */
0061: public class ASMContentHandler extends DefaultHandler implements
0062: Opcodes {
0063:
0064: /**
0065: * Stack of the intermediate processing contexts.
0066: */
0067: private final List stack = new ArrayList();
0068:
0069: /**
0070: * Complete name of the current element.
0071: */
0072: private String match = "";
0073:
0074: /**
0075: * <tt>true</tt> if the maximum stack size and number of local variables
0076: * must be automatically computed.
0077: */
0078: protected boolean computeMax;
0079:
0080: /**
0081: * Output stream to write result bytecode.
0082: */
0083: protected OutputStream os;
0084:
0085: /**
0086: * Current instance of the {@link ClassWriter ClassWriter} used to write
0087: * class bytecode.
0088: */
0089: protected ClassWriter cw;
0090:
0091: /**
0092: * Map of the active {@link Label Label} instances for current method.
0093: */
0094: protected HashMap labels;
0095:
0096: private static final String BASE = "class";
0097:
0098: private final RuleSet RULES = new RuleSet();
0099: {
0100: RULES.add(BASE, new ClassRule());
0101: RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
0102: RULES.add(BASE + "/interfaces", new InterfacesRule());
0103: RULES.add(BASE + "/outerclass", new OuterClassRule());
0104: RULES.add(BASE + "/innerclass", new InnerClassRule());
0105: RULES.add(BASE + "/source", new SourceRule());
0106: RULES.add(BASE + "/field", new FieldRule());
0107:
0108: RULES.add(BASE + "/method", new MethodRule());
0109: RULES.add(BASE + "/method/exceptions/exception",
0110: new ExceptionRule());
0111: RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
0112:
0113: RULES.add(BASE + "/method/annotationDefault",
0114: new AnnotationDefaultRule());
0115:
0116: RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
0117:
0118: RULES.add(BASE + "/method/code/frame", new FrameRule());
0119: RULES.add(BASE + "/method/code/frame/local",
0120: new FrameTypeRule());
0121: RULES.add(BASE + "/method/code/frame/stack",
0122: new FrameTypeRule());
0123:
0124: RULES.add(BASE + "/method/code/TABLESWITCH",
0125: new TableSwitchRule());
0126: RULES.add(BASE + "/method/code/TABLESWITCH/label",
0127: new TableSwitchLabelRule());
0128: RULES.add(BASE + "/method/code/LOOKUPSWITCH",
0129: new LookupSwitchRule());
0130: RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
0131: new LookupSwitchLabelRule());
0132:
0133: RULES.add(BASE + "/method/code/Label", new LabelRule());
0134: RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
0135: RULES.add(BASE + "/method/code/LineNumber",
0136: new LineNumberRule());
0137: RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
0138: RULES.add(BASE + "/method/code/Max", new MaxRule());
0139:
0140: RULES.add("*/annotation", new AnnotationRule());
0141: RULES.add("*/parameterAnnotation",
0142: new AnnotationParameterRule());
0143: RULES.add("*/annotationValue", new AnnotationValueRule());
0144: RULES.add("*/annotationValueAnnotation",
0145: new AnnotationValueAnnotationRule());
0146: RULES.add("*/annotationValueEnum",
0147: new AnnotationValueEnumRule());
0148: RULES.add("*/annotationValueArray",
0149: new AnnotationValueArrayRule());
0150: };
0151:
0152: private static interface OpcodeGroup {
0153: public static final int INSN = 0;
0154: public static final int INSN_INT = 1;
0155: public static final int INSN_VAR = 2;
0156: public static final int INSN_TYPE = 3;
0157: public static final int INSN_FIELD = 4;
0158: public static final int INSN_METHOD = 5;
0159: public static final int INSN_JUMP = 6;
0160: public static final int INSN_LDC = 7;
0161: public static final int INSN_IINC = 8;
0162: public static final int INSN_MULTIANEWARRAY = 9;
0163: }
0164:
0165: /**
0166: * Map of the opcode names to opcode and opcode group
0167: */
0168: static final HashMap OPCODES = new HashMap();
0169: static {
0170: OPCODES.put("NOP", new Opcode(NOP, OpcodeGroup.INSN));
0171: OPCODES.put("ACONST_NULL", new Opcode(ACONST_NULL,
0172: OpcodeGroup.INSN));
0173: OPCODES.put("ICONST_M1",
0174: new Opcode(ICONST_M1, OpcodeGroup.INSN));
0175: OPCODES.put("ICONST_0", new Opcode(ICONST_0, OpcodeGroup.INSN));
0176: OPCODES.put("ICONST_1", new Opcode(ICONST_1, OpcodeGroup.INSN));
0177: OPCODES.put("ICONST_2", new Opcode(ICONST_2, OpcodeGroup.INSN));
0178: OPCODES.put("ICONST_3", new Opcode(ICONST_3, OpcodeGroup.INSN));
0179: OPCODES.put("ICONST_4", new Opcode(ICONST_4, OpcodeGroup.INSN));
0180: OPCODES.put("ICONST_5", new Opcode(ICONST_5, OpcodeGroup.INSN));
0181: OPCODES.put("LCONST_0", new Opcode(LCONST_0, OpcodeGroup.INSN));
0182: OPCODES.put("LCONST_1", new Opcode(LCONST_1, OpcodeGroup.INSN));
0183: OPCODES.put("FCONST_0", new Opcode(FCONST_0, OpcodeGroup.INSN));
0184: OPCODES.put("FCONST_1", new Opcode(FCONST_1, OpcodeGroup.INSN));
0185: OPCODES.put("FCONST_2", new Opcode(FCONST_2, OpcodeGroup.INSN));
0186: OPCODES.put("DCONST_0", new Opcode(DCONST_0, OpcodeGroup.INSN));
0187: OPCODES.put("DCONST_1", new Opcode(DCONST_1, OpcodeGroup.INSN));
0188: OPCODES.put("BIPUSH", new Opcode(BIPUSH, OpcodeGroup.INSN_INT));
0189: OPCODES.put("SIPUSH", new Opcode(SIPUSH, OpcodeGroup.INSN_INT));
0190: OPCODES.put("LDC", new Opcode(LDC, OpcodeGroup.INSN_LDC));
0191: OPCODES.put("ILOAD", new Opcode(ILOAD, OpcodeGroup.INSN_VAR));
0192: OPCODES.put("LLOAD", new Opcode(LLOAD, OpcodeGroup.INSN_VAR));
0193: OPCODES.put("FLOAD", new Opcode(FLOAD, OpcodeGroup.INSN_VAR));
0194: OPCODES.put("DLOAD", new Opcode(DLOAD, OpcodeGroup.INSN_VAR));
0195: OPCODES.put("ALOAD", new Opcode(ALOAD, OpcodeGroup.INSN_VAR));
0196: OPCODES.put("IALOAD", new Opcode(IALOAD, OpcodeGroup.INSN));
0197: OPCODES.put("LALOAD", new Opcode(LALOAD, OpcodeGroup.INSN));
0198: OPCODES.put("FALOAD", new Opcode(FALOAD, OpcodeGroup.INSN));
0199: OPCODES.put("DALOAD", new Opcode(DALOAD, OpcodeGroup.INSN));
0200: OPCODES.put("AALOAD", new Opcode(AALOAD, OpcodeGroup.INSN));
0201: OPCODES.put("BALOAD", new Opcode(BALOAD, OpcodeGroup.INSN));
0202: OPCODES.put("CALOAD", new Opcode(CALOAD, OpcodeGroup.INSN));
0203: OPCODES.put("SALOAD", new Opcode(SALOAD, OpcodeGroup.INSN));
0204: OPCODES.put("ISTORE", new Opcode(ISTORE, OpcodeGroup.INSN_VAR));
0205: OPCODES.put("LSTORE", new Opcode(LSTORE, OpcodeGroup.INSN_VAR));
0206: OPCODES.put("FSTORE", new Opcode(FSTORE, OpcodeGroup.INSN_VAR));
0207: OPCODES.put("DSTORE", new Opcode(DSTORE, OpcodeGroup.INSN_VAR));
0208: OPCODES.put("ASTORE", new Opcode(ASTORE, OpcodeGroup.INSN_VAR));
0209: OPCODES.put("IASTORE", new Opcode(IASTORE, OpcodeGroup.INSN));
0210: OPCODES.put("LASTORE", new Opcode(LASTORE, OpcodeGroup.INSN));
0211: OPCODES.put("FASTORE", new Opcode(FASTORE, OpcodeGroup.INSN));
0212: OPCODES.put("DASTORE", new Opcode(DASTORE, OpcodeGroup.INSN));
0213: OPCODES.put("AASTORE", new Opcode(AASTORE, OpcodeGroup.INSN));
0214: OPCODES.put("BASTORE", new Opcode(BASTORE, OpcodeGroup.INSN));
0215: OPCODES.put("CASTORE", new Opcode(CASTORE, OpcodeGroup.INSN));
0216: OPCODES.put("SASTORE", new Opcode(SASTORE, OpcodeGroup.INSN));
0217: OPCODES.put("POP", new Opcode(POP, OpcodeGroup.INSN));
0218: OPCODES.put("POP2", new Opcode(POP2, OpcodeGroup.INSN));
0219: OPCODES.put("DUP", new Opcode(DUP, OpcodeGroup.INSN));
0220: OPCODES.put("DUP_X1", new Opcode(DUP_X1, OpcodeGroup.INSN));
0221: OPCODES.put("DUP_X2", new Opcode(DUP_X2, OpcodeGroup.INSN));
0222: OPCODES.put("DUP2", new Opcode(DUP2, OpcodeGroup.INSN));
0223: OPCODES.put("DUP2_X1", new Opcode(DUP2_X1, OpcodeGroup.INSN));
0224: OPCODES.put("DUP2_X2", new Opcode(DUP2_X2, OpcodeGroup.INSN));
0225: OPCODES.put("SWAP", new Opcode(SWAP, OpcodeGroup.INSN));
0226: OPCODES.put("IADD", new Opcode(IADD, OpcodeGroup.INSN));
0227: OPCODES.put("LADD", new Opcode(LADD, OpcodeGroup.INSN));
0228: OPCODES.put("FADD", new Opcode(FADD, OpcodeGroup.INSN));
0229: OPCODES.put("DADD", new Opcode(DADD, OpcodeGroup.INSN));
0230: OPCODES.put("ISUB", new Opcode(ISUB, OpcodeGroup.INSN));
0231: OPCODES.put("LSUB", new Opcode(LSUB, OpcodeGroup.INSN));
0232: OPCODES.put("FSUB", new Opcode(FSUB, OpcodeGroup.INSN));
0233: OPCODES.put("DSUB", new Opcode(DSUB, OpcodeGroup.INSN));
0234: OPCODES.put("IMUL", new Opcode(IMUL, OpcodeGroup.INSN));
0235: OPCODES.put("LMUL", new Opcode(LMUL, OpcodeGroup.INSN));
0236: OPCODES.put("FMUL", new Opcode(FMUL, OpcodeGroup.INSN));
0237: OPCODES.put("DMUL", new Opcode(DMUL, OpcodeGroup.INSN));
0238: OPCODES.put("IDIV", new Opcode(IDIV, OpcodeGroup.INSN));
0239: OPCODES.put("LDIV", new Opcode(LDIV, OpcodeGroup.INSN));
0240: OPCODES.put("FDIV", new Opcode(FDIV, OpcodeGroup.INSN));
0241: OPCODES.put("DDIV", new Opcode(DDIV, OpcodeGroup.INSN));
0242: OPCODES.put("IREM", new Opcode(IREM, OpcodeGroup.INSN));
0243: OPCODES.put("LREM", new Opcode(LREM, OpcodeGroup.INSN));
0244: OPCODES.put("FREM", new Opcode(FREM, OpcodeGroup.INSN));
0245: OPCODES.put("DREM", new Opcode(DREM, OpcodeGroup.INSN));
0246: OPCODES.put("INEG", new Opcode(INEG, OpcodeGroup.INSN));
0247: OPCODES.put("LNEG", new Opcode(LNEG, OpcodeGroup.INSN));
0248: OPCODES.put("FNEG", new Opcode(FNEG, OpcodeGroup.INSN));
0249: OPCODES.put("DNEG", new Opcode(DNEG, OpcodeGroup.INSN));
0250: OPCODES.put("ISHL", new Opcode(ISHL, OpcodeGroup.INSN));
0251: OPCODES.put("LSHL", new Opcode(LSHL, OpcodeGroup.INSN));
0252: OPCODES.put("ISHR", new Opcode(ISHR, OpcodeGroup.INSN));
0253: OPCODES.put("LSHR", new Opcode(LSHR, OpcodeGroup.INSN));
0254: OPCODES.put("IUSHR", new Opcode(IUSHR, OpcodeGroup.INSN));
0255: OPCODES.put("LUSHR", new Opcode(LUSHR, OpcodeGroup.INSN));
0256: OPCODES.put("IAND", new Opcode(IAND, OpcodeGroup.INSN));
0257: OPCODES.put("LAND", new Opcode(LAND, OpcodeGroup.INSN));
0258: OPCODES.put("IOR", new Opcode(IOR, OpcodeGroup.INSN));
0259: OPCODES.put("LOR", new Opcode(LOR, OpcodeGroup.INSN));
0260: OPCODES.put("IXOR", new Opcode(IXOR, OpcodeGroup.INSN));
0261: OPCODES.put("LXOR", new Opcode(LXOR, OpcodeGroup.INSN));
0262: OPCODES.put("IINC", new Opcode(IINC, OpcodeGroup.INSN_IINC));
0263: OPCODES.put("I2L", new Opcode(I2L, OpcodeGroup.INSN));
0264: OPCODES.put("I2F", new Opcode(I2F, OpcodeGroup.INSN));
0265: OPCODES.put("I2D", new Opcode(I2D, OpcodeGroup.INSN));
0266: OPCODES.put("L2I", new Opcode(L2I, OpcodeGroup.INSN));
0267: OPCODES.put("L2F", new Opcode(L2F, OpcodeGroup.INSN));
0268: OPCODES.put("L2D", new Opcode(L2D, OpcodeGroup.INSN));
0269: OPCODES.put("F2I", new Opcode(F2I, OpcodeGroup.INSN));
0270: OPCODES.put("F2L", new Opcode(F2L, OpcodeGroup.INSN));
0271: OPCODES.put("F2D", new Opcode(F2D, OpcodeGroup.INSN));
0272: OPCODES.put("D2I", new Opcode(D2I, OpcodeGroup.INSN));
0273: OPCODES.put("D2L", new Opcode(D2L, OpcodeGroup.INSN));
0274: OPCODES.put("D2F", new Opcode(D2F, OpcodeGroup.INSN));
0275: OPCODES.put("I2B", new Opcode(I2B, OpcodeGroup.INSN));
0276: OPCODES.put("I2C", new Opcode(I2C, OpcodeGroup.INSN));
0277: OPCODES.put("I2S", new Opcode(I2S, OpcodeGroup.INSN));
0278: OPCODES.put("LCMP", new Opcode(LCMP, OpcodeGroup.INSN));
0279: OPCODES.put("FCMPL", new Opcode(FCMPL, OpcodeGroup.INSN));
0280: OPCODES.put("FCMPG", new Opcode(FCMPG, OpcodeGroup.INSN));
0281: OPCODES.put("DCMPL", new Opcode(DCMPL, OpcodeGroup.INSN));
0282: OPCODES.put("DCMPG", new Opcode(DCMPG, OpcodeGroup.INSN));
0283: OPCODES.put("IFEQ", new Opcode(IFEQ, OpcodeGroup.INSN_JUMP));
0284: OPCODES.put("IFNE", new Opcode(IFNE, OpcodeGroup.INSN_JUMP));
0285: OPCODES.put("IFLT", new Opcode(IFLT, OpcodeGroup.INSN_JUMP));
0286: OPCODES.put("IFGE", new Opcode(IFGE, OpcodeGroup.INSN_JUMP));
0287: OPCODES.put("IFGT", new Opcode(IFGT, OpcodeGroup.INSN_JUMP));
0288: OPCODES.put("IFLE", new Opcode(IFLE, OpcodeGroup.INSN_JUMP));
0289: OPCODES.put("IF_ICMPEQ", new Opcode(IF_ICMPEQ,
0290: OpcodeGroup.INSN_JUMP));
0291: OPCODES.put("IF_ICMPNE", new Opcode(IF_ICMPNE,
0292: OpcodeGroup.INSN_JUMP));
0293: OPCODES.put("IF_ICMPLT", new Opcode(IF_ICMPLT,
0294: OpcodeGroup.INSN_JUMP));
0295: OPCODES.put("IF_ICMPGE", new Opcode(IF_ICMPGE,
0296: OpcodeGroup.INSN_JUMP));
0297: OPCODES.put("IF_ICMPGT", new Opcode(IF_ICMPGT,
0298: OpcodeGroup.INSN_JUMP));
0299: OPCODES.put("IF_ICMPLE", new Opcode(IF_ICMPLE,
0300: OpcodeGroup.INSN_JUMP));
0301: OPCODES.put("IF_ACMPEQ", new Opcode(IF_ACMPEQ,
0302: OpcodeGroup.INSN_JUMP));
0303: OPCODES.put("IF_ACMPNE", new Opcode(IF_ACMPNE,
0304: OpcodeGroup.INSN_JUMP));
0305: OPCODES.put("GOTO", new Opcode(GOTO, OpcodeGroup.INSN_JUMP));
0306: OPCODES.put("JSR", new Opcode(JSR, OpcodeGroup.INSN_JUMP));
0307: OPCODES.put("RET", new Opcode(RET, OpcodeGroup.INSN_VAR));
0308: OPCODES.put("IRETURN", new Opcode(IRETURN, OpcodeGroup.INSN));
0309: OPCODES.put("LRETURN", new Opcode(LRETURN, OpcodeGroup.INSN));
0310: OPCODES.put("FRETURN", new Opcode(FRETURN, OpcodeGroup.INSN));
0311: OPCODES.put("DRETURN", new Opcode(DRETURN, OpcodeGroup.INSN));
0312: OPCODES.put("ARETURN", new Opcode(ARETURN, OpcodeGroup.INSN));
0313: OPCODES.put("RETURN", new Opcode(RETURN, OpcodeGroup.INSN));
0314: OPCODES.put("GETSTATIC", new Opcode(GETSTATIC,
0315: OpcodeGroup.INSN_FIELD));
0316: OPCODES.put("PUTSTATIC", new Opcode(PUTSTATIC,
0317: OpcodeGroup.INSN_FIELD));
0318: OPCODES.put("GETFIELD", new Opcode(GETFIELD,
0319: OpcodeGroup.INSN_FIELD));
0320: OPCODES.put("PUTFIELD", new Opcode(PUTFIELD,
0321: OpcodeGroup.INSN_FIELD));
0322: OPCODES.put("INVOKEVIRTUAL", new Opcode(INVOKEVIRTUAL,
0323: OpcodeGroup.INSN_METHOD));
0324: OPCODES.put("INVOKESPECIAL", new Opcode(INVOKESPECIAL,
0325: OpcodeGroup.INSN_METHOD));
0326: OPCODES.put("INVOKESTATIC", new Opcode(INVOKESTATIC,
0327: OpcodeGroup.INSN_METHOD));
0328: OPCODES.put("INVOKEINTERFACE", new Opcode(INVOKEINTERFACE,
0329: OpcodeGroup.INSN_METHOD));
0330: OPCODES.put("NEW", new Opcode(NEW, OpcodeGroup.INSN_TYPE));
0331: OPCODES.put("NEWARRAY", new Opcode(NEWARRAY,
0332: OpcodeGroup.INSN_INT));
0333: OPCODES.put("ANEWARRAY", new Opcode(ANEWARRAY,
0334: OpcodeGroup.INSN_TYPE));
0335: OPCODES.put("ARRAYLENGTH", new Opcode(ARRAYLENGTH,
0336: OpcodeGroup.INSN));
0337: OPCODES.put("ATHROW", new Opcode(ATHROW, OpcodeGroup.INSN));
0338: OPCODES.put("CHECKCAST", new Opcode(CHECKCAST,
0339: OpcodeGroup.INSN_TYPE));
0340: OPCODES.put("INSTANCEOF", new Opcode(INSTANCEOF,
0341: OpcodeGroup.INSN_TYPE));
0342: OPCODES.put("MONITORENTER", new Opcode(MONITORENTER,
0343: OpcodeGroup.INSN));
0344: OPCODES.put("MONITOREXIT", new Opcode(MONITOREXIT,
0345: OpcodeGroup.INSN));
0346: OPCODES.put("MULTIANEWARRAY", new Opcode(MULTIANEWARRAY,
0347: OpcodeGroup.INSN_MULTIANEWARRAY));
0348: OPCODES
0349: .put("IFNULL",
0350: new Opcode(IFNULL, OpcodeGroup.INSN_JUMP));
0351: OPCODES.put("IFNONNULL", new Opcode(IFNONNULL,
0352: OpcodeGroup.INSN_JUMP));
0353: }
0354:
0355: private static final HashMap TYPES = new HashMap();
0356: static {
0357: String[] types = SAXCodeAdapter.TYPES;
0358: for (int i = 0; i < types.length; i++) {
0359: TYPES.put(types[i], new Integer(i));
0360: }
0361: }
0362:
0363: /**
0364: * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
0365: *
0366: * @param os output stream to write generated class.
0367: * @param computeMax <tt>true</tt> if the maximum stack size and the
0368: * maximum number of local variables must be automatically computed.
0369: * This value is passed to {@link ClassWriter ClassWriter} instance.
0370: */
0371: public ASMContentHandler(final OutputStream os,
0372: final boolean computeMax) {
0373: this .os = os;
0374: this .computeMax = computeMax;
0375: }
0376:
0377: /**
0378: * Returns the bytecode of the class that was build with underneath class
0379: * writer.
0380: *
0381: * @return the bytecode of the class that was build with underneath class
0382: * writer or null if there are no classwriter created.
0383: */
0384: public byte[] toByteArray() {
0385: return cw == null ? null : cw.toByteArray();
0386: }
0387:
0388: /**
0389: * Process notification of the start of an XML element being reached.
0390: *
0391: * @param ns - The Namespace URI, or the empty string if the element has no
0392: * Namespace URI or if Namespace processing is not being performed.
0393: * @param lName - The local name (without prefix), or the empty string if
0394: * Namespace processing is not being performed.
0395: * @param qName - The qualified name (with prefix), or the empty string if
0396: * qualified names are not available.
0397: * @param list - The attributes attached to the element. If there are no
0398: * attributes, it shall be an empty Attributes object.
0399: * @exception SAXException if a parsing error is to be reported
0400: */
0401: public final void startElement(final String ns, final String lName,
0402: final String qName, final Attributes list)
0403: throws SAXException {
0404: // the actual element name is either in lName or qName, depending
0405: // on whether the parser is namespace aware
0406: String name = lName == null || lName.length() == 0 ? qName
0407: : lName;
0408:
0409: // Compute the current matching rule
0410: StringBuffer sb = new StringBuffer(match);
0411: if (match.length() > 0) {
0412: sb.append('/');
0413: }
0414: sb.append(name);
0415: match = sb.toString();
0416:
0417: // Fire "begin" events for all relevant rules
0418: Rule r = (Rule) RULES.match(match);
0419: if (r != null) {
0420: r.begin(name, list);
0421: }
0422: }
0423:
0424: /**
0425: * Process notification of the end of an XML element being reached.
0426: *
0427: * @param ns - The Namespace URI, or the empty string if the element has no
0428: * Namespace URI or if Namespace processing is not being performed.
0429: * @param lName - The local name (without prefix), or the empty string if
0430: * Namespace processing is not being performed.
0431: * @param qName - The qualified XML 1.0 name (with prefix), or the empty
0432: * string if qualified names are not available.
0433: *
0434: * @exception SAXException if a parsing error is to be reported
0435: */
0436: public final void endElement(final String ns, final String lName,
0437: final String qName) throws SAXException {
0438: // the actual element name is either in lName or qName, depending
0439: // on whether the parser is namespace aware
0440: String name = lName == null || lName.length() == 0 ? qName
0441: : lName;
0442:
0443: // Fire "end" events for all relevant rules in reverse order
0444: Rule r = (Rule) RULES.match(match);
0445: if (r != null) {
0446: r.end(name);
0447: }
0448:
0449: // Recover the previous match expression
0450: int slash = match.lastIndexOf('/');
0451: if (slash >= 0) {
0452: match = match.substring(0, slash);
0453: } else {
0454: match = "";
0455: }
0456: }
0457:
0458: /**
0459: * Process notification of the end of a document and write generated
0460: * bytecode into output stream.
0461: *
0462: * @exception SAXException if parsing or writing error is to be reported.
0463: */
0464: public final void endDocument() throws SAXException {
0465: try {
0466: os.write(toByteArray());
0467: } catch (IOException ex) {
0468: throw new SAXException(ex.toString(), ex);
0469: }
0470: }
0471:
0472: /**
0473: * Return the top object on the stack without removing it. If there are no
0474: * objects on the stack, return <code>null</code>.
0475: *
0476: * @return the top object on the stack without removing it.
0477: */
0478: final Object peek() {
0479: return stack.size() == 0 ? null : stack.get(stack.size() - 1);
0480: }
0481:
0482: /**
0483: * Pop the top object off of the stack, and return it. If there are no
0484: * objects on the stack, return <code>null</code>.
0485: *
0486: * @return the top object off of the stack.
0487: */
0488: final Object pop() {
0489: return stack.size() == 0 ? null : stack
0490: .remove(stack.size() - 1);
0491: }
0492:
0493: /**
0494: * Push a new object onto the top of the object stack.
0495: *
0496: * @param object The new object
0497: */
0498: final void push(final Object object) {
0499: stack.add(object);
0500: }
0501:
0502: private static final class RuleSet {
0503:
0504: private final HashMap rules = new HashMap();
0505:
0506: private final List lpatterns = new ArrayList();
0507:
0508: private final List rpatterns = new ArrayList();
0509:
0510: public void add(final String path, final Object rule) {
0511: String pattern = path;
0512: if (path.startsWith("*/")) {
0513: pattern = path.substring(1);
0514: lpatterns.add(pattern);
0515: } else if (path.endsWith("/*")) {
0516: pattern = path.substring(0, path.length() - 1);
0517: rpatterns.add(pattern);
0518: }
0519: rules.put(pattern, rule);
0520: }
0521:
0522: public Object match(final String path) {
0523: if (rules.containsKey(path)) {
0524: return rules.get(path);
0525: }
0526:
0527: int n = path.lastIndexOf('/');
0528: for (Iterator it = lpatterns.iterator(); it.hasNext();) {
0529: String pattern = (String) it.next();
0530: if (path.substring(n).endsWith(pattern)) {
0531: return rules.get(pattern);
0532: }
0533: }
0534:
0535: for (Iterator it = rpatterns.iterator(); it.hasNext();) {
0536: String pattern = (String) it.next();
0537: if (path.startsWith(pattern)) {
0538: return rules.get(pattern);
0539: }
0540: }
0541:
0542: return null;
0543: }
0544: }
0545:
0546: /**
0547: * Rule
0548: */
0549: protected abstract class Rule {
0550:
0551: public void begin(final String name, final Attributes attrs)
0552: throws SAXException {
0553: }
0554:
0555: public void end(final String name) {
0556: }
0557:
0558: protected final Object getValue(final String desc,
0559: final String val) throws SAXException {
0560: Object value = null;
0561: if (val != null) {
0562: if (desc.equals("Ljava/lang/String;")) {
0563: value = decode(val);
0564: } else if ("Ljava/lang/Integer;".equals(desc)
0565: || "I".equals(desc) || "S".equals(desc)
0566: || "B".equals(desc) || "C".equals(desc)
0567: || desc.equals("Z")) {
0568: value = new Integer(val);
0569:
0570: } else if ("Ljava/lang/Short;".equals(desc)) {
0571: value = new Short(val);
0572:
0573: } else if ("Ljava/lang/Byte;".equals(desc)) {
0574: value = new Byte(val);
0575:
0576: } else if ("Ljava/lang/Character;".equals(desc)) {
0577: value = new Character(decode(val).charAt(0));
0578:
0579: } else if ("Ljava/lang/Boolean;".equals(desc)) {
0580: value = Boolean.valueOf(val);
0581:
0582: // } else if ("Ljava/lang/Integer;".equals(desc)
0583: // || desc.equals("I"))
0584: // {
0585: // value = new Integer(val);
0586: // } else if ("Ljava/lang/Character;".equals(desc)
0587: // || desc.equals("C"))
0588: // {
0589: // value = new Character(decode(val).charAt(0));
0590: // } else if ("Ljava/lang/Short;".equals(desc) ||
0591: // desc.equals("S"))
0592: // {
0593: // value = Short.valueOf(val);
0594: // } else if ("Ljava/lang/Byte;".equals(desc) ||
0595: // desc.equals("B"))
0596: // {
0597: // value = Byte.valueOf(val);
0598:
0599: } else if ("Ljava/lang/Long;".equals(desc)
0600: || desc.equals("J")) {
0601: value = new Long(val);
0602: } else if ("Ljava/lang/Float;".equals(desc)
0603: || desc.equals("F")) {
0604: value = new Float(val);
0605: } else if ("Ljava/lang/Double;".equals(desc)
0606: || desc.equals("D")) {
0607: value = new Double(val);
0608: } else if (Type.getDescriptor(Type.class).equals(desc)) {
0609: value = Type.getType(val);
0610:
0611: // } else if ("[I".equals(desc)) {
0612: // value = new int[0]; // TODO
0613: // } else if ("[C".equals(desc)) {
0614: // value = new char[0]; // TODO
0615: // } else if ("[Z".equals(desc)) {
0616: // value = new boolean[0]; // TODO
0617: // } else if ("[S".equals(desc)) {
0618: // value = new short[0]; // TODO
0619: // } else if ("[B".equals(desc)) {
0620: // value = new byte[0]; // TODO
0621: // } else if ("[J".equals(desc)) {
0622: // value = new long[0]; // TODO
0623: // } else if ("[F".equals(desc)) {
0624: // value = new float[0]; // TODO
0625: // } else if ("[D".equals(desc)) {
0626: // value = new double[0]; // TODO
0627:
0628: } else {
0629: throw new SAXException("Invalid value:" + val
0630: + " desc:" + desc + " ctx:" + this );
0631: }
0632: }
0633: return value;
0634: }
0635:
0636: private final String decode(final String val)
0637: throws SAXException {
0638: StringBuffer sb = new StringBuffer(val.length());
0639: try {
0640: int n = 0;
0641: while (n < val.length()) {
0642: char c = val.charAt(n);
0643: if (c == '\\') {
0644: n++;
0645: c = val.charAt(n);
0646: if (c == '\\') {
0647: sb.append('\\');
0648: } else {
0649: n++; // skip 'u'
0650: sb.append((char) Integer.parseInt(val
0651: .substring(n, n + 4), 16));
0652: n += 3;
0653: }
0654: } else {
0655: sb.append(c);
0656: }
0657: n++;
0658: }
0659:
0660: } catch (RuntimeException ex) {
0661: throw new SAXException(ex);
0662: }
0663: return sb.toString();
0664: }
0665:
0666: protected final Label getLabel(final Object label) {
0667: Label lbl = (Label) labels.get(label);
0668: if (lbl == null) {
0669: lbl = new Label();
0670: labels.put(label, lbl);
0671: }
0672: return lbl;
0673: }
0674:
0675: // TODO verify move to stack
0676: protected final MethodVisitor getCodeVisitor() {
0677: return (MethodVisitor) peek();
0678: }
0679:
0680: protected final int getAccess(final String s) {
0681: int access = 0;
0682: if (s.indexOf("public") != -1) {
0683: access |= Opcodes.ACC_PUBLIC;
0684: }
0685: if (s.indexOf("private") != -1) {
0686: access |= Opcodes.ACC_PRIVATE;
0687: }
0688: if (s.indexOf("protected") != -1) {
0689: access |= Opcodes.ACC_PROTECTED;
0690: }
0691: if (s.indexOf("static") != -1) {
0692: access |= Opcodes.ACC_STATIC;
0693: }
0694: if (s.indexOf("final") != -1) {
0695: access |= Opcodes.ACC_FINAL;
0696: }
0697: if (s.indexOf("super") != -1) {
0698: access |= Opcodes.ACC_SUPER;
0699: }
0700: if (s.indexOf("synchronized") != -1) {
0701: access |= Opcodes.ACC_SYNCHRONIZED;
0702: }
0703: if (s.indexOf("volatile") != -1) {
0704: access |= Opcodes.ACC_VOLATILE;
0705: }
0706: if (s.indexOf("bridge") != -1) {
0707: access |= Opcodes.ACC_BRIDGE;
0708: }
0709: if (s.indexOf("varargs") != -1) {
0710: access |= Opcodes.ACC_VARARGS;
0711: }
0712: if (s.indexOf("transient") != -1) {
0713: access |= Opcodes.ACC_TRANSIENT;
0714: }
0715: if (s.indexOf("native") != -1) {
0716: access |= Opcodes.ACC_NATIVE;
0717: }
0718: if (s.indexOf("interface") != -1) {
0719: access |= Opcodes.ACC_INTERFACE;
0720: }
0721: if (s.indexOf("abstract") != -1) {
0722: access |= Opcodes.ACC_ABSTRACT;
0723: }
0724: if (s.indexOf("strict") != -1) {
0725: access |= Opcodes.ACC_STRICT;
0726: }
0727: if (s.indexOf("synthetic") != -1) {
0728: access |= Opcodes.ACC_SYNTHETIC;
0729: }
0730: if (s.indexOf("annotation") != -1) {
0731: access |= Opcodes.ACC_ANNOTATION;
0732: }
0733: if (s.indexOf("enum") != -1) {
0734: access |= Opcodes.ACC_ENUM;
0735: }
0736: if (s.indexOf("deprecated") != -1) {
0737: access |= Opcodes.ACC_DEPRECATED;
0738: }
0739: return access;
0740: }
0741: }
0742:
0743: /**
0744: * ClassRule
0745: */
0746: private final class ClassRule extends Rule {
0747:
0748: public final void begin(final String name,
0749: final Attributes attrs) {
0750: int major = Integer.parseInt(attrs.getValue("major"));
0751: int minor = Integer.parseInt(attrs.getValue("minor"));
0752: cw = new ClassWriter(computeMax ? ClassWriter.COMPUTE_MAXS
0753: : 0);
0754: HashMap vals = new HashMap();
0755: vals.put("version", new Integer(minor << 16 | major));
0756: vals.put("access", attrs.getValue("access"));
0757: vals.put("name", attrs.getValue("name"));
0758: vals.put("parent", attrs.getValue("parent"));
0759: vals.put("source", attrs.getValue("source"));
0760: vals.put("signature", attrs.getValue("signature"));
0761: vals.put("interfaces", new ArrayList());
0762: push(vals);
0763: // values will be extracted in InterfacesRule.end();
0764: }
0765: }
0766:
0767: private final class SourceRule extends Rule {
0768:
0769: public void begin(final String name, final Attributes attrs) {
0770: String file = attrs.getValue("file");
0771: String debug = attrs.getValue("debug");
0772: cw.visitSource(file, debug);
0773: }
0774: }
0775:
0776: /**
0777: * InterfaceRule
0778: */
0779: private final class InterfaceRule extends Rule {
0780:
0781: public final void begin(final String name,
0782: final Attributes attrs) {
0783: ((List) ((HashMap) peek()).get("interfaces")).add(attrs
0784: .getValue("name"));
0785: }
0786: }
0787:
0788: /**
0789: * InterfacesRule
0790: */
0791: private final class InterfacesRule extends Rule {
0792:
0793: public final void end(final String element) {
0794: HashMap vals = (HashMap) pop();
0795: int version = ((Integer) vals.get("version")).intValue();
0796: int access = getAccess((String) vals.get("access"));
0797: String name = (String) vals.get("name");
0798: String signature = (String) vals.get("signature");
0799: String parent = (String) vals.get("parent");
0800: List infs = (List) vals.get("interfaces");
0801: String[] interfaces = (String[]) infs
0802: .toArray(new String[infs.size()]);
0803: cw.visit(version, access, name, signature, parent,
0804: interfaces);
0805: push(cw);
0806: }
0807: }
0808:
0809: /**
0810: * OuterClassRule
0811: */
0812: private final class OuterClassRule extends Rule {
0813:
0814: public final void begin(final String element,
0815: final Attributes attrs) {
0816: String owner = attrs.getValue("owner");
0817: String name = attrs.getValue("name");
0818: String desc = attrs.getValue("desc");
0819: cw.visitOuterClass(owner, name, desc);
0820: }
0821: }
0822:
0823: /**
0824: * InnerClassRule
0825: */
0826: private final class InnerClassRule extends Rule {
0827:
0828: public final void begin(final String element,
0829: final Attributes attrs) {
0830: int access = getAccess(attrs.getValue("access"));
0831: String name = attrs.getValue("name");
0832: String outerName = attrs.getValue("outerName");
0833: String innerName = attrs.getValue("innerName");
0834: cw.visitInnerClass(name, outerName, innerName, access);
0835: }
0836: }
0837:
0838: /**
0839: * FieldRule
0840: */
0841: private final class FieldRule extends Rule {
0842:
0843: public final void begin(final String element,
0844: final Attributes attrs) throws SAXException {
0845: int access = getAccess(attrs.getValue("access"));
0846: String name = attrs.getValue("name");
0847: String signature = attrs.getValue("signature");
0848: String desc = attrs.getValue("desc");
0849: Object value = getValue(desc, attrs.getValue("value"));
0850: push(cw.visitField(access, name, desc, signature, value));
0851: }
0852:
0853: public void end(final String name) {
0854: ((FieldVisitor) pop()).visitEnd();
0855: }
0856: }
0857:
0858: /**
0859: * MethodRule
0860: */
0861: private final class MethodRule extends Rule {
0862:
0863: public final void begin(final String name,
0864: final Attributes attrs) {
0865: labels = new HashMap();
0866: HashMap vals = new HashMap();
0867: vals.put("access", attrs.getValue("access"));
0868: vals.put("name", attrs.getValue("name"));
0869: vals.put("desc", attrs.getValue("desc"));
0870: vals.put("signature", attrs.getValue("signature"));
0871: vals.put("exceptions", new ArrayList());
0872: push(vals);
0873: // values will be extracted in ExceptionsRule.end();
0874: }
0875:
0876: public final void end(final String name) {
0877: ((MethodVisitor) pop()).visitEnd();
0878: labels = null;
0879: }
0880: }
0881:
0882: /**
0883: * ExceptionRule
0884: */
0885: private final class ExceptionRule extends Rule {
0886:
0887: public final void begin(final String name,
0888: final Attributes attrs) {
0889: ((List) ((HashMap) peek()).get("exceptions")).add(attrs
0890: .getValue("name"));
0891: }
0892: }
0893:
0894: /**
0895: * ExceptionsRule
0896: */
0897: private final class ExceptionsRule extends Rule {
0898:
0899: public final void end(final String element) {
0900: HashMap vals = (HashMap) pop();
0901: int access = getAccess((String) vals.get("access"));
0902: String name = (String) vals.get("name");
0903: String desc = (String) vals.get("desc");
0904: String signature = (String) vals.get("signature");
0905: List excs = (List) vals.get("exceptions");
0906: String[] exceptions = (String[]) excs
0907: .toArray(new String[excs.size()]);
0908:
0909: push(cw.visitMethod(access, name, desc, signature,
0910: exceptions));
0911: }
0912: }
0913:
0914: /**
0915: * TableSwitchRule
0916: */
0917: private class TableSwitchRule extends Rule {
0918:
0919: public final void begin(final String name,
0920: final Attributes attrs) {
0921: HashMap vals = new HashMap();
0922: vals.put("min", attrs.getValue("min"));
0923: vals.put("max", attrs.getValue("max"));
0924: vals.put("dflt", attrs.getValue("dflt"));
0925: vals.put("labels", new ArrayList());
0926: push(vals);
0927: }
0928:
0929: public final void end(final String name) {
0930: HashMap vals = (HashMap) pop();
0931: int min = Integer.parseInt((String) vals.get("min"));
0932: int max = Integer.parseInt((String) vals.get("max"));
0933: Label dflt = getLabel(vals.get("dflt"));
0934: List lbls = (List) vals.get("labels");
0935: Label[] labels = (Label[]) lbls.toArray(new Label[lbls
0936: .size()]);
0937: getCodeVisitor().visitTableSwitchInsn(min, max, dflt,
0938: labels);
0939: }
0940: }
0941:
0942: /**
0943: * TableSwitchLabelRule
0944: */
0945: private final class TableSwitchLabelRule extends Rule {
0946:
0947: public final void begin(final String name,
0948: final Attributes attrs) {
0949: ((List) ((HashMap) peek()).get("labels"))
0950: .add(getLabel(attrs.getValue("name")));
0951: }
0952: }
0953:
0954: /**
0955: * LookupSwitchRule
0956: */
0957: private final class LookupSwitchRule extends Rule {
0958:
0959: public final void begin(final String name,
0960: final Attributes attrs) {
0961: HashMap vals = new HashMap();
0962: vals.put("dflt", attrs.getValue("dflt"));
0963: vals.put("labels", new ArrayList());
0964: vals.put("keys", new ArrayList());
0965: push(vals);
0966: }
0967:
0968: public final void end(final String name) {
0969: HashMap vals = (HashMap) pop();
0970: Label dflt = getLabel(vals.get("dflt"));
0971: List keyList = (List) vals.get("keys");
0972: List lbls = (List) vals.get("labels");
0973: Label[] labels = (Label[]) lbls.toArray(new Label[lbls
0974: .size()]);
0975: int[] keys = new int[keyList.size()];
0976: for (int i = 0; i < keys.length; i++) {
0977: keys[i] = Integer.parseInt((String) keyList.get(i));
0978: }
0979: getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
0980: }
0981: }
0982:
0983: /**
0984: * LookupSwitchLabelRule
0985: */
0986: private final class LookupSwitchLabelRule extends Rule {
0987:
0988: public final void begin(final String name,
0989: final Attributes attrs) {
0990: HashMap vals = (HashMap) peek();
0991: ((List) vals.get("labels")).add(getLabel(attrs
0992: .getValue("name")));
0993: ((List) vals.get("keys")).add(attrs.getValue("key"));
0994: }
0995: }
0996:
0997: /**
0998: * FrameRule
0999: */
1000: private final class FrameRule extends Rule {
1001:
1002: public void begin(final String name, final Attributes attrs) {
1003: HashMap typeLists = new HashMap();
1004: typeLists.put("local", new ArrayList());
1005: typeLists.put("stack", new ArrayList());
1006: push(attrs.getValue("type"));
1007: push(attrs.getValue("count") == null ? "0" : attrs
1008: .getValue("count"));
1009: push(typeLists);
1010: }
1011:
1012: public void end(final String name) {
1013: HashMap typeLists = (HashMap) pop();
1014: List locals = (List) typeLists.get("local");
1015: int nLocal = locals.size();
1016: Object[] local = locals.toArray();
1017: List stacks = (List) typeLists.get("stack");
1018: int nStack = stacks.size();
1019: Object[] stack = stacks.toArray();
1020: String count = (String) pop();
1021: String type = (String) pop();
1022: if (type.equals("NEW")) {
1023: getCodeVisitor().visitFrame(Opcodes.F_NEW, nLocal,
1024: local, nStack, stack);
1025: } else if (type.equals("FULL")) {
1026: getCodeVisitor().visitFrame(Opcodes.F_FULL, nLocal,
1027: local, nStack, stack);
1028: } else if (type.equals("APPEND")) {
1029: getCodeVisitor().visitFrame(Opcodes.F_APPEND, nLocal,
1030: local, 0, null);
1031: } else if (type.equals("CHOP")) {
1032: getCodeVisitor().visitFrame(Opcodes.F_CHOP,
1033: Integer.parseInt(count), null, 0, null);
1034: } else if (type.equals("SAME")) {
1035: getCodeVisitor().visitFrame(Opcodes.F_SAME, 0, null, 0,
1036: null);
1037: } else if (type.equals("SAME1")) {
1038: getCodeVisitor().visitFrame(Opcodes.F_SAME1, 0, null,
1039: nStack, stack);
1040: }
1041: }
1042: }
1043:
1044: private final class FrameTypeRule extends Rule {
1045:
1046: public void begin(final String name, final Attributes attrs) {
1047: List types = (List) ((HashMap) peek()).get(name);
1048: String type = attrs.getValue("type");
1049: if ("uninitialized".equals(type)) {
1050: types.add(getLabel(attrs.getValue("label")));
1051: } else {
1052: Integer t = (Integer) TYPES.get(type);
1053: if (t == null) {
1054: types.add(type);
1055: } else {
1056: types.add(t);
1057: }
1058: }
1059: }
1060: }
1061:
1062: /**
1063: * LabelRule
1064: */
1065: private final class LabelRule extends Rule {
1066:
1067: public final void begin(final String name,
1068: final Attributes attrs) {
1069: getCodeVisitor().visitLabel(
1070: getLabel(attrs.getValue("name")));
1071: }
1072: }
1073:
1074: /**
1075: * TryCatchRule
1076: */
1077: private final class TryCatchRule extends Rule {
1078:
1079: public final void begin(final String name,
1080: final Attributes attrs) {
1081: Label start = getLabel(attrs.getValue("start"));
1082: Label end = getLabel(attrs.getValue("end"));
1083: Label handler = getLabel(attrs.getValue("handler"));
1084: String type = attrs.getValue("type");
1085: getCodeVisitor().visitTryCatchBlock(start, end, handler,
1086: type);
1087: }
1088: }
1089:
1090: /**
1091: * LineNumberRule
1092: */
1093: private final class LineNumberRule extends Rule {
1094:
1095: public final void begin(final String name,
1096: final Attributes attrs) {
1097: int line = Integer.parseInt(attrs.getValue("line"));
1098: Label start = getLabel(attrs.getValue("start"));
1099: getCodeVisitor().visitLineNumber(line, start);
1100: }
1101: }
1102:
1103: /**
1104: * LocalVarRule
1105: */
1106: private final class LocalVarRule extends Rule {
1107:
1108: public final void begin(final String element,
1109: final Attributes attrs) {
1110: String name = attrs.getValue("name");
1111: String desc = attrs.getValue("desc");
1112: String signature = attrs.getValue("signature");
1113: Label start = getLabel(attrs.getValue("start"));
1114: Label end = getLabel(attrs.getValue("end"));
1115: int var = Integer.parseInt(attrs.getValue("var"));
1116: getCodeVisitor().visitLocalVariable(name, desc, signature,
1117: start, end, var);
1118: }
1119: }
1120:
1121: /**
1122: * OpcodesRule
1123: */
1124: private final class OpcodesRule extends Rule {
1125:
1126: // public boolean match( String match, String element) {
1127: // return match.startsWith( path) && OPCODES.containsKey( element);
1128: // }
1129:
1130: public final void begin(final String element,
1131: final Attributes attrs) throws SAXException {
1132: Opcode o = (Opcode) OPCODES.get(element);
1133: if (o == null) {
1134: throw new SAXException("Invalid element: " + element
1135: + " at " + match);
1136: }
1137:
1138: switch (o.type) {
1139: case OpcodeGroup.INSN:
1140: getCodeVisitor().visitInsn(o.opcode);
1141: break;
1142:
1143: case OpcodeGroup.INSN_FIELD:
1144: getCodeVisitor().visitFieldInsn(o.opcode,
1145: attrs.getValue("owner"),
1146: attrs.getValue("name"), attrs.getValue("desc"));
1147: break;
1148:
1149: case OpcodeGroup.INSN_INT:
1150: getCodeVisitor().visitIntInsn(o.opcode,
1151: Integer.parseInt(attrs.getValue("value")));
1152: break;
1153:
1154: case OpcodeGroup.INSN_JUMP:
1155: getCodeVisitor().visitJumpInsn(o.opcode,
1156: getLabel(attrs.getValue("label")));
1157: break;
1158:
1159: case OpcodeGroup.INSN_METHOD:
1160: getCodeVisitor().visitMethodInsn(o.opcode,
1161: attrs.getValue("owner"),
1162: attrs.getValue("name"), attrs.getValue("desc"));
1163: break;
1164:
1165: case OpcodeGroup.INSN_TYPE:
1166: getCodeVisitor().visitTypeInsn(o.opcode,
1167: attrs.getValue("desc"));
1168: break;
1169:
1170: case OpcodeGroup.INSN_VAR:
1171: getCodeVisitor().visitVarInsn(o.opcode,
1172: Integer.parseInt(attrs.getValue("var")));
1173: break;
1174:
1175: case OpcodeGroup.INSN_IINC:
1176: getCodeVisitor().visitIincInsn(
1177: Integer.parseInt(attrs.getValue("var")),
1178: Integer.parseInt(attrs.getValue("inc")));
1179: break;
1180:
1181: case OpcodeGroup.INSN_LDC:
1182: getCodeVisitor().visitLdcInsn(
1183: getValue(attrs.getValue("desc"), attrs
1184: .getValue("cst")));
1185: break;
1186:
1187: case OpcodeGroup.INSN_MULTIANEWARRAY:
1188: getCodeVisitor().visitMultiANewArrayInsn(
1189: attrs.getValue("desc"),
1190: Integer.parseInt(attrs.getValue("dims")));
1191: break;
1192:
1193: default:
1194: throw new Error("Internal error");
1195:
1196: }
1197: }
1198: }
1199:
1200: /**
1201: * MaxRule
1202: */
1203: private final class MaxRule extends Rule {
1204:
1205: public final void begin(final String element,
1206: final Attributes attrs) {
1207: int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
1208: int maxLocals = Integer.parseInt(attrs
1209: .getValue("maxLocals"));
1210: getCodeVisitor().visitMaxs(maxStack, maxLocals);
1211: }
1212: }
1213:
1214: private final class AnnotationRule extends Rule {
1215:
1216: public void begin(final String name, final Attributes attrs) {
1217: String desc = attrs.getValue("desc");
1218: boolean visible = Boolean
1219: .valueOf(attrs.getValue("visible")).booleanValue();
1220:
1221: Object v = peek();
1222: if (v instanceof ClassVisitor) {
1223: push(((ClassVisitor) v).visitAnnotation(desc, visible));
1224: } else if (v instanceof FieldVisitor) {
1225: push(((FieldVisitor) v).visitAnnotation(desc, visible));
1226: } else if (v instanceof MethodVisitor) {
1227: push(((MethodVisitor) v).visitAnnotation(desc, visible));
1228: }
1229: }
1230:
1231: public void end(final String name) {
1232: AnnotationVisitor av = (AnnotationVisitor) pop();
1233: if (av != null) {
1234: av.visitEnd();
1235: }
1236: }
1237: }
1238:
1239: private final class AnnotationParameterRule extends Rule {
1240:
1241: public void begin(final String name, final Attributes attrs) {
1242: int parameter = Integer.parseInt(attrs
1243: .getValue("parameter"));
1244: String desc = attrs.getValue("desc");
1245: boolean visible = Boolean
1246: .valueOf(attrs.getValue("visible")).booleanValue();
1247:
1248: push(((MethodVisitor) peek()).visitParameterAnnotation(
1249: parameter, desc, visible));
1250: }
1251:
1252: public void end(final String name) {
1253: AnnotationVisitor av = (AnnotationVisitor) pop();
1254: if (av != null) {
1255: av.visitEnd();
1256: }
1257: }
1258: }
1259:
1260: private final class AnnotationValueRule extends Rule {
1261:
1262: public void begin(final String nm, final Attributes attrs)
1263: throws SAXException {
1264: AnnotationVisitor av = (AnnotationVisitor) peek();
1265: if (av != null) {
1266: av.visit(attrs.getValue("name"), getValue(attrs
1267: .getValue("desc"), attrs.getValue("value")));
1268: }
1269: }
1270: }
1271:
1272: private final class AnnotationValueEnumRule extends Rule {
1273:
1274: public void begin(final String nm, final Attributes attrs) {
1275: AnnotationVisitor av = (AnnotationVisitor) peek();
1276: if (av != null) {
1277: av.visitEnum(attrs.getValue("name"), attrs
1278: .getValue("desc"), attrs.getValue("value"));
1279: }
1280: }
1281: }
1282:
1283: private final class AnnotationValueAnnotationRule extends Rule {
1284:
1285: public void begin(final String nm, final Attributes attrs) {
1286: AnnotationVisitor av = (AnnotationVisitor) peek();
1287: push(av == null ? null : av.visitAnnotation(attrs
1288: .getValue("name"), attrs.getValue("desc")));
1289: }
1290:
1291: public void end(final String name) {
1292: AnnotationVisitor av = (AnnotationVisitor) pop();
1293: if (av != null) {
1294: av.visitEnd();
1295: }
1296: }
1297: }
1298:
1299: private final class AnnotationValueArrayRule extends Rule {
1300:
1301: public void begin(final String nm, final Attributes attrs) {
1302: AnnotationVisitor av = (AnnotationVisitor) peek();
1303: push(av == null ? null : av.visitArray(attrs
1304: .getValue("name")));
1305: }
1306:
1307: public void end(final String name) {
1308: AnnotationVisitor av = (AnnotationVisitor) pop();
1309: if (av != null) {
1310: av.visitEnd();
1311: }
1312: }
1313: }
1314:
1315: private final class AnnotationDefaultRule extends Rule {
1316:
1317: public void begin(final String nm, final Attributes attrs) {
1318: MethodVisitor av = (MethodVisitor) peek();
1319: push(av == null ? null : av.visitAnnotationDefault());
1320: }
1321:
1322: public void end(final String name) {
1323: AnnotationVisitor av = (AnnotationVisitor) pop();
1324: if (av != null) {
1325: av.visitEnd();
1326: }
1327: }
1328: }
1329:
1330: /**
1331: * Opcode
1332: */
1333: private final static class Opcode {
1334:
1335: public int opcode;
1336:
1337: public int type;
1338:
1339: public Opcode(final int opcode, final int type) {
1340: this.opcode = opcode;
1341: this.type = type;
1342: }
1343: }
1344: }
|