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