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