labelNames;
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.ASMifier}. Subclasses must not use this
+ * constructor . Instead, they must use the
+ * {@link #ASMifier(int, String, int)} version.
+ */
+ public ASMifier() {
+ this(Opcodes.ASM4, "cw", 0);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.ASMifier}.
+ *
+ * @param api
+ * the ASM API version implemented by this class. Must be one of
+ * {@link org.objectweb.asm.Opcodes#ASM4}.
+ * @param name
+ * the name of the visitor variable in the produced code.
+ * @param id
+ * identifier of the annotation visitor variable in the produced
+ * code.
+ */
+ protected ASMifier(final int api, final String name, final int id) {
+ super(api);
+ this.name = name;
+ this.id = id;
+ }
+
+ /**
+ * Prints the ASM source code to generate the given class to the standard
+ * output.
+ *
+ * Usage: ASMifier [-debug] <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err
+ .println("Prints the ASM code to generate the given class.");
+ System.err.println("Usage: ASMifier [-debug] "
+ + "");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1) {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(
+ System.out)), flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ String simpleName;
+ int n = name.lastIndexOf('/');
+ if (n == -1) {
+ simpleName = name;
+ } else {
+ text.add("package asm." + name.substring(0, n).replace('/', '.')
+ + ";\n");
+ simpleName = name.substring(n + 1);
+ }
+ text.add("import java.util.*;\n");
+ text.add("import org.objectweb.asm.*;\n");
+ text.add("import org.objectweb.asm.attrs.*;\n");
+ text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+ text.add("public static byte[] dump () throws Exception {\n\n");
+ text.add("ClassWriter cw = new ClassWriter(0);\n");
+ text.add("FieldVisitor fv;\n");
+ text.add("MethodVisitor mv;\n");
+ text.add("AnnotationVisitor av0;\n\n");
+
+ buf.setLength(0);
+ buf.append("cw.visit(");
+ switch (version) {
+ case Opcodes.V1_1:
+ buf.append("V1_1");
+ break;
+ case Opcodes.V1_2:
+ buf.append("V1_2");
+ break;
+ case Opcodes.V1_3:
+ buf.append("V1_3");
+ break;
+ case Opcodes.V1_4:
+ buf.append("V1_4");
+ break;
+ case Opcodes.V1_5:
+ buf.append("V1_5");
+ break;
+ case Opcodes.V1_6:
+ buf.append("V1_6");
+ break;
+ case Opcodes.V1_7:
+ buf.append("V1_7");
+ break;
+ default:
+ buf.append(version);
+ break;
+ }
+ buf.append(", ");
+ appendAccess(access | ACCESS_CLASS);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(superName);
+ buf.append(", ");
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < interfaces.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(interfaces[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ buf.append("cw.visitSource(");
+ appendConstant(file);
+ buf.append(", ");
+ appendConstant(debug);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ buf.setLength(0);
+ buf.append("cw.visitOuterClass(");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitClassAnnotation(final String desc,
+ final boolean visible) {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ buf.setLength(0);
+ buf.append("cw.visitInnerClass(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(outerName);
+ buf.append(", ");
+ appendConstant(innerName);
+ buf.append(", ");
+ appendAccess(access | ACCESS_INNER);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("fv = cw.visitField(");
+ appendAccess(access | ACCESS_FIELD);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("fv", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("mv = cw.visitMethod(");
+ appendAccess(access);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < exceptions.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(exceptions[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("mv", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("cw.visitEnd();\n\n");
+ text.add("return cw.toByteArray();\n");
+ text.add("}\n");
+ text.add("}\n");
+ }
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visit(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnum(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, desc);
+ buf.append(", ");
+ appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotation(final String name, final String desc) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitAnnotation(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", id + 1);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitArray(final String name) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitArray(");
+ appendConstant(buf, name);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", id + 1);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitFieldAnnotation(final String desc,
+ final boolean visible) {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ buf.setLength(0);
+ buf.append(name).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitAnnotationDefault() {
+ buf.setLength(0);
+ buf.append("{\n").append("av0 = ").append(name)
+ .append(".visitAnnotationDefault();\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitMethodAnnotation(final String desc,
+ final boolean visible) {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public ASMifier visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append("{\n").append("av0 = ").append(name)
+ .append(".visitParameterAnnotation(").append(parameter)
+ .append(", ");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ text.add(name + ".visitCode();\n");
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ buf.setLength(0);
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ declareFrameTypes(nLocal, local);
+ declareFrameTypes(nStack, stack);
+ if (type == Opcodes.F_NEW) {
+ buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
+ } else {
+ buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
+ }
+ buf.append(nLocal).append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, ").append(nStack).append(", new Object[] {");
+ appendFrameTypes(nStack, stack);
+ buf.append('}');
+ break;
+ case Opcodes.F_APPEND:
+ declareFrameTypes(nLocal, local);
+ buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
+ .append(nLocal).append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, 0, null");
+ break;
+ case Opcodes.F_CHOP:
+ buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
+ .append(nLocal).append(", null, 0, null");
+ break;
+ case Opcodes.F_SAME:
+ buf.append(name).append(
+ ".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ break;
+ case Opcodes.F_SAME1:
+ declareFrameTypes(1, stack);
+ buf.append(name).append(
+ ".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+ appendFrameTypes(1, stack);
+ buf.append('}');
+ break;
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append(name).append(".visitInsn(").append(OPCODES[opcode])
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append(name)
+ .append(".visitIntInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+ .toString(operand)).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append(name).append(".visitVarInsn(").append(OPCODES[opcode])
+ .append(", ").append(var).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode])
+ .append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitFieldInsn(")
+ .append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitMethodInsn(")
+ .append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitInvokeDynamicInsn(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(bsm);
+ buf.append(", new Object[]{");
+ for (int i = 0; i < bsmArgs.length; ++i) {
+ appendConstant(bsmArgs[i]);
+ if (i != bsmArgs.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("});\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode])
+ .append(", ");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append(name).append(".visitLabel(");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append(name).append(".visitLdcInsn(");
+ appendConstant(cst);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append(name).append(".visitIincInsn(").append(var).append(", ")
+ .append(increment).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append(name).append(".visitTableSwitchInsn(").append(min)
+ .append(", ").append(max).append(", ");
+ appendLabel(dflt);
+ buf.append(", new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append(name).append(".visitLookupSwitchInsn(");
+ appendLabel(dflt);
+ buf.append(", new int[] {");
+ for (int i = 0; i < keys.length; ++i) {
+ buf.append(i == 0 ? " " : ", ").append(keys[i]);
+ }
+ buf.append(" }, new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append(name).append(".visitMultiANewArrayInsn(");
+ appendConstant(desc);
+ buf.append(", ").append(dims).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ buf.setLength(0);
+ declareLabel(start);
+ declareLabel(end);
+ declareLabel(handler);
+ buf.append(name).append(".visitTryCatchBlock(");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ");
+ appendLabel(handler);
+ buf.append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitLocalVariable(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ").append(index).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append(name).append(".visitLineNumber(").append(line).append(", ");
+ appendLabel(start);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append(name).append(".visitMaxs(").append(maxStack).append(", ")
+ .append(maxLocals).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ buf.setLength(0);
+ buf.append(name).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Common methods
+ // ------------------------------------------------------------------------
+
+ public ASMifier visitAnnotation(final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append("{\n").append("av0 = ").append(name)
+ .append(".visitAnnotation(");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append("// ATTRIBUTE ").append(attr.type).append('\n');
+ if (attr instanceof ASMifiable) {
+ if (labelNames == null) {
+ labelNames = new HashMap();
+ }
+ buf.append("{\n");
+ ((ASMifiable) attr).asmify(buf, "attr", labelNames);
+ buf.append(name).append(".visitAttribute(attr);\n");
+ buf.append("}\n");
+ }
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ protected ASMifier createASMifier(final String name, final int id) {
+ return new ASMifier(Opcodes.ASM4, name, id);
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to
+ * {@link #buf buf}.
+ *
+ * @param access
+ * some access modifiers.
+ */
+ void appendAccess(final int access) {
+ boolean first = true;
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("ACC_PUBLIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("ACC_PRIVATE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("ACC_PROTECTED");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_FINAL");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STATIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ if ((access & ACCESS_CLASS) == 0) {
+ buf.append("ACC_SYNCHRONIZED");
+ } else {
+ buf.append("ACC_SUPER");
+ }
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0
+ && (access & ACCESS_FIELD) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VOLATILE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_BRIDGE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VARARGS");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0
+ && (access & ACCESS_FIELD) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_TRANSIENT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_NATIVE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0
+ && ((access & ACCESS_CLASS) != 0
+ || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0)) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ENUM");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0
+ && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0)) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ANNOTATION");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ABSTRACT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_INTERFACE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STRICT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_SYNTHETIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_DEPRECATED");
+ first = false;
+ }
+ if (first) {
+ buf.append('0');
+ }
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param cst
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be null .
+ */
+ protected void appendConstant(final Object cst) {
+ appendConstant(buf, cst);
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param buf
+ * a string buffer.
+ * @param cst
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be null .
+ */
+ static void appendConstant(final StringBuffer buf, final Object cst) {
+ if (cst == null) {
+ buf.append("null");
+ } else if (cst instanceof String) {
+ appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append("Type.getType(\"");
+ buf.append(((Type) cst).getDescriptor());
+ buf.append("\")");
+ } else if (cst instanceof Handle) {
+ buf.append("new Handle(");
+ Handle h = (Handle) cst;
+ buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()])
+ .append(", \"");
+ buf.append(h.getOwner()).append("\", \"");
+ buf.append(h.getName()).append("\", \"");
+ buf.append(h.getDesc()).append("\")");
+ } else if (cst instanceof Byte) {
+ buf.append("new Byte((byte)").append(cst).append(')');
+ } else if (cst instanceof Boolean) {
+ buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE"
+ : "Boolean.FALSE");
+ } else if (cst instanceof Short) {
+ buf.append("new Short((short)").append(cst).append(')');
+ } else if (cst instanceof Character) {
+ int c = ((Character) cst).charValue();
+ buf.append("new Character((char)").append(c).append(')');
+ } else if (cst instanceof Integer) {
+ buf.append("new Integer(").append(cst).append(')');
+ } else if (cst instanceof Float) {
+ buf.append("new Float(\"").append(cst).append("\")");
+ } else if (cst instanceof Long) {
+ buf.append("new Long(").append(cst).append("L)");
+ } else if (cst instanceof Double) {
+ buf.append("new Double(\"").append(cst).append("\")");
+ } else if (cst instanceof byte[]) {
+ byte[] v = (byte[]) cst;
+ buf.append("new byte[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof boolean[]) {
+ boolean[] v = (boolean[]) cst;
+ buf.append("new boolean[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof short[]) {
+ short[] v = (short[]) cst;
+ buf.append("new short[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof char[]) {
+ char[] v = (char[]) cst;
+ buf.append("new char[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append("(char)")
+ .append((int) v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof int[]) {
+ int[] v = (int[]) cst;
+ buf.append("new int[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof long[]) {
+ long[] v = (long[]) cst;
+ buf.append("new long[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
+ }
+ buf.append('}');
+ } else if (cst instanceof float[]) {
+ float[] v = (float[]) cst;
+ buf.append("new float[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
+ }
+ buf.append('}');
+ } else if (cst instanceof double[]) {
+ double[] v = (double[]) cst;
+ buf.append("new double[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
+ }
+ buf.append('}');
+ }
+ }
+
+ private void declareFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (o[i] instanceof Label) {
+ declareLabel((Label) o[i]);
+ }
+ }
+ }
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(", ");
+ }
+ if (o[i] instanceof String) {
+ appendConstant(o[i]);
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ buf.append("Opcodes.TOP");
+ break;
+ case 1:
+ buf.append("Opcodes.INTEGER");
+ break;
+ case 2:
+ buf.append("Opcodes.FLOAT");
+ break;
+ case 3:
+ buf.append("Opcodes.DOUBLE");
+ break;
+ case 4:
+ buf.append("Opcodes.LONG");
+ break;
+ case 5:
+ buf.append("Opcodes.NULL");
+ break;
+ case 6:
+ buf.append("Opcodes.UNINITIALIZED_THIS");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends a declaration of the given label to {@link #buf buf}. This
+ * declaration is of the form "Label lXXX = new Label();". Does nothing if
+ * the given label has already been declared.
+ *
+ * @param l
+ * a label.
+ */
+ protected void declareLabel(final Label l) {
+ if (labelNames == null) {
+ labelNames = new HashMap();
+ }
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "l" + labelNames.size();
+ labelNames.put(l, name);
+ buf.append("Label ").append(name).append(" = new Label();\n");
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. The given label
+ * must already have a name. One way to ensure this is to always call
+ * {@link #declareLabel declared} before calling this method.
+ *
+ * @param l
+ * a label.
+ */
+ protected void appendLabel(final Label l) {
+ buf.append(labelNames.get(l));
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/CheckAnnotationAdapter.java b/parabotv2/src/org/objectweb/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000..47aae74
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/CheckAnnotationAdapter.java
@@ -0,0 +1,136 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * An {@link org.objectweb.asm.AnnotationVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter extends AnnotationVisitor {
+
+ private final boolean named;
+
+ private boolean end;
+
+ public CheckAnnotationAdapter(final AnnotationVisitor av) {
+ this(av, true);
+ }
+
+ CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
+ super(Opcodes.ASM4, av);
+ this.named = named;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ checkEnd();
+ checkName(name);
+ if (!(value instanceof Byte || value instanceof Boolean
+ || value instanceof Character || value instanceof Short
+ || value instanceof Integer || value instanceof Long
+ || value instanceof Float || value instanceof Double
+ || value instanceof String || value instanceof Type
+ || value instanceof byte[] || value instanceof boolean[]
+ || value instanceof char[] || value instanceof short[]
+ || value instanceof int[] || value instanceof long[]
+ || value instanceof float[] || value instanceof double[])) {
+ throw new IllegalArgumentException("Invalid annotation value");
+ }
+ if (value instanceof Type) {
+ int sort = ((Type) value).getSort();
+ if (sort != Type.OBJECT && sort != Type.ARRAY) {
+ throw new IllegalArgumentException("Invalid annotation value");
+ }
+ }
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (value == null) {
+ throw new IllegalArgumentException("Invalid enum value");
+ }
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(av == null ? null
+ : av.visitAnnotation(name, desc));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ checkEnd();
+ checkName(name);
+ return new CheckAnnotationAdapter(av == null ? null
+ : av.visitArray(name), false);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot call a visit method after visitEnd has been called");
+ }
+ }
+
+ private void checkName(final String name) {
+ if (named && name == null) {
+ throw new IllegalArgumentException(
+ "Annotation value name must not be null");
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/CheckClassAdapter.java b/parabotv2/src/org/objectweb/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..2ebe567
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/CheckClassAdapter.java
@@ -0,0 +1,906 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.Frame;
+import org.objectweb.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link org.objectweb.asm.ClassVisitor} that checks that its methods are properly used. More
+ * precisely this class adapter checks each method call individually, based
+ * only on its arguments, but does not check the sequence
+ * of method calls. For example, the invalid sequence
+ * visitField(ACC_PUBLIC, "i", "I", null) visitField(ACC_PUBLIC,
+ * "i", "D", null) will not be detected by this class adapter.
+ *
+ *
+ * CheckClassAdapter can be also used to verify bytecode
+ * transformations in order to make sure transformed bytecode is sane. For
+ * example:
+ *
+ *
+ * InputStream is = ...; // get bytes for the source class
+ * ClassReader cr = new ClassReader(is);
+ * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
+ * ClassVisitor cv = new MyClassAdapter (new CheckClassAdapter(cw));
+ * cr.accept(cv, 0);
+ *
+ * StringWriter sw = new StringWriter();
+ * PrintWriter pw = new PrintWriter(sw);
+ * CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
+ * assertTrue(sw.toString(), sw.toString().length()==0);
+ *
+ *
+ * Above code runs transformed bytecode trough the
+ * CheckClassAdapter. It won't be exactly the same verification as
+ * JVM does, but it run data flow analysis for the code of each method and
+ * checks that expectations are met for each method instruction.
+ *
+ *
+ * If method bytecode has errors, assertion text will show the erroneous
+ * instruction number and dump of the failed method with information about
+ * locals and stack slot for each instruction. For example (format is -
+ * insnNumber locals : stack):
+ *
+ *
+ * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ * at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
+ * at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * ...
+ * remove()V
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . . :
+ * ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I
+ * ISTORE 2
+ * 00001 LinkedBlockingQueue$Itr . I . . . . . . :
+ * ...
+ *
+ * 00071 LinkedBlockingQueue$Itr . I . . . . . . :
+ * ILOAD 1
+ * 00072 ?
+ * INVOKESPECIAL java/lang/Integer. (I)V
+ * ...
+ *
+ *
+ * In the above output you can see that variable 1 loaded by
+ * ILOAD 1 instruction at position 00071 is not
+ * initialized. You can also see that at the beginning of the method (code
+ * inserted by the transformation) variable 2 is initialized.
+ *
+ *
+ * Note that when used like that, CheckClassAdapter.verify() can
+ * trigger additional class loading, because it is using
+ * SimpleVerifier.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckClassAdapter extends ClassVisitor {
+
+ /**
+ * The class version number.
+ */
+ private int version;
+
+ /**
+ * true if the visit method has been called.
+ */
+ private boolean start;
+
+ /**
+ * true if the visitSource method has been called.
+ */
+ private boolean source;
+
+ /**
+ * true if the visitOuterClass method has been called.
+ */
+ private boolean outer;
+
+ /**
+ * true if the visitEnd method has been called.
+ */
+ private boolean end;
+
+ /**
+ * The already visited labels. This map associate Integer values to Label
+ * keys.
+ */
+ private Map labels;
+
+ /**
+ * true if the method code must be checked with a BasicVerifier.
+ */
+ private boolean checkDataFlow;
+
+ /**
+ * Checks a given class.
+ *
+ * Usage: CheckClassAdapter <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ if (args.length != 1) {
+ System.err.println("Verifies the given class.");
+ System.err.println("Usage: CheckClassAdapter "
+ + "");
+ return;
+ }
+ ClassReader cr;
+ if (args[0].endsWith(".class")) {
+ cr = new ClassReader(new FileInputStream(args[0]));
+ } else {
+ cr = new ClassReader(args[0]);
+ }
+
+ verify(cr, false, new PrintWriter(System.err));
+ }
+
+ /**
+ * Checks a given class.
+ *
+ * @param cr
+ * a ClassReader that contains bytecode for the
+ * analysis.
+ * @param loader
+ * a ClassLoader which will be used to load
+ * referenced classes. This is useful if you are verifiying
+ * multiple interdependent classes.
+ * @param dump
+ * true if bytecode should be printed out not only when errors
+ * are found.
+ * @param pw
+ * write where results going to be printed
+ */
+ public static void verify(final ClassReader cr, final ClassLoader loader,
+ final boolean dump, final PrintWriter pw) {
+ ClassNode cn = new ClassNode();
+ cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
+
+ Type syperType = cn.superName == null ? null : Type
+ .getObjectType(cn.superName);
+ List methods = cn.methods;
+
+ List interfaces = new ArrayList();
+ for (Iterator i = cn.interfaces.iterator(); i.hasNext();) {
+ interfaces.add(Type.getObjectType(i.next().toString()));
+ }
+
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = methods.get(i);
+ SimpleVerifier verifier = new SimpleVerifier(
+ Type.getObjectType(cn.name), syperType, interfaces,
+ (cn.access & Opcodes.ACC_INTERFACE) != 0);
+ Analyzer a = new Analyzer(verifier);
+ if (loader != null) {
+ verifier.setClassLoader(loader);
+ }
+ try {
+ a.analyze(cn.name, method);
+ if (!dump) {
+ continue;
+ }
+ } catch (Exception e) {
+ e.printStackTrace(pw);
+ }
+ printAnalyzerResult(method, a, pw);
+ }
+ pw.flush();
+ }
+
+ /**
+ * Checks a given class
+ *
+ * @param cr
+ * a ClassReader that contains bytecode for the
+ * analysis.
+ * @param dump
+ * true if bytecode should be printed out not only when errors
+ * are found.
+ * @param pw
+ * write where results going to be printed
+ */
+ public static void verify(final ClassReader cr, final boolean dump,
+ final PrintWriter pw) {
+ verify(cr, null, dump, pw);
+ }
+
+ static void printAnalyzerResult(MethodNode method, Analyzer a,
+ final PrintWriter pw) {
+ Frame[] frames = a.getFrames();
+ Textifier t = new Textifier();
+ TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+ pw.println(method.name + method.desc);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ method.instructions.get(j).accept(mv);
+
+ StringBuffer s = new StringBuffer();
+ Frame f = frames[j];
+ if (f == null) {
+ s.append('?');
+ } else {
+ for (int k = 0; k < f.getLocals(); ++k) {
+ s.append(getShortName(f.getLocal(k).toString()))
+ .append(' ');
+ }
+ s.append(" : ");
+ for (int k = 0; k < f.getStackSize(); ++k) {
+ s.append(getShortName(f.getStack(k).toString()))
+ .append(' ');
+ }
+ }
+ while (s.length() < method.maxStack + method.maxLocals + 1) {
+ s.append(' ');
+ }
+ pw.print(Integer.toString(j + 100000).substring(1));
+ pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+ }
+ for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+ method.tryCatchBlocks.get(j).accept(mv);
+ pw.print(" " + t.text.get(t.text.size() - 1));
+ }
+ pw.println();
+ }
+
+ private static String getShortName(final String name) {
+ int n = name.lastIndexOf('/');
+ int k = name.length();
+ if (name.charAt(k - 1) == ';') {
+ k--;
+ }
+ return n == -1 ? name : name.substring(n + 1, k);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckClassAdapter}. Subclasses must not use
+ * this constructor . Instead, they must use the
+ * {@link #CheckClassAdapter(int, org.objectweb.asm.ClassVisitor, boolean)} version.
+ *
+ * @param cv
+ * the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor cv) {
+ this(cv, true);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckClassAdapter}. Subclasses must not use
+ * this constructor . Instead, they must use the
+ * {@link #CheckClassAdapter(int, org.objectweb.asm.ClassVisitor, boolean)} version.
+ *
+ * @param cv
+ * the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow
+ * true to perform basic data flow checks, or
+ * false to not perform any data flow check (see
+ * {@link CheckMethodAdapter}). This option requires valid
+ * maxLocals and maxStack values.
+ */
+ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
+ this(Opcodes.ASM4, cv, checkDataFlow);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckClassAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link org.objectweb.asm.Opcodes#ASM4}.
+ * @param cv
+ * the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow
+ * true to perform basic data flow checks, or
+ * false to not perform any data flow check (see
+ * {@link CheckMethodAdapter}). This option requires valid
+ * maxLocals and maxStack values.
+ */
+ protected CheckClassAdapter(final int api, final ClassVisitor cv,
+ final boolean checkDataFlow) {
+ super(api, cv);
+ this.labels = new HashMap();
+ this.checkDataFlow = checkDataFlow;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ if (start) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ start = true;
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+ + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (name == null || !name.endsWith("package-info")) {
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException(
+ "The super class name of the Object class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(superName, "super class name");
+ }
+ if (signature != null) {
+ checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException(
+ "The super class name of interfaces must be 'java/lang/Object'");
+ }
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(interfaces[i],
+ "interface name at index " + i);
+ }
+ }
+ this.version = version;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (source) {
+ throw new IllegalStateException(
+ "visitSource can be called only once.");
+ }
+ source = true;
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ checkState();
+ if (outer) {
+ throw new IllegalStateException(
+ "visitOuterClass can be called only once.");
+ }
+ outer = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
+ }
+ if (desc != null) {
+ CheckMethodAdapter.checkMethodDesc(desc);
+ }
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+ }
+ if (innerName != null) {
+ CheckMethodAdapter.checkIdentifier(innerName, "inner class name");
+ }
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+ + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (signature != null) {
+ checkFieldSignature(signature);
+ }
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ FieldVisitor av = super
+ .visitField(access, name, desc, signature, value);
+ return new CheckFieldAdapter(av);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+ + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+ + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (!"".equals(name) && !"".equals(name)) {
+ CheckMethodAdapter.checkMethodIdentifier(version, name,
+ "method name");
+ }
+ CheckMethodAdapter.checkMethodDesc(desc);
+ if (signature != null) {
+ checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(exceptions[i],
+ "exception name at index " + i);
+ }
+ }
+ CheckMethodAdapter cma;
+ if (checkDataFlow) {
+ cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
+ access, name, desc, signature, exceptions), labels);
+ } else {
+ cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
+ signature, exceptions), labels);
+ }
+ cma.version = version;
+ return cma;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkState();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkState();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkState();
+ end = true;
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that the visit method has been called and that visitEnd has not
+ * been called.
+ */
+ private void checkState() {
+ if (!start) {
+ throw new IllegalStateException(
+ "Cannot visit member before visit has been called.");
+ }
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot visit member after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This
+ * method also checks that mutually incompatible flags are not set
+ * simultaneously.
+ *
+ * @param access
+ * the access flags to be checked
+ * @param possibleAccess
+ * the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: "
+ + access);
+ }
+ int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+ int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+ int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+ if (pub + pri + pro > 1) {
+ throw new IllegalArgumentException(
+ "public private and protected are mutually exclusive: "
+ + access);
+ }
+ int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+ int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+ if (fin + abs > 1) {
+ throw new IllegalArgumentException(
+ "final and abstract are mutually exclusive: " + access);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkClassSignature(final String signature) {
+ // ClassSignature:
+ // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkMethodSignature(final String signature) {
+ // MethodTypeSignature:
+ // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+ // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkFieldSignature(final String signature) {
+ int pos = checkFieldTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks the formal type parameters of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameters(final String signature, int pos) {
+ // FormalTypeParameters:
+ // < FormalTypeParameter+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkFormalTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkFormalTypeParameter(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a formal type parameter of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameter(final String signature, int pos) {
+ // FormalTypeParameter:
+ // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+ pos = checkIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkFieldTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkFieldTypeSignature(signature, pos + 1);
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a field type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFieldTypeSignature(final String signature, int pos) {
+ // FieldTypeSignature:
+ // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+ //
+ // ArrayTypeSignature:
+ // [ TypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, int pos) {
+ // ClassTypeSignature:
+ // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+ // TypeArguments? )* ;
+
+ pos = checkChar('L', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkIdentifier(signature, pos + 1);
+ }
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, int pos) {
+ // TypeArguments:
+ // < TypeArgument+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, int pos) {
+ // TypeArgument:
+ // * | ( ( + | - )? FieldTypeSignature )
+
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkFieldTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(final String signature,
+ int pos) {
+ // TypeVariableSignature:
+ // T Identifier ;
+
+ pos = checkChar('T', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks a type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeSignature(final String signature, int pos) {
+ // TypeSignature:
+ // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return pos + 1;
+ default:
+ return checkFieldTypeSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks an identifier.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkIdentifier(final String signature, int pos) {
+ if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+ throw new IllegalArgumentException(signature
+ + ": identifier expected at index " + pos);
+ }
+ ++pos;
+ while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+ ++pos;
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a single character.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, int pos) {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c
+ + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the signature car at the given index.
+ *
+ * @param signature
+ * a signature.
+ * @param pos
+ * an index in signature.
+ * @return the character at the given index, or 0 if there is no such
+ * character.
+ */
+ private static char getChar(final String signature, int pos) {
+ return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/CheckFieldAdapter.java b/parabotv2/src/org/objectweb/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..0dc6170
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A {@link org.objectweb.asm.FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+ private boolean end;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckFieldAdapter}. Subclasses must not use
+ * this constructor . Instead, they must use the
+ * {@link #CheckFieldAdapter(int, org.objectweb.asm.FieldVisitor)} version.
+ *
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ */
+ public CheckFieldAdapter(final FieldVisitor fv) {
+ this(Opcodes.ASM4, fv);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckFieldAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link org.objectweb.asm.Opcodes#ASM4}.
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ */
+ protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+ super(api, fv);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEnd();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEnd();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ super.visitEnd();
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot call a visit method after visitEnd has been called");
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/CheckMethodAdapter.java b/parabotv2/src/org/objectweb/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..622aac0
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1397 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link org.objectweb.asm.MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based only on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.objectweb.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is void m () , the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String, org.objectweb.asm.MethodVisitor, java.util.Map)} constructor.
+ * They are not performed if any other constructor is used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+ /**
+ * The class version number.
+ */
+ public int version;
+
+ /**
+ * The access flags of the method.
+ */
+ private int access;
+
+ /**
+ * true if the visitCode method has been called.
+ */
+ private boolean startCode;
+
+ /**
+ * true if the visitMaxs method has been called.
+ */
+ private boolean endCode;
+
+ /**
+ * true if the visitEnd method has been called.
+ */
+ private boolean endMethod;
+
+ /**
+ * Number of visited instructions.
+ */
+ private int insnCount;
+
+ /**
+ * The already visited labels. This map associate Integer values to pseudo
+ * code offsets.
+ */
+ private final Map labels;
+
+ /**
+ * The labels used in this method. Every used label must be visited with
+ * visitLabel before the end of the method (i.e. should be in #labels).
+ */
+ private Set usedLabels;
+
+ /**
+ * Number of visited frames in expanded form.
+ */
+ private int expandedFrames;
+
+ /**
+ * Number of visited frames in compressed form.
+ */
+ private int compressedFrames;
+
+ /**
+ * Number of instructions before the last visited frame.
+ */
+ private int lastFrame = -1;
+
+ /**
+ * The exception handler ranges. Each pair of list element contains the
+ * start and end labels of an exception handler block.
+ */
+ private List handlers;
+
+ /**
+ * Code of the visit method to be used for each opcode.
+ */
+ private static final int[] TYPE;
+
+ /**
+ * The Label.status field.
+ */
+ private static Field labelStatusField;
+
+ static {
+ String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+ + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+ + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+ TYPE = new int[s.length()];
+ for (int i = 0; i < TYPE.length; ++i) {
+ TYPE[i] = s.charAt(i) - 'A' - 1;
+ }
+ }
+
+ // code to generate the above string
+ // public static void main (String[] args) {
+ // int[] TYPE = new int[] {
+ // 0, //NOP
+ // 0, //ACONST_NULL
+ // 0, //ICONST_M1
+ // 0, //ICONST_0
+ // 0, //ICONST_1
+ // 0, //ICONST_2
+ // 0, //ICONST_3
+ // 0, //ICONST_4
+ // 0, //ICONST_5
+ // 0, //LCONST_0
+ // 0, //LCONST_1
+ // 0, //FCONST_0
+ // 0, //FCONST_1
+ // 0, //FCONST_2
+ // 0, //DCONST_0
+ // 0, //DCONST_1
+ // 1, //BIPUSH
+ // 1, //SIPUSH
+ // 7, //LDC
+ // -1, //LDC_W
+ // -1, //LDC2_W
+ // 2, //ILOAD
+ // 2, //LLOAD
+ // 2, //FLOAD
+ // 2, //DLOAD
+ // 2, //ALOAD
+ // -1, //ILOAD_0
+ // -1, //ILOAD_1
+ // -1, //ILOAD_2
+ // -1, //ILOAD_3
+ // -1, //LLOAD_0
+ // -1, //LLOAD_1
+ // -1, //LLOAD_2
+ // -1, //LLOAD_3
+ // -1, //FLOAD_0
+ // -1, //FLOAD_1
+ // -1, //FLOAD_2
+ // -1, //FLOAD_3
+ // -1, //DLOAD_0
+ // -1, //DLOAD_1
+ // -1, //DLOAD_2
+ // -1, //DLOAD_3
+ // -1, //ALOAD_0
+ // -1, //ALOAD_1
+ // -1, //ALOAD_2
+ // -1, //ALOAD_3
+ // 0, //IALOAD
+ // 0, //LALOAD
+ // 0, //FALOAD
+ // 0, //DALOAD
+ // 0, //AALOAD
+ // 0, //BALOAD
+ // 0, //CALOAD
+ // 0, //SALOAD
+ // 2, //ISTORE
+ // 2, //LSTORE
+ // 2, //FSTORE
+ // 2, //DSTORE
+ // 2, //ASTORE
+ // -1, //ISTORE_0
+ // -1, //ISTORE_1
+ // -1, //ISTORE_2
+ // -1, //ISTORE_3
+ // -1, //LSTORE_0
+ // -1, //LSTORE_1
+ // -1, //LSTORE_2
+ // -1, //LSTORE_3
+ // -1, //FSTORE_0
+ // -1, //FSTORE_1
+ // -1, //FSTORE_2
+ // -1, //FSTORE_3
+ // -1, //DSTORE_0
+ // -1, //DSTORE_1
+ // -1, //DSTORE_2
+ // -1, //DSTORE_3
+ // -1, //ASTORE_0
+ // -1, //ASTORE_1
+ // -1, //ASTORE_2
+ // -1, //ASTORE_3
+ // 0, //IASTORE
+ // 0, //LASTORE
+ // 0, //FASTORE
+ // 0, //DASTORE
+ // 0, //AASTORE
+ // 0, //BASTORE
+ // 0, //CASTORE
+ // 0, //SASTORE
+ // 0, //POP
+ // 0, //POP2
+ // 0, //DUP
+ // 0, //DUP_X1
+ // 0, //DUP_X2
+ // 0, //DUP2
+ // 0, //DUP2_X1
+ // 0, //DUP2_X2
+ // 0, //SWAP
+ // 0, //IADD
+ // 0, //LADD
+ // 0, //FADD
+ // 0, //DADD
+ // 0, //ISUB
+ // 0, //LSUB
+ // 0, //FSUB
+ // 0, //DSUB
+ // 0, //IMUL
+ // 0, //LMUL
+ // 0, //FMUL
+ // 0, //DMUL
+ // 0, //IDIV
+ // 0, //LDIV
+ // 0, //FDIV
+ // 0, //DDIV
+ // 0, //IREM
+ // 0, //LREM
+ // 0, //FREM
+ // 0, //DREM
+ // 0, //INEG
+ // 0, //LNEG
+ // 0, //FNEG
+ // 0, //DNEG
+ // 0, //ISHL
+ // 0, //LSHL
+ // 0, //ISHR
+ // 0, //LSHR
+ // 0, //IUSHR
+ // 0, //LUSHR
+ // 0, //IAND
+ // 0, //LAND
+ // 0, //IOR
+ // 0, //LOR
+ // 0, //IXOR
+ // 0, //LXOR
+ // 8, //IINC
+ // 0, //I2L
+ // 0, //I2F
+ // 0, //I2D
+ // 0, //L2I
+ // 0, //L2F
+ // 0, //L2D
+ // 0, //F2I
+ // 0, //F2L
+ // 0, //F2D
+ // 0, //D2I
+ // 0, //D2L
+ // 0, //D2F
+ // 0, //I2B
+ // 0, //I2C
+ // 0, //I2S
+ // 0, //LCMP
+ // 0, //FCMPL
+ // 0, //FCMPG
+ // 0, //DCMPL
+ // 0, //DCMPG
+ // 6, //IFEQ
+ // 6, //IFNE
+ // 6, //IFLT
+ // 6, //IFGE
+ // 6, //IFGT
+ // 6, //IFLE
+ // 6, //IF_ICMPEQ
+ // 6, //IF_ICMPNE
+ // 6, //IF_ICMPLT
+ // 6, //IF_ICMPGE
+ // 6, //IF_ICMPGT
+ // 6, //IF_ICMPLE
+ // 6, //IF_ACMPEQ
+ // 6, //IF_ACMPNE
+ // 6, //GOTO
+ // 6, //JSR
+ // 2, //RET
+ // 9, //TABLESWITCH
+ // 10, //LOOKUPSWITCH
+ // 0, //IRETURN
+ // 0, //LRETURN
+ // 0, //FRETURN
+ // 0, //DRETURN
+ // 0, //ARETURN
+ // 0, //RETURN
+ // 4, //GETSTATIC
+ // 4, //PUTSTATIC
+ // 4, //GETFIELD
+ // 4, //PUTFIELD
+ // 5, //INVOKEVIRTUAL
+ // 5, //INVOKESPECIAL
+ // 5, //INVOKESTATIC
+ // 5, //INVOKEINTERFACE
+ // -1, //INVOKEDYNAMIC
+ // 3, //NEW
+ // 1, //NEWARRAY
+ // 3, //ANEWARRAY
+ // 0, //ARRAYLENGTH
+ // 0, //ATHROW
+ // 3, //CHECKCAST
+ // 3, //INSTANCEOF
+ // 0, //MONITORENTER
+ // 0, //MONITOREXIT
+ // -1, //WIDE
+ // 11, //MULTIANEWARRAY
+ // 6, //IFNULL
+ // 6, //IFNONNULL
+ // -1, //GOTO_W
+ // -1 //JSR_W
+ // };
+ // for (int i = 0; i < TYPE.length; ++i) {
+ // System.out.print((char)(TYPE[i] + 1 + 'A'));
+ // }
+ // System.out.println();
+ // }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String, org.objectweb.asm.MethodVisitor, java.util.Map)}).
+ * Subclasses must not use this constructor . Instead, they must use
+ * the {@link #CheckMethodAdapter(int, org.objectweb.asm.MethodVisitor, java.util.Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv) {
+ this(mv, new HashMap());
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String, org.objectweb.asm.MethodVisitor, java.util.Map)}).
+ * Subclasses must not use this constructor . Instead, they must use
+ * the {@link #CheckMethodAdapter(int, org.objectweb.asm.MethodVisitor, java.util.Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(final MethodVisitor mv,
+ final Map labels) {
+ this(Opcodes.ASM4, mv, labels);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String, org.objectweb.asm.MethodVisitor, java.util.Map)}).
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ protected CheckMethodAdapter(final int api, final MethodVisitor mv,
+ final Map labels) {
+ super(api, mv);
+ this.labels = labels;
+ this.usedLabels = new HashSet();
+ this.handlers = new ArrayList();
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.CheckMethodAdapter} object. This method adapter
+ * will perform basic data flow checks. For instance in a method whose
+ * signature is void m () , the invalid instruction IRETURN, or the
+ * invalid sequence IADD L2I will be detected.
+ *
+ * @param access
+ * the method's access flags.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link org.objectweb.asm.Type Type}).
+ * @param cmv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(final int access, final String name,
+ final String desc, final MethodVisitor cmv,
+ final Map labels) {
+ this(new MethodNode(access, name, desc, null, null) {
+ @Override
+ public void visitEnd() {
+ Analyzer a = new Analyzer(
+ new BasicVerifier());
+ try {
+ a.analyze("dummy", this);
+ } catch (Exception e) {
+ if (e instanceof IndexOutOfBoundsException
+ && maxLocals == 0 && maxStack == 0) {
+ throw new RuntimeException(
+ "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+ }
+ e.printStackTrace();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ CheckClassAdapter.printAnalyzerResult(this, a, pw);
+ pw.close();
+ throw new RuntimeException(e.getMessage() + ' '
+ + sw.toString());
+ }
+ accept(cmv);
+ }
+ }, labels);
+ this.access = access;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkEndMethod();
+ return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitParameterAnnotation(
+ parameter, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEndMethod();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ throw new RuntimeException("Abstract methods cannot have code");
+ }
+ startCode = true;
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (insnCount == lastFrame) {
+ throw new IllegalStateException(
+ "At most one frame can be visited at a given code location.");
+ }
+ lastFrame = insnCount;
+ int mLocal;
+ int mStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mLocal = Integer.MAX_VALUE;
+ mStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ mLocal = 0;
+ mStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ mLocal = 0;
+ mStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ mLocal = 3;
+ mStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
+ }
+
+ if (nLocal > mLocal) {
+ throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+ + " for frame type " + type);
+ }
+ if (nStack > mStack) {
+ throw new IllegalArgumentException("Invalid nStack=" + nStack
+ + " for frame type " + type);
+ }
+
+ if (type != Opcodes.F_CHOP) {
+ if (nLocal > 0 && (local == null || local.length < nLocal)) {
+ throw new IllegalArgumentException(
+ "Array local[] is shorter than nLocal");
+ }
+ for (int i = 0; i < nLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
+ }
+ if (nStack > 0 && (stack == null || stack.length < nStack)) {
+ throw new IllegalArgumentException(
+ "Array stack[] is shorter than nStack");
+ }
+ for (int i = 0; i < nStack; ++i) {
+ checkFrameValue(stack[i]);
+ }
+ if (type == Opcodes.F_NEW) {
+ ++expandedFrames;
+ } else {
+ ++compressedFrames;
+ }
+ if (expandedFrames > 0 && compressedFrames > 0) {
+ throw new RuntimeException(
+ "Expanded and compressed frames must not be mixed.");
+ }
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 0);
+ super.visitInsn(opcode);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 1);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ // case Constants.NEWARRAY:
+ default:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException(
+ "Invalid operand (must be an array type code T_...): "
+ + operand);
+ }
+ }
+ super.visitIntInsn(opcode, operand);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 2);
+ checkUnsignedShort(var, "Invalid variable index");
+ super.visitVarInsn(opcode, var);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 3);
+ checkInternalName(type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException(
+ "NEW cannot be used to create arrays: " + type);
+ }
+ super.visitTypeInsn(opcode, type);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 4);
+ checkInternalName(owner, "owner");
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 5);
+ if (opcode != Opcodes.INVOKESPECIAL || !"".equals(name)) {
+ checkMethodIdentifier(version, name, "name");
+ }
+ checkInternalName(owner, "owner");
+ checkMethodDesc(desc);
+ super.visitMethodInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ checkStartCode();
+ checkEndCode();
+ checkMethodIdentifier(version, name, "name");
+ checkMethodDesc(desc);
+ if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+ && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+ throw new IllegalArgumentException("invalid handle tag "
+ + bsm.getTag());
+ }
+ for (int i = 0; i < bsmArgs.length; i++) {
+ checkLDCConstant(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 6);
+ checkLabel(label, false, "label");
+ checkNonDebugLabel(label);
+ super.visitJumpInsn(opcode, label);
+ usedLabels.add(label);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(label, false, "label");
+ if (labels.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labels.put(label, new Integer(insnCount));
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ checkStartCode();
+ checkEndCode();
+ checkLDCConstant(cst);
+ super.visitLdcInsn(cst);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(var, "Invalid variable index");
+ checkSignedShort(increment, "Invalid increment");
+ super.visitIincInsn(var, increment);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ checkStartCode();
+ checkEndCode();
+ if (max < min) {
+ throw new IllegalArgumentException("Max = " + max
+ + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException(
+ "There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ checkEndCode();
+ checkStartCode();
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException(
+ "There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ usedLabels.add(dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ checkStartCode();
+ checkEndCode();
+ checkDesc(desc, false);
+ if (desc.charAt(0) != '[') {
+ throw new IllegalArgumentException(
+ "Invalid descriptor (must be an array type descriptor): "
+ + desc);
+ }
+ if (dims < 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must be greater than 0): " + dims);
+ }
+ if (dims > desc.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must not be greater than dims(desc)): "
+ + dims);
+ }
+ super.visitMultiANewArrayInsn(desc, dims);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(start, false, "start label");
+ checkLabel(end, false, "end label");
+ checkLabel(handler, false, "handler label");
+ checkNonDebugLabel(start);
+ checkNonDebugLabel(end);
+ checkNonDebugLabel(handler);
+ if (labels.get(start) != null || labels.get(end) != null
+ || labels.get(handler) != null) {
+ throw new IllegalStateException(
+ "Try catch blocks must be visited before their labels");
+ }
+ if (type != null) {
+ checkInternalName(type, "type");
+ }
+ super.visitTryCatchBlock(start, end, handler, type);
+ handlers.add(start);
+ handlers.add(end);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ checkStartCode();
+ checkEndCode();
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ checkLabel(start, true, "start label");
+ checkLabel(end, true, "end label");
+ checkUnsignedShort(index, "Invalid variable index");
+ int s = labels.get(start).intValue();
+ int e = labels.get(end).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(line, "Invalid line number");
+ checkLabel(start, true, "start label");
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ checkStartCode();
+ checkEndCode();
+ endCode = true;
+ for (Label l : usedLabels) {
+ if (labels.get(l) == null) {
+ throw new IllegalStateException("Undefined label used");
+ }
+ }
+ for (int i = 0; i < handlers.size();) {
+ Integer start = labels.get(handlers.get(i++));
+ Integer end = labels.get(handlers.get(i++));
+ if (start == null || end == null) {
+ throw new IllegalStateException(
+ "Undefined try catch block labels");
+ }
+ if (end.intValue() <= start.intValue()) {
+ throw new IllegalStateException(
+ "Emty try catch block handler range");
+ }
+ }
+ checkUnsignedShort(maxStack, "Invalid max stack");
+ checkUnsignedShort(maxLocals, "Invalid max locals");
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEndMethod();
+ endMethod = true;
+ super.visitEnd();
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks that the visitCode method has been called.
+ */
+ void checkStartCode() {
+ if (!startCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions before visitCode has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitMaxs method has not been called.
+ */
+ void checkEndCode() {
+ if (endCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions after visitMaxs has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitEnd method has not been called.
+ */
+ void checkEndMethod() {
+ if (endMethod) {
+ throw new IllegalStateException(
+ "Cannot visit elements after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks a stack frame value.
+ *
+ * @param value
+ * the value to be checked.
+ */
+ void checkFrameValue(final Object value) {
+ if (value == Opcodes.TOP || value == Opcodes.INTEGER
+ || value == Opcodes.FLOAT || value == Opcodes.LONG
+ || value == Opcodes.DOUBLE || value == Opcodes.NULL
+ || value == Opcodes.UNINITIALIZED_THIS) {
+ return;
+ }
+ if (value instanceof String) {
+ checkInternalName((String) value, "Invalid stack frame value");
+ return;
+ }
+ if (!(value instanceof Label)) {
+ throw new IllegalArgumentException("Invalid stack frame value: "
+ + value);
+ } else {
+ usedLabels.add((Label) value);
+ }
+ }
+
+ /**
+ * Checks that the type of the given opcode is equal to the given type.
+ *
+ * @param opcode
+ * the opcode to be checked.
+ * @param type
+ * the expected opcode type.
+ */
+ static void checkOpcode(final int opcode, final int type) {
+ if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+ throw new IllegalArgumentException("Invalid opcode: " + opcode);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed byte.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedByte(final int value, final String msg) {
+ if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed byte): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedShort(final int value, final String msg) {
+ if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an unsigned short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkUnsignedShort(final int value, final String msg) {
+ if (value < 0 || value > 65535) {
+ throw new IllegalArgumentException(msg
+ + " (must be an unsigned short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an {@link Integer}, a{@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the value to be checked.
+ */
+ static void checkConstant(final Object cst) {
+ if (!(cst instanceof Integer) && !(cst instanceof Float)
+ && !(cst instanceof Long) && !(cst instanceof Double)
+ && !(cst instanceof String)) {
+ throw new IllegalArgumentException("Invalid constant: " + cst);
+ }
+ }
+
+ void checkLDCConstant(final Object cst) {
+ if (cst instanceof Type) {
+ int s = ((Type) cst).getSort();
+ if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+ throw new IllegalArgumentException("Illegal LDC constant value");
+ }
+ if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+ throw new IllegalArgumentException(
+ "ldc of a constant class requires at least version 1.5");
+ }
+ if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a method type requires at least version 1.7");
+ }
+ } else if (cst instanceof Handle) {
+ if ((version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a handle requires at least version 1.7");
+ }
+ int tag = ((Handle) cst).getTag();
+ if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+ throw new IllegalArgumentException("invalid handle tag " + tag);
+ }
+ } else {
+ checkConstant(cst);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid unqualified name.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkUnqualifiedName(int version, final String name,
+ final String msg) {
+ if ((version & 0xFFFF) < Opcodes.V1_5) {
+ checkIdentifier(name, msg);
+ } else {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final String msg) {
+ checkIdentifier(name, 0, -1, msg);
+ }
+
+ /**
+ * Checks that the given substring is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to name.length() if name is not
+ * null .
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final int start,
+ final int end, final String msg) {
+ if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ int max = end == -1 ? name.length() : end;
+ for (int i = start + 1; i < max; ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkMethodIdentifier(int version, final String name,
+ final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if ((version & 0xFFFF) >= Opcodes.V1_5) {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ return;
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a '', '' or a valid Java identifier): "
+ + name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be '' or '' or a valid Java identifier): "
+ + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (name.charAt(0) == '[') {
+ checkDesc(name, false);
+ } else {
+ checkInternalName(name, 0, -1, msg);
+ }
+ }
+
+ /**
+ * Checks that the given substring is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to name.length() if name is not
+ * null .
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final int start,
+ final int end, final String msg) {
+ int max = end == -1 ? name.length() : end;
+ try {
+ int begin = start;
+ int slash;
+ do {
+ slash = name.indexOf('/', begin + 1);
+ if (slash == -1 || slash > max) {
+ slash = max;
+ }
+ checkIdentifier(name, begin, slash, null);
+ begin = slash + 1;
+ } while (slash != max);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a fully qualified class name in internal form): "
+ + name);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param canBeVoid
+ * true if V can be considered valid.
+ */
+ static void checkDesc(final String desc, final boolean canBeVoid) {
+ int end = checkDesc(desc, 0, canBeVoid);
+ if (end != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that a the given substring is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param canBeVoid
+ * true if V can be considered valid.
+ * @return the index of the last character of the type decriptor, plus one.
+ */
+ static int checkDesc(final String desc, final int start,
+ final boolean canBeVoid) {
+ if (desc == null || start >= desc.length()) {
+ throw new IllegalArgumentException(
+ "Invalid type descriptor (must not be null or empty)");
+ }
+ int index;
+ switch (desc.charAt(start)) {
+ case 'V':
+ if (canBeVoid) {
+ return start + 1;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return start + 1;
+ case '[':
+ index = start + 1;
+ while (index < desc.length() && desc.charAt(index) == '[') {
+ ++index;
+ }
+ if (index < desc.length()) {
+ return checkDesc(desc, index, false);
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'L':
+ index = desc.indexOf(';', start);
+ if (index == -1 || index - start < 2) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ try {
+ checkInternalName(desc, start + 1, index, null);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ return index + 1;
+ default:
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid method descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ */
+ static void checkMethodDesc(final String desc) {
+ if (desc == null || desc.length() == 0) {
+ throw new IllegalArgumentException(
+ "Invalid method descriptor (must not be null or empty)");
+ }
+ if (desc.charAt(0) != '(' || desc.length() < 3) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ int start = 1;
+ if (desc.charAt(start) != ')') {
+ do {
+ if (desc.charAt(start) == 'V') {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ start = checkDesc(desc, start, false);
+ } while (start < desc.length() && desc.charAt(start) != ')');
+ }
+ start = checkDesc(desc, start + 1, true);
+ if (start != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given label is not null. This method can also check that
+ * the label has been visited.
+ *
+ * @param label
+ * the label to be checked.
+ * @param checkVisited
+ * true to check that the label has been visited.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ void checkLabel(final Label label, final boolean checkVisited,
+ final String msg) {
+ if (label == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null)");
+ }
+ if (checkVisited && labels.get(label) == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be visited first)");
+ }
+ }
+
+ /**
+ * Checks that the given label is not a label used only for debug purposes.
+ *
+ * @param label
+ * the label to be checked.
+ */
+ private static void checkNonDebugLabel(final Label label) {
+ Field f = getLabelStatusField();
+ int status = 0;
+ try {
+ status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+ } catch (IllegalAccessException e) {
+ throw new Error("Internal error");
+ }
+ if ((status & 0x01) != 0) {
+ throw new IllegalArgumentException(
+ "Labels used for debug info cannot be reused for control flow");
+ }
+ }
+
+ /**
+ * Returns the Field object corresponding to the Label.status field.
+ *
+ * @return the Field object corresponding to the Label.status field.
+ */
+ private static Field getLabelStatusField() {
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("a");
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("status");
+ }
+ }
+ return labelStatusField;
+ }
+
+ /**
+ * Returns the field of the Label class whose name is given.
+ *
+ * @param name
+ * a field name.
+ * @return the field of the Label class whose name is given, or null.
+ */
+ private static Field getLabelField(final String name) {
+ try {
+ Field f = Label.class.getDeclaredField(name);
+ f.setAccessible(true);
+ return f;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/CheckSignatureAdapter.java b/parabotv2/src/org/objectweb/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..6f7693a
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,330 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link org.objectweb.asm.signature.SignatureVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+ /**
+ * Type to be used to check class signatures. See
+ * {@link #CheckSignatureAdapter(int, org.objectweb.asm.signature.SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See
+ * {@link #CheckSignatureAdapter(int, org.objectweb.asm.signature.SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See
+ * {@link #CheckSignatureAdapter(int, org.objectweb.asm.signature.SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ private static final int EMPTY = 1;
+
+ private static final int FORMAL = 2;
+
+ private static final int BOUND = 4;
+
+ private static final int SUPER = 8;
+
+ private static final int PARAM = 16;
+
+ private static final int RETURN = 32;
+
+ private static final int SIMPLE_TYPE = 64;
+
+ private static final int CLASS_TYPE = 128;
+
+ private static final int END = 256;
+
+ /**
+ * Type of the signature to be checked.
+ */
+ private final int type;
+
+ /**
+ * State of the automaton used to check the order of method calls.
+ */
+ private int state;
+
+ /**
+ * true if the checked type signature can be 'V'.
+ */
+ private boolean canBeVoid;
+
+ /**
+ * The visitor to which this adapter must delegate calls. May be
+ * null .
+ */
+ private final SignatureVisitor sv;
+
+ /**
+ * Creates a new {@link org.objectweb.asm.util.CheckSignatureAdapter} object. Subclasses must
+ * not use this constructor . Instead, they must use the
+ * {@link #CheckSignatureAdapter(int, int, org.objectweb.asm.signature.SignatureVisitor)} version.
+ *
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * null .
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+ this(Opcodes.ASM4, type, sv);
+ }
+
+ /**
+ * Creates a new {@link org.objectweb.asm.util.CheckSignatureAdapter} object.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link org.objectweb.asm.Opcodes#ASM4}.
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * null .
+ */
+ protected CheckSignatureAdapter(final int api, final int type,
+ final SignatureVisitor sv) {
+ super(api);
+ this.type = type;
+ this.state = EMPTY;
+ this.sv = sv;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE
+ || (state != EMPTY && state != FORMAL && state != BOUND)) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+ state = FORMAL;
+ if (sv != null) {
+ sv.visitFormalTypeParameter(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (state != FORMAL) {
+ throw new IllegalStateException();
+ }
+ state = BOUND;
+ SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (state != FORMAL && state != BOUND) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = SUPER;
+ SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (state != SUPER) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterface();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // method signatures
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = PARAM;
+ SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = RETURN;
+ SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+ CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ cv.canBeVoid = true;
+ return cv;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (state != RETURN) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // type signatures
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitBaseType(descriptor);
+ }
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "type variable");
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitTypeVariable(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = SIMPLE_TYPE;
+ SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ state = CLASS_TYPE;
+ if (sv != null) {
+ sv.visitClassType(name);
+ }
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "inner class name");
+ if (sv != null) {
+ sv.visitInnerClassType(name);
+ }
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (sv != null) {
+ sv.visitTypeArgument();
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = END;
+ if (sv != null) {
+ sv.visitEnd();
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/Printer.java b/parabotv2/src/org/objectweb/asm/util/Printer.java
new file mode 100644
index 0000000..b5742e2
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/Printer.java
@@ -0,0 +1,499 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+
+/**
+ * An abstract converter from visit events to text.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class Printer {
+
+ /**
+ * The names of the Java Virtual Machine opcodes.
+ */
+ public static final String[] OPCODES;
+
+ /**
+ * The names of the for operand parameter values of the
+ * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when
+ * opcode is NEWARRAY.
+ */
+ public static final String[] TYPES;
+
+ /**
+ * The names of the tag field values for
+ * {@link org.objectweb.asm.Handle}.
+ */
+ public static final String[] HANDLE_TAG;
+
+ static {
+ String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"
+ + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"
+ + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
+ + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"
+ + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"
+ + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
+ + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"
+ + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"
+ + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
+ + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"
+ + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"
+ + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
+ + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"
+ + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"
+ + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
+ + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"
+ + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"
+ + "INVOKESTATIC,INVOKEINTERFACE,INVOKEDYNAMIC,NEW,NEWARRAY,"
+ + "ANEWARRAY,ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,"
+ + "MONITORENTER,MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
+ OPCODES = new String[200];
+ int i = 0;
+ int j = 0;
+ int l;
+ while ((l = s.indexOf(',', j)) > 0) {
+ OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);
+ j = l + 1;
+ }
+
+ s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
+ TYPES = new String[12];
+ j = 0;
+ i = 4;
+ while ((l = s.indexOf(',', j)) > 0) {
+ TYPES[i++] = s.substring(j, l);
+ j = l + 1;
+ }
+
+ s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
+ + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+ + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+ HANDLE_TAG = new String[10];
+ j = 0;
+ i = 1;
+ while ((l = s.indexOf(',', j)) > 0) {
+ HANDLE_TAG[i++] = s.substring(j, l);
+ j = l + 1;
+ }
+ }
+
+ /**
+ * The ASM API version implemented by this class. The value of this field
+ * must be one of {@link org.objectweb.asm.Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * A buffer that can be used to create strings.
+ */
+ protected final StringBuffer buf;
+
+ /**
+ * The text to be printed. Since the code of methods is not necessarily
+ * visited in sequential order, one method after the other, but can be
+ * interlaced (some instructions from method one, then some instructions
+ * from method two, then some instructions from method one again...), it is
+ * not possible to print the visited instructions directly to a sequential
+ * stream. A class is therefore printed in a two steps process: a string
+ * tree is constructed during the visit, and printed to a sequential stream
+ * at the end of the visit. This string tree is stored in this field, as a
+ * string list that can contain other string lists, which can themselves
+ * contain other string lists, and so on.
+ */
+ public final List text;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.Printer}.
+ */
+ protected Printer(final int api) {
+ this.api = api;
+ this.buf = new StringBuffer();
+ this.text = new ArrayList();
+ }
+
+ /**
+ * Class header. See {@link org.objectweb.asm.ClassVisitor#visit}.
+ */
+ public abstract void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces);
+
+ /**
+ * Class source. See {@link org.objectweb.asm.ClassVisitor#visitSource}.
+ */
+ public abstract void visitSource(final String file, final String debug);
+
+ /**
+ * Class outer class. See
+ * {@link org.objectweb.asm.ClassVisitor#visitOuterClass}.
+ */
+ public abstract void visitOuterClass(final String owner, final String name,
+ final String desc);
+
+ /**
+ * Class annotation. See
+ * {@link org.objectweb.asm.ClassVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitClassAnnotation(final String desc,
+ final boolean visible);
+
+ /**
+ * Class attribute. See
+ * {@link org.objectweb.asm.ClassVisitor#visitAttribute}.
+ */
+ public abstract void visitClassAttribute(final Attribute attr);
+
+ /**
+ * Class inner name. See
+ * {@link org.objectweb.asm.ClassVisitor#visitInnerClass}.
+ */
+ public abstract void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access);
+
+ /**
+ * Class field. See {@link org.objectweb.asm.ClassVisitor#visitField}.
+ */
+ public abstract Printer visitField(final int access, final String name,
+ final String desc, final String signature, final Object value);
+
+ /**
+ * Class method. See {@link org.objectweb.asm.ClassVisitor#visitMethod}.
+ */
+ public abstract Printer visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions);
+
+ /**
+ * Class end. See {@link org.objectweb.asm.ClassVisitor#visitEnd}.
+ */
+ public abstract void visitClassEnd();
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Annotation value. See {@link org.objectweb.asm.AnnotationVisitor#visit}.
+ */
+ public abstract void visit(final String name, final Object value);
+
+ /**
+ * Annotation enum value. See
+ * {@link org.objectweb.asm.AnnotationVisitor#visitEnum}.
+ */
+ public abstract void visitEnum(final String name, final String desc,
+ final String value);
+
+ /**
+ * Nested annotation value. See
+ * {@link org.objectweb.asm.AnnotationVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitAnnotation(final String name, final String desc);
+
+ /**
+ * Annotation array value. See
+ * {@link org.objectweb.asm.AnnotationVisitor#visitArray}.
+ */
+ public abstract Printer visitArray(final String name);
+
+ /**
+ * Annotation end. See {@link org.objectweb.asm.AnnotationVisitor#visitEnd}.
+ */
+ public abstract void visitAnnotationEnd();
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * Field annotation. See
+ * {@link org.objectweb.asm.FieldVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitFieldAnnotation(final String desc,
+ final boolean visible);
+
+ /**
+ * Field attribute. See
+ * {@link org.objectweb.asm.FieldVisitor#visitAttribute}.
+ */
+ public abstract void visitFieldAttribute(final Attribute attr);
+
+ /**
+ * Field end. See {@link org.objectweb.asm.FieldVisitor#visitEnd}.
+ */
+ public abstract void visitFieldEnd();
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Method default annotation. See
+ * {@link org.objectweb.asm.MethodVisitor#visitAnnotationDefault}.
+ */
+ public abstract Printer visitAnnotationDefault();
+
+ /**
+ * Method annotation. See
+ * {@link org.objectweb.asm.MethodVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitMethodAnnotation(final String desc,
+ final boolean visible);
+
+ /**
+ * Method parameter annotation. See
+ * {@link org.objectweb.asm.MethodVisitor#visitParameterAnnotation}.
+ */
+ public abstract Printer visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible);
+
+ /**
+ * Method attribute. See
+ * {@link org.objectweb.asm.MethodVisitor#visitAttribute}.
+ */
+ public abstract void visitMethodAttribute(final Attribute attr);
+
+ /**
+ * Method start. See {@link org.objectweb.asm.MethodVisitor#visitCode}.
+ */
+ public abstract void visitCode();
+
+ /**
+ * Method stack frame. See
+ * {@link org.objectweb.asm.MethodVisitor#visitFrame}.
+ */
+ public abstract void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack);
+
+ /**
+ * Method instruction. See {@link org.objectweb.asm.MethodVisitor#visitInsn}
+ * .
+ */
+ public abstract void visitInsn(final int opcode);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitIntInsn}.
+ */
+ public abstract void visitIntInsn(final int opcode, final int operand);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitVarInsn}.
+ */
+ public abstract void visitVarInsn(final int opcode, final int var);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitTypeInsn}.
+ */
+ public abstract void visitTypeInsn(final int opcode, final String type);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitFieldInsn}.
+ */
+ public abstract void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitMethodInsn}.
+ */
+ public abstract void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ */
+ public abstract void visitInvokeDynamicInsn(String name, String desc,
+ Handle bsm, Object... bsmArgs);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitJumpInsn}.
+ */
+ public abstract void visitJumpInsn(final int opcode, final Label label);
+
+ /**
+ * Method label. See {@link org.objectweb.asm.MethodVisitor#visitLabel}.
+ */
+ public abstract void visitLabel(final Label label);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitLdcInsn}.
+ */
+ public abstract void visitLdcInsn(final Object cst);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitIincInsn}.
+ */
+ public abstract void visitIincInsn(final int var, final int increment);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}.
+ */
+ public abstract void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}.
+ */
+ public abstract void visitLookupSwitchInsn(final Label dflt,
+ final int[] keys, final Label[] labels);
+
+ /**
+ * Method instruction. See
+ * {@link org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}.
+ */
+ public abstract void visitMultiANewArrayInsn(final String desc,
+ final int dims);
+
+ /**
+ * Method exception handler. See
+ * {@link org.objectweb.asm.MethodVisitor#visitTryCatchBlock}.
+ */
+ public abstract void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type);
+
+ /**
+ * Method debug info. See
+ * {@link org.objectweb.asm.MethodVisitor#visitLocalVariable}.
+ */
+ public abstract void visitLocalVariable(final String name,
+ final String desc, final String signature, final Label start,
+ final Label end, final int index);
+
+ /**
+ * Method debug info. See
+ * {@link org.objectweb.asm.MethodVisitor#visitLineNumber}.
+ */
+ public abstract void visitLineNumber(final int line, final Label start);
+
+ /**
+ * Method max stack and max locals. See
+ * {@link org.objectweb.asm.MethodVisitor#visitMaxs}.
+ */
+ public abstract void visitMaxs(final int maxStack, final int maxLocals);
+
+ /**
+ * Method end. See {@link org.objectweb.asm.MethodVisitor#visitEnd}.
+ */
+ public abstract void visitMethodEnd();
+
+ /**
+ * Returns the text constructed by this visitor.
+ *
+ * @return the text constructed by this visitor.
+ */
+ public List getText() {
+ return text;
+ }
+
+ /**
+ * Prints the text constructed by this visitor.
+ *
+ * @param pw
+ * the print writer to be used.
+ */
+ public void print(final PrintWriter pw) {
+ printList(pw, text);
+ }
+
+ /**
+ * Appends a quoted string to a given buffer.
+ *
+ * @param buf
+ * the buffer where the string must be added.
+ * @param s
+ * the string to be added.
+ */
+ public static void appendString(final StringBuffer buf, final String s) {
+ buf.append('\"');
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\n') {
+ buf.append("\\n");
+ } else if (c == '\r') {
+ buf.append("\\r");
+ } else if (c == '\\') {
+ buf.append("\\\\");
+ } else if (c == '"') {
+ buf.append("\\\"");
+ } else if (c < 0x20 || c > 0x7f) {
+ buf.append("\\u");
+ if (c < 0x10) {
+ buf.append("000");
+ } else if (c < 0x100) {
+ buf.append("00");
+ } else if (c < 0x1000) {
+ buf.append('0');
+ }
+ buf.append(Integer.toString(c, 16));
+ } else {
+ buf.append(c);
+ }
+ }
+ buf.append('\"');
+ }
+
+ /**
+ * Prints the given string tree.
+ *
+ * @param pw
+ * the writer to be used to print the tree.
+ * @param l
+ * a string tree, i.e., a string list that can contain other
+ * string lists, and so on recursively.
+ */
+ static void printList(final PrintWriter pw, final List> l) {
+ for (int i = 0; i < l.size(); ++i) {
+ Object o = l.get(i);
+ if (o instanceof List) {
+ printList(pw, (List>) o);
+ } else {
+ pw.print(o.toString());
+ }
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/Textifiable.java b/parabotv2/src/org/objectweb/asm/util/Textifiable.java
new file mode 100644
index 0000000..aad97ba
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/Textifiable.java
@@ -0,0 +1,56 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.util.Map;
+
+import org.objectweb.asm.Label;
+
+/**
+ * An {@link org.objectweb.asm.Attribute Attribute} that can print a readable
+ * representation of itself.
+ *
+ * Implementations should construct readable output from an attribute data
+ * structure. Such representation could be used in unit test assertions.
+ *
+ * @author Eugene Kuleshov
+ */
+public interface Textifiable {
+
+ /**
+ * Build a human readable representation of this attribute.
+ *
+ * @param buf
+ * a buffer used for printing Java code.
+ * @param labelNames
+ * map of label instances to their names.
+ */
+ void textify(StringBuffer buf, Map labelNames);
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/Textifier.java b/parabotv2/src/org/objectweb/asm/util/Textifier.java
new file mode 100644
index 0000000..c1b42a0
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/Textifier.java
@@ -0,0 +1,1200 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+
+/**
+ * A {@link org.objectweb.asm.util.Printer} that prints a disassembled view of the classes it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class Textifier extends Printer {
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for internal
+ * type names in bytecode notation.
+ */
+ public static final int INTERNAL_NAME = 0;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int FIELD_DESCRIPTOR = 1;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * signatures, formatted in bytecode notation
+ */
+ public static final int FIELD_SIGNATURE = 2;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int METHOD_DESCRIPTOR = 3;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * signatures, formatted in bytecode notation
+ */
+ public static final int METHOD_SIGNATURE = 4;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in bytecode notation
+ */
+ public static final int CLASS_SIGNATURE = 5;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field or
+ * method return value signatures, formatted in default Java notation
+ * (non-bytecode)
+ */
+ public static final int TYPE_DECLARATION = 6;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int CLASS_DECLARATION = 7;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * parameter signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int PARAMETERS_DECLARATION = 8;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for handle
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int HANDLE_DESCRIPTOR = 9;
+
+ /**
+ * Tab for class members.
+ */
+ protected String tab = " ";
+
+ /**
+ * Tab for bytecode instructions.
+ */
+ protected String tab2 = " ";
+
+ /**
+ * Tab for table and lookup switch instructions.
+ */
+ protected String tab3 = " ";
+
+ /**
+ * Tab for labels.
+ */
+ protected String ltab = " ";
+
+ /**
+ * The label names. This map associate String values to Label keys.
+ */
+ protected Map labelNames;
+
+ private int valueNumber = 0;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.Textifier}. Subclasses must not use this
+ * constructor . Instead, they must use the {@link #Textifier(int)}
+ * version.
+ */
+ public Textifier() {
+ this(Opcodes.ASM4);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.Textifier}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link org.objectweb.asm.Opcodes#ASM4}.
+ */
+ protected Textifier(final int api) {
+ super(api);
+ }
+
+ /**
+ * Prints a disassembled view of the given class to the standard output.
+ *
+ * Usage: Textifier [-debug] <binary class name or class file name >
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err
+ .println("Prints a disassembled view of the given class.");
+ System.err.println("Usage: Textifier [-debug] "
+ + "");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1) {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ int major = version & 0xFFFF;
+ int minor = version >>> 16;
+ buf.setLength(0);
+ buf.append("// class version ").append(major).append('.').append(minor)
+ .append(" (").append(version).append(")\n");
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append("// DEPRECATED\n");
+ }
+ buf.append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
+
+ appendDescriptor(CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(sv);
+ buf.append("// declaration: ").append(name)
+ .append(sv.getDeclaration()).append('\n');
+ }
+
+ appendAccess(access & ~Opcodes.ACC_SUPER);
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ buf.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ buf.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) == 0) {
+ buf.append("class ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+
+ if (superName != null && !"java/lang/Object".equals(superName)) {
+ buf.append(" extends ");
+ appendDescriptor(INTERNAL_NAME, superName);
+ buf.append(' ');
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append(" implements ");
+ for (int i = 0; i < interfaces.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, interfaces[i]);
+ buf.append(' ');
+ }
+ }
+ buf.append(" {\n\n");
+
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ if (file != null) {
+ buf.append(tab).append("// compiled from: ").append(file)
+ .append('\n');
+ }
+ if (debug != null) {
+ buf.append(tab).append("// debug info: ").append(debug)
+ .append('\n');
+ }
+ if (buf.length() > 0) {
+ text.add(buf.toString());
+ }
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ buf.setLength(0);
+ buf.append(tab).append("OUTERCLASS ");
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append(' ');
+ if (name != null) {
+ buf.append(name).append(' ');
+ }
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitClassAnnotation(final String desc,
+ final boolean visible) {
+ text.add("\n");
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attr) {
+ text.add("\n");
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ buf.setLength(0);
+ buf.append(tab).append("// access flags 0x");
+ buf.append(
+ Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
+ .append('\n');
+ buf.append(tab);
+ appendAccess(access);
+ buf.append("INNERCLASS ");
+ appendDescriptor(INTERNAL_NAME, name);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, outerName);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, innerName);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab).append("// declaration: ")
+ .append(sv.getDeclaration()).append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(name);
+ if (value != null) {
+ buf.append(" = ");
+ if (value instanceof String) {
+ buf.append('\"').append(value).append('\"');
+ } else {
+ buf.append(value);
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ return t;
+ }
+
+ @Override
+ public Textifier visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
+
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(METHOD_SIGNATURE, signature);
+
+ TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(v);
+ String genericDecl = v.getDeclaration();
+ String genericReturn = v.getReturnType();
+ String genericExceptions = v.getExceptions();
+
+ buf.append(tab).append("// declaration: ").append(genericReturn)
+ .append(' ').append(name).append(genericDecl);
+ if (genericExceptions != null) {
+ buf.append(" throws ").append(genericExceptions);
+ }
+ buf.append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ buf.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ buf.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ buf.append("bridge ");
+ }
+
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append(" throws ");
+ for (int i = 0; i < exceptions.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, exceptions[i]);
+ buf.append(' ');
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ return t;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("}\n");
+ }
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+
+ if (value instanceof String) {
+ visitString((String) value);
+ } else if (value instanceof Type) {
+ visitType((Type) value);
+ } else if (value instanceof Byte) {
+ visitByte(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ visitBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Short) {
+ visitShort(((Short) value).shortValue());
+ } else if (value instanceof Character) {
+ visitChar(((Character) value).charValue());
+ } else if (value instanceof Integer) {
+ visitInt(((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ visitFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ visitLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ visitDouble(((Double) value).doubleValue());
+ } else if (value.getClass().isArray()) {
+ buf.append('{');
+ if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitByte(v[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitBoolean(v[i]);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitShort(v[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitChar(v[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitInt(v[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitLong(v[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitFloat(v[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitDouble(v[i]);
+ }
+ }
+ buf.append('}');
+ }
+
+ text.add(buf.toString());
+ }
+
+ private void visitInt(final int value) {
+ buf.append(value);
+ }
+
+ private void visitLong(final long value) {
+ buf.append(value).append('L');
+ }
+
+ private void visitFloat(final float value) {
+ buf.append(value).append('F');
+ }
+
+ private void visitDouble(final double value) {
+ buf.append(value).append('D');
+ }
+
+ private void visitChar(final char value) {
+ buf.append("(char)").append((int) value);
+ }
+
+ private void visitShort(final short value) {
+ buf.append("(short)").append(value);
+ }
+
+ private void visitByte(final byte value) {
+ buf.append("(byte)").append(value);
+ }
+
+ private void visitBoolean(final boolean value) {
+ buf.append(value);
+ }
+
+ private void visitString(final String value) {
+ appendString(buf, value);
+ }
+
+ private void visitType(final Type value) {
+ buf.append(value.getClassName()).append(".class");
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('.').append(value);
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitAnnotation(final String name, final String desc) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(")");
+ return t;
+ }
+
+ @Override
+ public Textifier visitArray(final String name) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('{');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add("}");
+ return t;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Textifier visitFieldAnnotation(final String desc,
+ final boolean visible) {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Textifier visitAnnotationDefault() {
+ text.add(tab2 + "default=");
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add("\n");
+ return t;
+ }
+
+ @Override
+ public Textifier visitMethodAnnotation(final String desc,
+ final boolean visible) {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public Textifier visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append(tab2).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(visible ? ") // parameter " : ") // invisible, parameter ");
+ text.add(new Integer(parameter));
+ text.add("\n");
+ return t;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Textifiable) {
+ ((Textifiable) attr).textify(buf, labelNames);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ buf.setLength(0);
+ buf.append(ltab);
+ buf.append("FRAME ");
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ buf.append("FULL [");
+ appendFrameTypes(nLocal, local);
+ buf.append("] [");
+ appendFrameTypes(nStack, stack);
+ buf.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ buf.append("APPEND [");
+ appendFrameTypes(nLocal, local);
+ buf.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("CHOP ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ buf.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ buf.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+ .toString(operand)).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(" : ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(' ');
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ buf.setLength(0);
+ buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append(" [");
+ appendHandle(bsm);
+ buf.append(tab3).append("// arguments:");
+ if (bsmArgs.length == 0) {
+ buf.append(" none");
+ } else {
+ buf.append('\n').append(tab3);
+ for (int i = 0; i < bsmArgs.length; i++) {
+ Object cst = bsmArgs[i];
+ if (cst instanceof String) {
+ Printer.appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append(((Type) cst).getDescriptor()).append(".class");
+ } else if (cst instanceof Handle) {
+ appendHandle((Handle) cst);
+ } else {
+ buf.append(cst);
+ }
+ buf.append(", ");
+ }
+ buf.setLength(buf.length() - 2);
+ }
+ buf.append('\n');
+ buf.append(tab2).append("]\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ buf.append(ltab);
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append(tab2).append("LDC ");
+ if (cst instanceof String) {
+ Printer.appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append(((Type) cst).getDescriptor()).append(".class");
+ } else {
+ buf.append(cst);
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append(tab2).append("IINC ").append(var).append(' ')
+ .append(increment).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ buf.setLength(0);
+ buf.append(tab2).append("TABLESWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(min + i).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ buf.setLength(0);
+ buf.append(tab2).append("LOOKUPSWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(keys[i]).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append(tab2).append("MULTIANEWARRAY ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(dims).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ buf.setLength(0);
+ buf.append(tab2).append("TRYCATCHBLOCK ");
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ');
+ appendLabel(handler);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ buf.setLength(0);
+ buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ');
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ').append(index).append('\n');
+
+ if (signature != null) {
+ buf.append(tab2);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab2).append("// declaration: ")
+ .append(sv.getDeclaration()).append('\n');
+ }
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append(tab2).append("LINENUMBER ").append(line).append(' ');
+ appendLabel(start);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');
+ text.add(buf.toString());
+
+ buf.setLength(0);
+ buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Common methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Prints a disassembled view of the given annotation.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * true if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public Textifier visitAnnotation(final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(visible ? ")\n" : ") // invisible\n");
+ return t;
+ }
+
+ /**
+ * Prints a disassembled view of the given attribute.
+ *
+ * @param attr
+ * an attribute.
+ */
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Textifiable) {
+ ((Textifiable) attr).textify(buf, null);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new TraceVisitor instance.
+ *
+ * @return a new TraceVisitor.
+ */
+ protected Textifier createTextifier() {
+ return new Textifier();
+ }
+
+ /**
+ * Appends an internal name, a type descriptor or a type signature to
+ * {@link #buf buf}.
+ *
+ * @param type
+ * indicates if desc is an internal name, a field descriptor, a
+ * method descriptor, a class signature, ...
+ * @param desc
+ * an internal name, type descriptor, or type signature. May be
+ * null .
+ */
+ protected void appendDescriptor(final int type, final String desc) {
+ if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
+ || type == METHOD_SIGNATURE) {
+ if (desc != null) {
+ buf.append("// signature ").append(desc).append('\n');
+ }
+ } else {
+ buf.append(desc);
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. Creates a new
+ * label name if the given label does not yet have one.
+ *
+ * @param l
+ * a label.
+ */
+ protected void appendLabel(final Label l) {
+ if (labelNames == null) {
+ labelNames = new HashMap();
+ }
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(l, name);
+ }
+ buf.append(name);
+ }
+
+ /**
+ * Appends the information about the given handle to {@link #buf buf}.
+ *
+ * @param h
+ * a handle, non null.
+ */
+ protected void appendHandle(final Handle h) {
+ buf.append('\n').append(tab3);
+ int tag = h.getTag();
+ buf.append("// handle kind 0x").append(Integer.toHexString(tag))
+ .append(" : ");
+ switch (tag) {
+ case Opcodes.H_GETFIELD:
+ buf.append("GETFIELD");
+ break;
+ case Opcodes.H_GETSTATIC:
+ buf.append("GETSTATIC");
+ break;
+ case Opcodes.H_PUTFIELD:
+ buf.append("PUTFIELD");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ buf.append("PUTSTATIC");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ buf.append("INVOKEINTERFACE");
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ buf.append("INVOKESPECIAL");
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ buf.append("INVOKESTATIC");
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ buf.append("INVOKEVIRTUAL");
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ buf.append("NEWINVOKESPECIAL");
+ break;
+ }
+ buf.append('\n');
+ buf.append(tab3);
+ appendDescriptor(INTERNAL_NAME, h.getOwner());
+ buf.append('.');
+ buf.append(h.getName());
+ buf.append('(');
+ appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
+ buf.append(')').append('\n');
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to
+ * {@link #buf buf}.
+ *
+ * @param access
+ * some access modifiers.
+ */
+ private void appendAccess(final int access) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ buf.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ buf.append("static ");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ buf.append("synchronized ");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ buf.append("volatile ");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ buf.append("transient ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ buf.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ buf.append("strictfp ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ buf.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ }
+ }
+
+ private void appendComa(final int i) {
+ if (i != 0) {
+ buf.append(", ");
+ }
+ }
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(' ');
+ }
+ if (o[i] instanceof String) {
+ String desc = (String) o[i];
+ if (desc.startsWith("[")) {
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ } else {
+ appendDescriptor(INTERNAL_NAME, desc);
+ }
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ appendDescriptor(FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(FIELD_DESCRIPTOR, "U");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/TraceAnnotationVisitor.java b/parabotv2/src/org/objectweb/asm/util/TraceAnnotationVisitor.java
new file mode 100644
index 0000000..e03b057
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/TraceAnnotationVisitor.java
@@ -0,0 +1,89 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * An {@link org.objectweb.asm.AnnotationVisitor} that prints the annotations it visits with a
+ * {@link org.objectweb.asm.util.Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
+
+ private final Printer p;
+
+ public TraceAnnotationVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
+ super(Opcodes.ASM4, av);
+ this.p = p;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ p.visit(name, value);
+ super.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ p.visitEnum(name, desc, value);
+ super.visitEnum(name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ Printer p = this.p.visitAnnotation(name, desc);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitAnnotation(name, desc);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ Printer p = this.p.visitArray(name);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitArray(name);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitAnnotationEnd();
+ super.visitEnd();
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/TraceClassVisitor.java b/parabotv2/src/org/objectweb/asm/util/TraceClassVisitor.java
new file mode 100644
index 0000000..a5a56bc
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/TraceClassVisitor.java
@@ -0,0 +1,209 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import java.io.PrintWriter;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A {@link org.objectweb.asm.ClassVisitor} that prints the classes it visits with a
+ * {@link org.objectweb.asm.util.Printer}. This class visitor can be used in the middle of a class
+ * visitor chain to trace the class that is visited at a given point in this
+ * chain. This may be useful for debugging purposes.
+ *
+ * The trace printed when visiting the Hello class is the following:
+ *
+ *
+ *
+ *
+ * // class version 49.0 (49) // access flags 0x21 public class Hello {
+ *
+ * // compiled from: Hello.java
+ *
+ * // access flags 0x1 public <init> ()V ALOAD 0 INVOKESPECIAL
+ * java/lang/Object <init> ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
+ *
+ * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
+ * java/lang/System out Ljava/io/PrintStream; LDC "hello"
+ * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
+ * MAXSTACK = 2 MAXLOCALS = 1 }
+ *
+ *
+ * where Hello is defined by:
+ *
+ *
+ *
+ *
+ * public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
+ * }
+ *
+ *
+ *
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public final class TraceClassVisitor extends ClassVisitor {
+
+ /**
+ * The print writer to be used to print the class. May be null.
+ */
+ private final PrintWriter pw;
+
+ /**
+ * The object that actually converts visit events into text.
+ */
+ public final Printer p;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.TraceClassVisitor}.
+ *
+ * @param pw
+ * the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final PrintWriter pw) {
+ this(null, pw);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.TraceClassVisitor}.
+ *
+ * @param cv
+ * the {@link org.objectweb.asm.ClassVisitor} to which this visitor delegates
+ * calls. May be null .
+ * @param pw
+ * the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
+ this(cv, new Textifier(), pw);
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.util.TraceClassVisitor}.
+ *
+ * @param cv
+ * the {@link org.objectweb.asm.ClassVisitor} to which this visitor delegates
+ * calls. May be null .
+ * @param p
+ * the object that actually converts visit events into text.
+ * @param pw
+ * the print writer to be used to print the class. May be null if
+ * you simply want to use the result via
+ * {@link org.objectweb.asm.util.Printer#getText()}, instead of printing it.
+ */
+ public TraceClassVisitor(final ClassVisitor cv, final Printer p,
+ final PrintWriter pw) {
+ super(Opcodes.ASM4, cv);
+ this.pw = pw;
+ this.p = p;
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ p.visit(version, access, name, signature, superName, interfaces);
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ p.visitSource(file, debug);
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ p.visitOuterClass(owner, name, desc);
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ Printer p = this.p.visitClassAnnotation(desc, visible);
+ AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitClassAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ p.visitInnerClass(name, outerName, innerName, access);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ Printer p = this.p.visitField(access, name, desc, signature, value);
+ FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
+ signature, value);
+ return new TraceFieldVisitor(fv, p);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ Printer p = this.p.visitMethod(access, name, desc, signature,
+ exceptions);
+ MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
+ desc, signature, exceptions);
+ return new TraceMethodVisitor(mv, p);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitClassEnd();
+ if (pw != null) {
+ p.print(pw);
+ pw.flush();
+ }
+ super.visitEnd();
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/TraceFieldVisitor.java b/parabotv2/src/org/objectweb/asm/util/TraceFieldVisitor.java
new file mode 100644
index 0000000..3f98bd4
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/TraceFieldVisitor.java
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A {@link org.objectweb.asm.FieldVisitor} that prints the fields it visits with a
+ * {@link org.objectweb.asm.util.Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceFieldVisitor extends FieldVisitor {
+
+ public final Printer p;
+
+ public TraceFieldVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
+ super(Opcodes.ASM4, fv);
+ this.p = p;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ Printer p = this.p.visitFieldAnnotation(desc, visible);
+ AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitFieldAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitFieldEnd();
+ super.visitEnd();
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/TraceMethodVisitor.java b/parabotv2/src/org/objectweb/asm/util/TraceMethodVisitor.java
new file mode 100644
index 0000000..5f874d1
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/TraceMethodVisitor.java
@@ -0,0 +1,223 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * A {@link org.objectweb.asm.MethodVisitor} that prints the methods it visits with a
+ * {@link org.objectweb.asm.util.Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceMethodVisitor extends MethodVisitor {
+
+ public final Printer p;
+
+ public TraceMethodVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
+ super(Opcodes.ASM4, mv);
+ this.p = p;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ Printer p = this.p.visitMethodAnnotation(desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitMethodAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ Printer p = this.p.visitAnnotationDefault();
+ AnnotationVisitor av = mv == null ? null : mv.visitAnnotationDefault();
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
+ parameter, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitCode() {
+ p.visitCode();
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ p.visitFrame(type, nLocal, local, nStack, stack);
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ p.visitInsn(opcode);
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ p.visitIntInsn(opcode, operand);
+ super.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ p.visitVarInsn(opcode, var);
+ super.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ p.visitTypeInsn(opcode, type);
+ super.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ p.visitFieldInsn(opcode, owner, name, desc);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ p.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ p.visitJumpInsn(opcode, label);
+ super.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ p.visitLabel(label);
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ p.visitLdcInsn(cst);
+ super.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ p.visitIincInsn(var, increment);
+ super.visitIincInsn(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ p.visitTableSwitchInsn(min, max, dflt, labels);
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ p.visitLookupSwitchInsn(dflt, keys, labels);
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ p.visitMultiANewArrayInsn(desc, dims);
+ super.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ p.visitTryCatchBlock(start, end, handler, type);
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ p.visitLocalVariable(name, desc, signature, start, end, index);
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ p.visitLineNumber(line, start);
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ p.visitMaxs(maxStack, maxLocals);
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitMethodEnd();
+ super.visitEnd();
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/TraceSignatureVisitor.java b/parabotv2/src/org/objectweb/asm/util/TraceSignatureVisitor.java
new file mode 100644
index 0000000..ef4d37f
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/TraceSignatureVisitor.java
@@ -0,0 +1,317 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.util;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link org.objectweb.asm.signature.SignatureVisitor} that prints a disassembled view of the signature
+ * it visits.
+ *
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public final class TraceSignatureVisitor extends SignatureVisitor {
+
+ private final StringBuffer declaration;
+
+ private boolean isInterface;
+
+ private boolean seenFormalParameter;
+
+ private boolean seenInterfaceBound;
+
+ private boolean seenParameter;
+
+ private boolean seenInterface;
+
+ private StringBuffer returnType;
+
+ private StringBuffer exceptions;
+
+ /**
+ * Stack used to keep track of class types that have arguments. Each element
+ * of this stack is a boolean encoded in one bit. The top of the stack is
+ * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+ * /2.
+ */
+ private int argumentStack;
+
+ /**
+ * Stack used to keep track of array class types. Each element of this stack
+ * is a boolean encoded in one bit. The top of the stack is the lowest order
+ * bit. Pushing false = *2, pushing true = *2+1, popping = /2.
+ */
+ private int arrayStack;
+
+ private String separator = "";
+
+ public TraceSignatureVisitor(final int access) {
+ super(Opcodes.ASM4);
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+ this.declaration = new StringBuffer();
+ }
+
+ private TraceSignatureVisitor(final StringBuffer buf) {
+ super(Opcodes.ASM4);
+ this.declaration = buf;
+ }
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ declaration.append(seenFormalParameter ? ", " : "<").append(name);
+ seenFormalParameter = true;
+ seenInterfaceBound = false;
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ separator = seenInterfaceBound ? ", " : " extends ";
+ seenInterfaceBound = true;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ separator = seenInterface ? ", " : isInterface ? " extends "
+ : " implements ";
+ seenInterface = true;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (seenParameter) {
+ declaration.append(", ");
+ } else {
+ seenParameter = true;
+ declaration.append('(');
+ }
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (seenParameter) {
+ seenParameter = false;
+ } else {
+ declaration.append('(');
+ }
+ declaration.append(')');
+ returnType = new StringBuffer();
+ return new TraceSignatureVisitor(returnType);
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (exceptions == null) {
+ exceptions = new StringBuffer();
+ } else {
+ exceptions.append(", ");
+ }
+ // startType();
+ return new TraceSignatureVisitor(exceptions);
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ switch (descriptor) {
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ // case 'D':
+ default:
+ declaration.append("double");
+ break;
+ }
+ endType();
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ declaration.append(name);
+ endType();
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ startType();
+ arrayStack |= 1;
+ return this;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if ("java/lang/Object".equals(name)) {
+ // Map
+ // or
+ // abstract public V get(Object key); (seen in Dictionary.class)
+ // should have Object
+ // but java.lang.String extends java.lang.Object is unnecessary
+ boolean needObjectClass = argumentStack % 2 != 0 || seenParameter;
+ if (needObjectClass) {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ } else {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ declaration.append('.');
+ declaration.append(separator).append(name.replace('/', '.'));
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+ declaration.append('?');
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char tag) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+
+ if (tag == EXTENDS) {
+ declaration.append("? extends ");
+ } else if (tag == SUPER) {
+ declaration.append("? super ");
+ }
+
+ startType();
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ endType();
+ }
+
+ public String getDeclaration() {
+ return declaration.toString();
+ }
+
+ public String getReturnType() {
+ return returnType == null ? null : returnType.toString();
+ }
+
+ public String getExceptions() {
+ return exceptions == null ? null : exceptions.toString();
+ }
+
+ // -----------------------------------------------
+
+ private void endFormals() {
+ if (seenFormalParameter) {
+ declaration.append('>');
+ seenFormalParameter = false;
+ }
+ }
+
+ private void startType() {
+ arrayStack *= 2;
+ }
+
+ private void endType() {
+ if (arrayStack % 2 == 0) {
+ arrayStack /= 2;
+ } else {
+ while (arrayStack % 2 != 0) {
+ arrayStack /= 2;
+ declaration.append("[]");
+ }
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/util/package.html b/parabotv2/src/org/objectweb/asm/util/package.html
new file mode 100644
index 0000000..91d7420
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/util/package.html
@@ -0,0 +1,40 @@
+
+
+
+Provides ASM visitors that can be useful for programming and
+debugging purposes. These class visitors are normally not used by applications
+at runtime. This is why they are bundled in an optional asm-util.jar
+library that is separated from (but requires) the asm.jar library,
+which contains the core ASM framework.
+
+@since ASM 1.3.2
+
+
diff --git a/parabotv2/src/org/objectweb/asm/xml/ASMContentHandler.java b/parabotv2/src/org/objectweb/asm/xml/ASMContentHandler.java
new file mode 100644
index 0000000..2944e04
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/ASMContentHandler.java
@@ -0,0 +1,1318 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
+ * document into Java class file. This class can be feeded by any kind of SAX
+ * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
+ *
+ * @see org.objectweb.asm.xml.SAXClassAdapter
+ * @see org.objectweb.asm.xml.Processor
+ *
+ * @author Eugene Kuleshov
+ */
+@SuppressWarnings("unchecked")
+public class ASMContentHandler extends DefaultHandler implements Opcodes {
+
+ /**
+ * Stack of the intermediate processing contexts.
+ */
+ private final ArrayList stack = new ArrayList();
+
+ /**
+ * Complete name of the current element.
+ */
+ String match = "";
+
+ /**
+ * Current instance of the {@link org.objectweb.asm.ClassVisitor ClassVisitor} used to visit
+ * classfile bytecode.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Map of the active {@link org.objectweb.asm.Label Label} instances for current method.
+ */
+ protected Map labels;
+
+ private static final String BASE = "class";
+
+ private final RuleSet RULES = new RuleSet();
+ {
+ RULES.add(BASE, new ClassRule());
+ RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
+ RULES.add(BASE + "/interfaces", new InterfacesRule());
+ RULES.add(BASE + "/outerclass", new OuterClassRule());
+ RULES.add(BASE + "/innerclass", new InnerClassRule());
+ RULES.add(BASE + "/source", new SourceRule());
+ RULES.add(BASE + "/field", new FieldRule());
+
+ RULES.add(BASE + "/method", new MethodRule());
+ RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
+ RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
+
+ RULES.add(BASE + "/method/annotationDefault",
+ new AnnotationDefaultRule());
+
+ RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
+
+ RULES.add(BASE + "/method/code/frame", new FrameRule());
+ RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
+ RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
+
+ RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
+ RULES.add(BASE + "/method/code/TABLESWITCH/label",
+ new TableSwitchLabelRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
+ new LookupSwitchLabelRule());
+
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
+ new InvokeDynamicBsmArgumentsRule());
+
+ RULES.add(BASE + "/method/code/Label", new LabelRule());
+ RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
+ RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
+ RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
+ RULES.add(BASE + "/method/code/Max", new MaxRule());
+
+ RULES.add("*/annotation", new AnnotationRule());
+ RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
+ RULES.add("*/annotationValue", new AnnotationValueRule());
+ RULES.add("*/annotationValueAnnotation",
+ new AnnotationValueAnnotationRule());
+ RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
+ RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
+ }
+
+ private static interface OpcodeGroup {
+ public static final int INSN = 0;
+ public static final int INSN_INT = 1;
+ public static final int INSN_VAR = 2;
+ public static final int INSN_TYPE = 3;
+ public static final int INSN_FIELD = 4;
+ public static final int INSN_METHOD = 5;
+ public static final int INSN_JUMP = 6;
+ public static final int INSN_LDC = 7;
+ public static final int INSN_IINC = 8;
+ public static final int INSN_MULTIANEWARRAY = 9;
+ }
+
+ /**
+ * Map of the opcode names to opcode and opcode group
+ */
+ static final HashMap OPCODES = new HashMap();
+ static {
+ addOpcode("NOP", NOP, OpcodeGroup.INSN);
+ addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
+ addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
+ addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
+ addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
+ addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
+ addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
+ addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
+ addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
+ addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
+ addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
+ addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
+ addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
+ addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
+ addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
+ addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
+ addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
+ addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
+ addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
+ addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
+ addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
+ addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
+ addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
+ addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
+ addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
+ addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
+ addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
+ addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
+ addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
+ addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
+ addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
+ addOpcode("POP", POP, OpcodeGroup.INSN);
+ addOpcode("POP2", POP2, OpcodeGroup.INSN);
+ addOpcode("DUP", DUP, OpcodeGroup.INSN);
+ addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
+ addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
+ addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
+ addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
+ addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
+ addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
+ addOpcode("IADD", IADD, OpcodeGroup.INSN);
+ addOpcode("LADD", LADD, OpcodeGroup.INSN);
+ addOpcode("FADD", FADD, OpcodeGroup.INSN);
+ addOpcode("DADD", DADD, OpcodeGroup.INSN);
+ addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
+ addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
+ addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
+ addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
+ addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
+ addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
+ addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
+ addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
+ addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
+ addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
+ addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
+ addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
+ addOpcode("IREM", IREM, OpcodeGroup.INSN);
+ addOpcode("LREM", LREM, OpcodeGroup.INSN);
+ addOpcode("FREM", FREM, OpcodeGroup.INSN);
+ addOpcode("DREM", DREM, OpcodeGroup.INSN);
+ addOpcode("INEG", INEG, OpcodeGroup.INSN);
+ addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
+ addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
+ addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
+ addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
+ addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
+ addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
+ addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
+ addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
+ addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
+ addOpcode("IAND", IAND, OpcodeGroup.INSN);
+ addOpcode("LAND", LAND, OpcodeGroup.INSN);
+ addOpcode("IOR", IOR, OpcodeGroup.INSN);
+ addOpcode("LOR", LOR, OpcodeGroup.INSN);
+ addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
+ addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
+ addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
+ addOpcode("I2L", I2L, OpcodeGroup.INSN);
+ addOpcode("I2F", I2F, OpcodeGroup.INSN);
+ addOpcode("I2D", I2D, OpcodeGroup.INSN);
+ addOpcode("L2I", L2I, OpcodeGroup.INSN);
+ addOpcode("L2F", L2F, OpcodeGroup.INSN);
+ addOpcode("L2D", L2D, OpcodeGroup.INSN);
+ addOpcode("F2I", F2I, OpcodeGroup.INSN);
+ addOpcode("F2L", F2L, OpcodeGroup.INSN);
+ addOpcode("F2D", F2D, OpcodeGroup.INSN);
+ addOpcode("D2I", D2I, OpcodeGroup.INSN);
+ addOpcode("D2L", D2L, OpcodeGroup.INSN);
+ addOpcode("D2F", D2F, OpcodeGroup.INSN);
+ addOpcode("I2B", I2B, OpcodeGroup.INSN);
+ addOpcode("I2C", I2C, OpcodeGroup.INSN);
+ addOpcode("I2S", I2S, OpcodeGroup.INSN);
+ addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
+ addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
+ addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
+ addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
+ addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
+ addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
+ addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
+ addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
+ addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
+ addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
+ addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
+ addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
+ addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
+ addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
+ addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
+ addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
+ addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
+ addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
+ addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
+ addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
+ addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
+ addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
+ addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
+ addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
+ addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
+ OpcodeGroup.INSN_MULTIANEWARRAY);
+ addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
+ }
+
+ private static void addOpcode(String operStr, int oper, int group) {
+ OPCODES.put(operStr, new Opcode(oper, group));
+ }
+
+ static final HashMap TYPES = new HashMap();
+ static {
+ String[] types = SAXCodeAdapter.TYPES;
+ for (int i = 0; i < types.length; i++) {
+ TYPES.put(types[i], new Integer(i));
+ }
+ }
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.xml.ASMContentHandler ASMContentHandler} object.
+ *
+ * @param cv
+ * class visitor that will be called to reconstruct the classfile
+ * using the XML stream.
+ */
+ public ASMContentHandler(final ClassVisitor cv) {
+ this.cv = cv;
+ }
+
+ /**
+ * Process notification of the start of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified name (with prefix), or the empty string if
+ * qualified names are not available.
+ * @param list
+ * - The attributes attached to the element. If there are no
+ * attributes, it shall be an empty Attributes object.
+ * @exception org.xml.sax.SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void startElement(final String ns, final String lName,
+ final String qName, final Attributes list) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Compute the current matching rule
+ StringBuffer sb = new StringBuffer(match);
+ if (match.length() > 0) {
+ sb.append('/');
+ }
+ sb.append(name);
+ match = sb.toString();
+
+ // Fire "begin" events for all relevant rules
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.begin(name, list);
+ }
+ }
+
+ /**
+ * Process notification of the end of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified XML 1.0 name (with prefix), or the empty
+ * string if qualified names are not available.
+ *
+ * @exception org.xml.sax.SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void endElement(final String ns, final String lName,
+ final String qName) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Fire "end" events for all relevant rules in reverse order
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.end(name);
+ }
+
+ // Recover the previous match expression
+ int slash = match.lastIndexOf('/');
+ if (slash >= 0) {
+ match = match.substring(0, slash);
+ } else {
+ match = "";
+ }
+ }
+
+ /**
+ * Return the top object on the stack without removing it. If there are no
+ * objects on the stack, return null.
+ *
+ * @return the top object on the stack without removing it.
+ */
+ final Object peek() {
+ int size = stack.size();
+ return size == 0 ? null : stack.get(size - 1);
+ }
+
+ /**
+ * Pop the top object off of the stack, and return it. If there are no
+ * objects on the stack, return null.
+ *
+ * @return the top object off of the stack.
+ */
+ final Object pop() {
+ int size = stack.size();
+ return size == 0 ? null : stack.remove(size - 1);
+ }
+
+ /**
+ * Push a new object onto the top of the object stack.
+ *
+ * @param object
+ * The new object
+ */
+ final void push(final Object object) {
+ stack.add(object);
+ }
+
+ static final class RuleSet {
+
+ private final HashMap rules = new HashMap();
+
+ private final ArrayList lpatterns = new ArrayList();
+
+ private final ArrayList rpatterns = new ArrayList();
+
+ public void add(final String path, final Object rule) {
+ String pattern = path;
+ if (path.startsWith("*/")) {
+ pattern = path.substring(1);
+ lpatterns.add(pattern);
+ } else if (path.endsWith("/*")) {
+ pattern = path.substring(0, path.length() - 1);
+ rpatterns.add(pattern);
+ }
+ rules.put(pattern, rule);
+ }
+
+ public Object match(final String path) {
+ if (rules.containsKey(path)) {
+ return rules.get(path);
+ }
+
+ int n = path.lastIndexOf('/');
+ for (Iterator it = lpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.substring(n).endsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ for (Iterator it = rpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.startsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Rule
+ */
+ protected abstract class Rule {
+
+ public void begin(final String name, final Attributes attrs)
+ throws SAXException {
+ }
+
+ public void end(final String name) {
+ }
+
+ protected final Object getValue(final String desc, final String val)
+ throws SAXException {
+ Object value = null;
+ if (val != null) {
+ if ("Ljava/lang/String;".equals(desc)) {
+ value = decode(val);
+ } else if ("Ljava/lang/Integer;".equals(desc)
+ || "I".equals(desc) || "S".equals(desc)
+ || "B".equals(desc) || "C".equals(desc)
+ || "Z".equals(desc)) {
+ value = new Integer(val);
+
+ } else if ("Ljava/lang/Short;".equals(desc)) {
+ value = new Short(val);
+
+ } else if ("Ljava/lang/Byte;".equals(desc)) {
+ value = new Byte(val);
+
+ } else if ("Ljava/lang/Character;".equals(desc)) {
+ value = new Character(decode(val).charAt(0));
+
+ } else if ("Ljava/lang/Boolean;".equals(desc)) {
+ value = Boolean.valueOf(val);
+
+ } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
+ value = new Long(val);
+ } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
+ value = new Float(val);
+ } else if ("Ljava/lang/Double;".equals(desc)
+ || "D".equals(desc)) {
+ value = new Double(val);
+ } else if (Type.getDescriptor(Type.class).equals(desc)) {
+ value = Type.getType(val);
+
+ } else if (Type.getDescriptor(Handle.class).equals(desc)) {
+ value = decodeHandle(val);
+
+ } else {
+ // TODO use of default toString().
+ throw new SAXException("Invalid value:" + val + " desc:"
+ + desc + " ctx:" + this);
+ }
+ }
+ return value;
+ }
+
+ Handle decodeHandle(final String val) throws SAXException {
+ try {
+ int dotIndex = val.indexOf('.');
+ int descIndex = val.indexOf('(', dotIndex + 1);
+ int tagIndex = val.lastIndexOf('(');
+
+ int tag = Integer.parseInt(val.substring(tagIndex + 1,
+ val.length() - 1));
+ String owner = val.substring(0, dotIndex);
+ String name = val.substring(dotIndex + 1, descIndex);
+ String desc = val.substring(descIndex, tagIndex - 1);
+ return new Handle(tag, owner, name, desc);
+
+ } catch (RuntimeException e) {
+ throw new SAXException("Malformed handle " + val, e);
+ }
+ }
+
+ private final String decode(final String val) throws SAXException {
+ StringBuffer sb = new StringBuffer(val.length());
+ try {
+ int n = 0;
+ while (n < val.length()) {
+ char c = val.charAt(n);
+ if (c == '\\') {
+ n++;
+ c = val.charAt(n);
+ if (c == '\\') {
+ sb.append('\\');
+ } else {
+ n++; // skip 'u'
+ sb.append((char) Integer.parseInt(
+ val.substring(n, n + 4), 16));
+ n += 3;
+ }
+ } else {
+ sb.append(c);
+ }
+ n++;
+ }
+
+ } catch (RuntimeException ex) {
+ throw new SAXException(ex);
+ }
+ return sb.toString();
+ }
+
+ protected final Label getLabel(final Object label) {
+ Label lbl = labels.get(label);
+ if (lbl == null) {
+ lbl = new Label();
+ labels.put(label, lbl);
+ }
+ return lbl;
+ }
+
+ // TODO verify move to stack
+ protected final MethodVisitor getCodeVisitor() {
+ return (MethodVisitor) peek();
+ }
+
+ protected final int getAccess(final String s) {
+ int access = 0;
+ if (s.indexOf("public") != -1) {
+ access |= ACC_PUBLIC;
+ }
+ if (s.indexOf("private") != -1) {
+ access |= ACC_PRIVATE;
+ }
+ if (s.indexOf("protected") != -1) {
+ access |= ACC_PROTECTED;
+ }
+ if (s.indexOf("static") != -1) {
+ access |= ACC_STATIC;
+ }
+ if (s.indexOf("final") != -1) {
+ access |= ACC_FINAL;
+ }
+ if (s.indexOf("super") != -1) {
+ access |= ACC_SUPER;
+ }
+ if (s.indexOf("synchronized") != -1) {
+ access |= ACC_SYNCHRONIZED;
+ }
+ if (s.indexOf("volatile") != -1) {
+ access |= ACC_VOLATILE;
+ }
+ if (s.indexOf("bridge") != -1) {
+ access |= ACC_BRIDGE;
+ }
+ if (s.indexOf("varargs") != -1) {
+ access |= ACC_VARARGS;
+ }
+ if (s.indexOf("transient") != -1) {
+ access |= ACC_TRANSIENT;
+ }
+ if (s.indexOf("native") != -1) {
+ access |= ACC_NATIVE;
+ }
+ if (s.indexOf("interface") != -1) {
+ access |= ACC_INTERFACE;
+ }
+ if (s.indexOf("abstract") != -1) {
+ access |= ACC_ABSTRACT;
+ }
+ if (s.indexOf("strict") != -1) {
+ access |= ACC_STRICT;
+ }
+ if (s.indexOf("synthetic") != -1) {
+ access |= ACC_SYNTHETIC;
+ }
+ if (s.indexOf("annotation") != -1) {
+ access |= ACC_ANNOTATION;
+ }
+ if (s.indexOf("enum") != -1) {
+ access |= ACC_ENUM;
+ }
+ if (s.indexOf("deprecated") != -1) {
+ access |= ACC_DEPRECATED;
+ }
+ return access;
+ }
+ }
+
+ /**
+ * ClassRule
+ */
+ final class ClassRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int major = Integer.parseInt(attrs.getValue("major"));
+ int minor = Integer.parseInt(attrs.getValue("minor"));
+ HashMap vals = new HashMap();
+ vals.put("version", new Integer(minor << 16 | major));
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("parent", attrs.getValue("parent"));
+ vals.put("source", attrs.getValue("source"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("interfaces", new ArrayList());
+ push(vals);
+ // values will be extracted in InterfacesRule.end();
+ }
+ }
+
+ final class SourceRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String file = attrs.getValue("file");
+ String debug = attrs.getValue("debug");
+ cv.visitSource(file, debug);
+ }
+ }
+
+ /**
+ * InterfaceRule
+ */
+ final class InterfaceRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList) ((HashMap, ?>) peek()).get("interfaces"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * InterfacesRule
+ */
+ final class InterfacesRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap, ?> vals = (HashMap, ?>) pop();
+ int version = ((Integer) vals.get("version")).intValue();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String signature = (String) vals.get("signature");
+ String parent = (String) vals.get("parent");
+ ArrayList> infs = (ArrayList>) vals.get("interfaces");
+ String[] interfaces = infs.toArray(new String[infs.size()]);
+ cv.visit(version, access, name, signature, parent, interfaces);
+ push(cv);
+ }
+ }
+
+ /**
+ * OuterClassRule
+ */
+ final class OuterClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String owner = attrs.getValue("owner");
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ /**
+ * InnerClassRule
+ */
+ final class InnerClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String outerName = attrs.getValue("outerName");
+ String innerName = attrs.getValue("innerName");
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ /**
+ * FieldRule
+ */
+ final class FieldRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String signature = attrs.getValue("signature");
+ String desc = attrs.getValue("desc");
+ Object value = getValue(desc, attrs.getValue("value"));
+ push(cv.visitField(access, name, desc, signature, value));
+ }
+
+ @Override
+ public void end(final String name) {
+ ((FieldVisitor) pop()).visitEnd();
+ }
+ }
+
+ /**
+ * MethodRule
+ */
+ final class MethodRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ labels = new HashMap();
+ HashMap vals = new HashMap();
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("desc", attrs.getValue("desc"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("exceptions", new ArrayList());
+ push(vals);
+ // values will be extracted in ExceptionsRule.end();
+ }
+
+ @Override
+ public final void end(final String name) {
+ ((MethodVisitor) pop()).visitEnd();
+ labels = null;
+ }
+ }
+
+ /**
+ * ExceptionRule
+ */
+ final class ExceptionRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList) ((HashMap, ?>) peek()).get("exceptions"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * ExceptionsRule
+ */
+ final class ExceptionsRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap, ?> vals = (HashMap, ?>) pop();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String desc = (String) vals.get("desc");
+ String signature = (String) vals.get("signature");
+ ArrayList> excs = (ArrayList>) vals.get("exceptions");
+ String[] exceptions = excs.toArray(new String[excs.size()]);
+
+ push(cv.visitMethod(access, name, desc, signature, exceptions));
+ }
+ }
+
+ /**
+ * TableSwitchRule
+ */
+ final class TableSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap vals = new HashMap();
+ vals.put("min", attrs.getValue("min"));
+ vals.put("max", attrs.getValue("max"));
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap, ?> vals = (HashMap, ?>) pop();
+ int min = Integer.parseInt((String) vals.get("min"));
+ int max = Integer.parseInt((String) vals.get("max"));
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList> lbls = (ArrayList>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * TableSwitchLabelRule
+ */
+ final class TableSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList) ((HashMap, ?>) peek()).get("labels"))
+ .add(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * LookupSwitchRule
+ */
+ final class LookupSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap vals = new HashMap();
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList());
+ vals.put("keys", new ArrayList());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap, ?> vals = (HashMap, ?>) pop();
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList keyList = (ArrayList) vals.get("keys");
+ ArrayList> lbls = (ArrayList>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ int[] keys = new int[keyList.size()];
+ for (int i = 0; i < keys.length; i++) {
+ keys[i] = Integer.parseInt(keyList.get(i));
+ }
+ getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * LookupSwitchLabelRule
+ */
+ final class LookupSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap, ?> vals = (HashMap, ?>) peek();
+ ((ArrayList) vals.get("labels")).add(getLabel(attrs
+ .getValue("name")));
+ ((ArrayList) vals.get("keys")).add(attrs.getValue("key"));
+ }
+ }
+
+ /**
+ * FrameRule
+ */
+ final class FrameRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ HashMap typeLists = new HashMap();
+ typeLists.put("local", new ArrayList());
+ typeLists.put("stack", new ArrayList());
+ push(attrs.getValue("type"));
+ push(attrs.getValue("count") == null ? "0" : attrs
+ .getValue("count"));
+ push(typeLists);
+ }
+
+ @Override
+ public void end(final String name) {
+ HashMap, ?> typeLists = (HashMap, ?>) pop();
+ ArrayList> locals = (ArrayList>) typeLists.get("local");
+ int nLocal = locals.size();
+ Object[] local = locals.toArray();
+ ArrayList> stacks = (ArrayList>) typeLists.get("stack");
+ int nStack = stacks.size();
+ Object[] stack = stacks.toArray();
+ String count = (String) pop();
+ String type = (String) pop();
+ if ("NEW".equals(type)) {
+ getCodeVisitor()
+ .visitFrame(F_NEW, nLocal, local, nStack, stack);
+ } else if ("FULL".equals(type)) {
+ getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
+ stack);
+ } else if ("APPEND".equals(type)) {
+ getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
+ } else if ("CHOP".equals(type)) {
+ getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
+ null, 0, null);
+ } else if ("SAME".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
+ } else if ("SAME1".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
+ }
+ }
+ }
+
+ final class FrameTypeRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ ArrayList types = (ArrayList) ((HashMap, ?>) peek())
+ .get(name);
+ String type = attrs.getValue("type");
+ if ("uninitialized".equals(type)) {
+ types.add(getLabel(attrs.getValue("label")));
+ } else {
+ Integer t = TYPES.get(type);
+ if (t == null) {
+ types.add(type);
+ } else {
+ types.add(t);
+ }
+ }
+ }
+ }
+
+ /**
+ * LabelRule
+ */
+ final class LabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * TryCatchRule
+ */
+ final class TryCatchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ Label handler = getLabel(attrs.getValue("handler"));
+ String type = attrs.getValue("type");
+ getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * LineNumberRule
+ */
+ final class LineNumberRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int line = Integer.parseInt(attrs.getValue("line"));
+ Label start = getLabel(attrs.getValue("start"));
+ getCodeVisitor().visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * LocalVarRule
+ */
+ final class LocalVarRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ String signature = attrs.getValue("signature");
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ int var = Integer.parseInt(attrs.getValue("var"));
+ getCodeVisitor().visitLocalVariable(name, desc, signature, start,
+ end, var);
+ }
+ }
+
+ /**
+ * InvokeDynamicRule
+ */
+ final class InvokeDynamicRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ push(attrs.getValue("name"));
+ push(attrs.getValue("desc"));
+ push(decodeHandle(attrs.getValue("bsm")));
+ push(new ArrayList());
+ }
+
+ @Override
+ public final void end(final String element) {
+ ArrayList> bsmArgs = (ArrayList>) pop();
+ Handle bsm = (Handle) pop();
+ String desc = (String) pop();
+ String name = (String) pop();
+ getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
+ bsmArgs.toArray());
+ }
+ }
+
+ /**
+ * InvokeDynamicBsmArgumentsRule
+ */
+ final class InvokeDynamicBsmArgumentsRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ ArrayList bsmArgs = (ArrayList) peek();
+ bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
+ }
+ }
+
+ /**
+ * OpcodesRule
+ */
+ final class OpcodesRule extends Rule {
+
+ // public boolean match( String match, String element) {
+ // return match.startsWith( path) && OPCODES.containsKey( element);
+ // }
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ Opcode o = OPCODES.get(element);
+ if (o == null) {
+ throw new SAXException("Invalid element: " + element + " at "
+ + match);
+ }
+
+ switch (o.type) {
+ case OpcodeGroup.INSN:
+ getCodeVisitor().visitInsn(o.opcode);
+ break;
+
+ case OpcodeGroup.INSN_FIELD:
+ getCodeVisitor().visitFieldInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_INT:
+ getCodeVisitor().visitIntInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("value")));
+ break;
+
+ case OpcodeGroup.INSN_JUMP:
+ getCodeVisitor().visitJumpInsn(o.opcode,
+ getLabel(attrs.getValue("label")));
+ break;
+
+ case OpcodeGroup.INSN_METHOD:
+ getCodeVisitor().visitMethodInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_TYPE:
+ getCodeVisitor()
+ .visitTypeInsn(o.opcode, attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_VAR:
+ getCodeVisitor().visitVarInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("var")));
+ break;
+
+ case OpcodeGroup.INSN_IINC:
+ getCodeVisitor().visitIincInsn(
+ Integer.parseInt(attrs.getValue("var")),
+ Integer.parseInt(attrs.getValue("inc")));
+ break;
+
+ case OpcodeGroup.INSN_LDC:
+ getCodeVisitor()
+ .visitLdcInsn(
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("cst")));
+ break;
+
+ case OpcodeGroup.INSN_MULTIANEWARRAY:
+ getCodeVisitor().visitMultiANewArrayInsn(
+ attrs.getValue("desc"),
+ Integer.parseInt(attrs.getValue("dims")));
+ break;
+
+ default:
+ throw new Error("Internal error");
+
+ }
+ }
+ }
+
+ /**
+ * MaxRule
+ */
+ final class MaxRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
+ int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
+ getCodeVisitor().visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ final class AnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ Object v = peek();
+ if (v instanceof ClassVisitor) {
+ push(((ClassVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof FieldVisitor) {
+ push(((FieldVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof MethodVisitor) {
+ push(((MethodVisitor) v).visitAnnotation(desc, visible));
+ }
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationParameterRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ int parameter = Integer.parseInt(attrs.getValue("parameter"));
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
+ desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs)
+ throws SAXException {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visit(
+ attrs.getValue("name"),
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("value")));
+ }
+ }
+ }
+
+ final class AnnotationValueEnumRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
+ attrs.getValue("value"));
+ }
+ }
+ }
+
+ final class AnnotationValueAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
+ attrs.getValue("desc")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueArrayRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitArray(attrs.getValue("name")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationDefaultRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ MethodVisitor av = (MethodVisitor) peek();
+ push(av == null ? null : av.visitAnnotationDefault());
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ /**
+ * Opcode
+ */
+ static final class Opcode {
+
+ public final int opcode;
+
+ public final int type;
+
+ Opcode(final int opcode, final int type) {
+ this.opcode = opcode;
+ this.type = type;
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/Processor.java b/parabotv2/src/org/objectweb/asm/xml/Processor.java
new file mode 100644
index 0000000..a50ffca
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/Processor.java
@@ -0,0 +1,1044 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamSource;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Processor is a command line tool that can be used for bytecode waving
+ * directed by XSL transformation.
+ *
+ * In order to use a concrete XSLT engine, system property
+ * javax.xml.transform.TransformerFactory must be set to one of the
+ * following values.
+ *
+ *
+ *
+ *
+ * jd.xslt
+ * jd.xml.xslt.trax.TransformerFactoryImpl
+ *
+ *
+ *
+ * Saxon
+ * net.sf.saxon.TransformerFactoryImpl
+ *
+ *
+ *
+ * Caucho
+ * com.caucho.xsl.Xsl
+ *
+ *
+ *
+ * Xalan interpeter
+ * org.apache.xalan.processor.TransformerFactory
+ *
+ *
+ *
+ * Xalan xsltc
+ * org.apache.xalan.xsltc.trax.TransformerFactoryImpl
+ *
+ *
+ *
+ *
+ * @author Eugene Kuleshov
+ */
+public class Processor {
+
+ public static final int BYTECODE = 1;
+
+ public static final int MULTI_XML = 2;
+
+ public static final int SINGLE_XML = 3;
+
+ private static final String SINGLE_XML_NAME = "classes.xml";
+
+ private final int inRepresentation;
+
+ private final int outRepresentation;
+
+ private final InputStream input;
+
+ private final OutputStream output;
+
+ private final Source xslt;
+
+ private int n = 0;
+
+ public Processor(final int inRepresenation, final int outRepresentation,
+ final InputStream input, final OutputStream output,
+ final Source xslt) {
+ this.inRepresentation = inRepresenation;
+ this.outRepresentation = outRepresentation;
+ this.input = input;
+ this.output = output;
+ this.xslt = xslt;
+ }
+
+ public int process() throws TransformerException, IOException, SAXException {
+ ZipInputStream zis = new ZipInputStream(input);
+ final ZipOutputStream zos = new ZipOutputStream(output);
+ final OutputStreamWriter osw = new OutputStreamWriter(zos);
+
+ Thread.currentThread().setContextClassLoader(
+ getClass().getClassLoader());
+
+ TransformerFactory tf = TransformerFactory.newInstance();
+ if (!tf.getFeature(SAXSource.FEATURE)
+ || !tf.getFeature(SAXResult.FEATURE)) {
+ return 0;
+ }
+
+ SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
+ Templates templates = null;
+ if (xslt != null) {
+ templates = saxtf.newTemplates(xslt);
+ }
+
+ // configuring outHandlerFactory
+ // ///////////////////////////////////////////////////////
+
+ EntryElement entryElement = getEntryElement(zos);
+
+ ContentHandler outDocHandler = null;
+ switch (outRepresentation) {
+ case BYTECODE:
+ outDocHandler = new OutputSlicingHandler(
+ new ASMContentHandlerFactory(zos), entryElement, false);
+ break;
+
+ case MULTI_XML:
+ outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
+ true), entryElement, true);
+ break;
+
+ case SINGLE_XML:
+ ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
+ zos.putNextEntry(outputEntry);
+ outDocHandler = new SAXWriter(osw, false);
+ break;
+
+ }
+
+ // configuring inputDocHandlerFactory
+ // /////////////////////////////////////////////////
+ ContentHandler inDocHandler;
+ if (templates == null) {
+ inDocHandler = outDocHandler;
+ } else {
+ inDocHandler = new InputSlicingHandler("class", outDocHandler,
+ new TransformerHandlerFactory(saxtf, templates,
+ outDocHandler));
+ }
+ ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
+ inDocHandler);
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.startDocument();
+ inDocHandler.startElement("", "classes", "classes",
+ new AttributesImpl());
+ }
+
+ int i = 0;
+ ZipEntry ze;
+ while ((ze = zis.getNextEntry()) != null) {
+ update(ze.getName(), n++);
+ if (isClassEntry(ze)) {
+ processEntry(zis, ze, inDocHandlerFactory);
+ } else {
+ OutputStream os = entryElement.openEntry(getName(ze));
+ copyEntry(zis, os);
+ entryElement.closeEntry();
+ }
+
+ i++;
+ }
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.endElement("", "classes", "classes");
+ inDocHandler.endDocument();
+ }
+
+ if (outRepresentation == SINGLE_XML) {
+ zos.closeEntry();
+ }
+ zos.flush();
+ zos.close();
+
+ return i;
+ }
+
+ private void copyEntry(final InputStream is, final OutputStream os)
+ throws IOException {
+ if (outRepresentation == SINGLE_XML) {
+ return;
+ }
+
+ byte[] buff = new byte[2048];
+ int i;
+ while ((i = is.read(buff)) != -1) {
+ os.write(buff, 0, i);
+ }
+ }
+
+ private boolean isClassEntry(final ZipEntry ze) {
+ String name = ze.getName();
+ return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
+ || name.endsWith(".class") || name.endsWith(".class.xml");
+ }
+
+ private void processEntry(final ZipInputStream zis, final ZipEntry ze,
+ final ContentHandlerFactory handlerFactory) {
+ ContentHandler handler = handlerFactory.createContentHandler();
+ try {
+
+ // if (CODE2ASM.equals(command)) { // read bytecode and process it
+ // // with TraceClassVisitor
+ // ClassReader cr = new ClassReader(readEntry(zis, ze));
+ // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
+ // false);
+ // }
+
+ boolean singleInputDocument = inRepresentation == SINGLE_XML;
+ if (inRepresentation == BYTECODE) { // read bytecode and process it
+ // with handler
+ ClassReader cr = new ClassReader(readEntry(zis, ze));
+ cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
+
+ } else { // read XML and process it with handler
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(
+ singleInputDocument ? (InputStream) new ProtectedInputStream(
+ zis) : new ByteArrayInputStream(readEntry(zis,
+ ze))));
+
+ }
+ } catch (Exception ex) {
+ update(ze.getName(), 0);
+ update(ex, 0);
+ }
+ }
+
+ private EntryElement getEntryElement(final ZipOutputStream zos) {
+ if (outRepresentation == SINGLE_XML) {
+ return new SingleDocElement(zos);
+ }
+ return new ZipEntryElement(zos);
+ }
+
+ // private ContentHandlerFactory getHandlerFactory(
+ // OutputStream os,
+ // SAXTransformerFactory saxtf,
+ // Templates templates)
+ // {
+ // ContentHandlerFactory factory = null;
+ // if (templates == null) {
+ // if (outputRepresentation == BYTECODE) { // factory used to write
+ // // bytecode
+ // factory = new ASMContentHandlerFactory(os, computeMax);
+ // } else { // factory used to write XML
+ // factory = new SAXWriterFactory(os, true);
+ // }
+ // } else {
+ // if (outputRepresentation == BYTECODE) { // factory used to transform
+ // // and then write bytecode
+ // factory = new ASMTransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // computeMax);
+ // } else { // factory used to transformand then write XML
+ // factory = new TransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // outputRepresentation == SINGLE_XML);
+ // }
+ // }
+ // return factory;
+ // }
+
+ private String getName(final ZipEntry ze) {
+ String name = ze.getName();
+ if (isClassEntry(ze)) {
+ if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
+ name = name.substring(0, name.length() - 4); // .class.xml to
+ // .class
+ } else if (inRepresentation == BYTECODE
+ && outRepresentation != BYTECODE) {
+ name += ".xml"; // .class to .class.xml
+ }
+ // } else if( CODE2ASM.equals( command)) {
+ // name = name.substring( 0, name.length()-6).concat( ".asm");
+ }
+ return name;
+ }
+
+ private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
+ throws IOException {
+ long size = ze.getSize();
+ if (size > -1) {
+ byte[] buff = new byte[(int) size];
+ int k = 0;
+ int n;
+ while ((n = zis.read(buff, k, buff.length - k)) > 0) {
+ k += n;
+ }
+ return buff;
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buff = new byte[4096];
+ int i;
+ while ((i = zis.read(buff)) != -1) {
+ bos.write(buff, 0, i);
+ }
+ return bos.toByteArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+ */
+ protected void update(final Object arg, final int n) {
+ if (arg instanceof Throwable) {
+ ((Throwable) arg).printStackTrace();
+ } else {
+ if (n % 100 == 0) {
+ System.err.println(n + " " + arg);
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ if (args.length < 2) {
+ showUsage();
+ return;
+ }
+
+ int inRepresentation = getRepresentation(args[0]);
+ int outRepresentation = getRepresentation(args[1]);
+
+ InputStream is = System.in;
+ OutputStream os = new BufferedOutputStream(System.out);
+
+ Source xslt = null;
+ // boolean computeMax = true;
+
+ for (int i = 2; i < args.length; i++) {
+ if ("-in".equals(args[i])) {
+ is = new FileInputStream(args[++i]);
+
+ } else if ("-out".equals(args[i])) {
+ os = new BufferedOutputStream(new FileOutputStream(args[++i]));
+
+ } else if ("-xslt".equals(args[i])) {
+ xslt = new StreamSource(new FileInputStream(args[++i]));
+
+ // } else if( "-computemax".equals( args[ i].toLowerCase())) {
+ // computeMax = true;
+
+ } else {
+ showUsage();
+ return;
+
+ }
+ }
+
+ if (inRepresentation == 0 || outRepresentation == 0) {
+ showUsage();
+ return;
+ }
+
+ Processor m = new Processor(inRepresentation, outRepresentation, is,
+ os, xslt);
+
+ long l1 = System.currentTimeMillis();
+ int n = m.process();
+ long l2 = System.currentTimeMillis();
+ System.err.println(n);
+ System.err.println((l2 - l1) + "ms " + 1000f * n / (l2 - l1)
+ + " resources/sec");
+ }
+
+ private static int getRepresentation(final String s) {
+ if ("code".equals(s)) {
+ return BYTECODE;
+ } else if ("xml".equals(s)) {
+ return MULTI_XML;
+ } else if ("singlexml".equals(s)) {
+ return SINGLE_XML;
+ }
+ return 0;
+ }
+
+ private static void showUsage() {
+ System.err
+ .println("Usage: Main [-in ] [-out ] [-xslt ]");
+ System.err
+ .println(" when -in or -out is omitted sysin and sysout would be used");
+ System.err
+ .println(" and - code | xml | singlexml");
+ }
+
+ /**
+ * IputStream wrapper class used to protect input streams from being closed
+ * by some stupid XML parsers.
+ */
+ private static final class ProtectedInputStream extends InputStream {
+ private final InputStream is;
+
+ ProtectedInputStream(final InputStream is) {
+ this.is = is;
+ }
+
+ @Override
+ public final void close() throws IOException {
+ }
+
+ @Override
+ public final int read() throws IOException {
+ return is.read();
+ }
+
+ @Override
+ public final int read(final byte[] b, final int off, final int len)
+ throws IOException {
+ return is.read(b, off, len);
+ }
+
+ @Override
+ public final int available() throws IOException {
+ return is.available();
+ }
+ }
+
+ /**
+ * A {@link org.objectweb.asm.xml.Processor.ContentHandlerFactory ContentHandlerFactory} is used to create
+ * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
+ * context.
+ */
+ private static interface ContentHandlerFactory {
+
+ /**
+ * Creates an instance of the content handler.
+ *
+ * @return content handler
+ */
+ ContentHandler createContentHandler();
+
+ }
+
+ /**
+ * SAXWriterFactory
+ */
+ private static final class SAXWriterFactory implements
+ ContentHandlerFactory {
+ private final Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return new SAXWriter(w, optimizeEmptyElements);
+ }
+
+ }
+
+ /**
+ * ASMContentHandlerFactory
+ */
+ private static final class ASMContentHandlerFactory implements
+ ContentHandlerFactory {
+ final OutputStream os;
+
+ ASMContentHandlerFactory(final OutputStream os) {
+ this.os = os;
+ }
+
+ public final ContentHandler createContentHandler() {
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ return new ASMContentHandler(cw) {
+ @Override
+ public void endDocument() throws SAXException {
+ try {
+ os.write(cw.toByteArray());
+ } catch (IOException e) {
+ throw new SAXException(e);
+ }
+ }
+ };
+ }
+
+ }
+
+ /**
+ * TransformerHandlerFactory
+ */
+ private static final class TransformerHandlerFactory implements
+ ContentHandlerFactory {
+ private SAXTransformerFactory saxtf;
+
+ private final Templates templates;
+
+ private ContentHandler outputHandler;
+
+ TransformerHandlerFactory(final SAXTransformerFactory saxtf,
+ final Templates templates, final ContentHandler outputHandler) {
+ this.saxtf = saxtf;
+ this.templates = templates;
+ this.outputHandler = outputHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ try {
+ TransformerHandler handler = saxtf
+ .newTransformerHandler(templates);
+ handler.setResult(new SAXResult(outputHandler));
+ return handler;
+ } catch (TransformerConfigurationException ex) {
+ throw new RuntimeException(ex.toString());
+ }
+ }
+ }
+
+ /**
+ * SubdocumentHandlerFactory
+ */
+ private static final class SubdocumentHandlerFactory implements
+ ContentHandlerFactory {
+ private final ContentHandler subdocumentHandler;
+
+ SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
+ this.subdocumentHandler = subdocumentHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return subdocumentHandler;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} and
+ * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
+ * from SAX 2.0 events into {@link java.io.Writer Writer}.
+ *
+ * This implementation does not support namespaces, entity
+ * definitions (uncluding DTD), CDATA and text elements.
+ */
+ private static final class SAXWriter extends DefaultHandler implements
+ LexicalHandler {
+ private static final char[] OFF = " "
+ .toCharArray();
+
+ private Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ private boolean openElement = false;
+
+ private int ident = 0;
+
+ /**
+ * Creates SAXWriter.
+ *
+ * @param w
+ * writer
+ * @param optimizeEmptyElements
+ * if set to true, short XML syntax will be used
+ * for empty elements
+ */
+ SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ @Override
+ public final void startElement(final String ns, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write('<' + qName);
+ if (atts != null && atts.getLength() > 0) {
+ writeAttributes(atts);
+ }
+
+ if (optimizeEmptyElements) {
+ openElement = true;
+ } else {
+ w.write(">\n");
+ }
+ ident += 2;
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endElement(final String ns, final String localName,
+ final String qName) throws SAXException {
+ ident -= 2;
+ try {
+ if (openElement) {
+ w.write("/>\n");
+ openElement = false;
+ } else {
+ writeIdent();
+ w.write("" + qName + ">\n");
+ }
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ try {
+ w.flush();
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void comment(final char[] ch, final int off, final int len)
+ throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write("\n");
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void startDTD(final String arg0, final String arg1,
+ final String arg2) throws SAXException {
+ }
+
+ public final void endDTD() throws SAXException {
+ }
+
+ public final void startEntity(final String arg0) throws SAXException {
+ }
+
+ public final void endEntity(final String arg0) throws SAXException {
+ }
+
+ public final void startCDATA() throws SAXException {
+ }
+
+ public final void endCDATA() throws SAXException {
+ }
+
+ private final void writeAttributes(final Attributes atts)
+ throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int len = atts.getLength();
+ for (int i = 0; i < len; i++) {
+ sb.append(' ').append(atts.getLocalName(i)).append("=\"")
+ .append(esc(atts.getValue(i))).append('\"');
+ }
+ w.write(sb.toString());
+ }
+
+ /**
+ * Encode string with escaping.
+ *
+ * @param str
+ * string to encode.
+ * @return encoded string
+ */
+ private static final String esc(final String str) {
+ StringBuffer sb = new StringBuffer(str.length());
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '&':
+ sb.append("&");
+ break;
+
+ case '<':
+ sb.append("<");
+ break;
+
+ case '>':
+ sb.append(">");
+ break;
+
+ case '\"':
+ sb.append(""");
+ break;
+
+ default:
+ if (ch > 0x7f) {
+ sb.append("").append(Integer.toString(ch))
+ .append(';');
+ } else {
+ sb.append(ch);
+ }
+
+ }
+ }
+ return sb.toString();
+ }
+
+ private final void writeIdent() throws IOException {
+ int n = ident;
+ while (n > 0) {
+ if (n > OFF.length) {
+ w.write(OFF);
+ n -= OFF.length;
+ } else {
+ w.write(OFF, 0, n);
+ n = 0;
+ }
+ }
+ }
+
+ private final void closeElement() throws IOException {
+ if (openElement) {
+ w.write(">\n");
+ }
+ openElement = false;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ *
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class InputSlicingHandler extends DefaultHandler {
+ private String subdocumentRoot;
+
+ private final ContentHandler rootHandler;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.xml.Processor.InputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentRoot
+ * name/path to the root element of the subdocument
+ * @param rootHandler
+ * content handler for the entire document (subdocument
+ * envelope).
+ * @param subdocumentHandlerFactory
+ * a {@link org.objectweb.asm.xml.Processor.ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link org.xml.sax.ContentHandler ContentHandler} instances
+ * for subdocuments.
+ */
+ InputSlicingHandler(final String subdocumentRoot,
+ final ContentHandler rootHandler,
+ final ContentHandlerFactory subdocumentHandlerFactory) {
+ this.subdocumentRoot = subdocumentRoot;
+ this.rootHandler = rootHandler;
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ } else if (rootHandler != null) {
+ rootHandler.startElement(namespaceURI, localName, qName, list);
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ }
+ } else if (rootHandler != null) {
+ rootHandler.endElement(namespaceURI, localName, qName);
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.startDocument();
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.endDocument();
+
+ }
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ } else if (rootHandler != null) {
+ rootHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ *
+ *
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class OutputSlicingHandler extends DefaultHandler {
+ private final String subdocumentRoot;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private final EntryElement entryElement;
+
+ private boolean isXml;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.xml.Processor.OutputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentHandlerFactory
+ * a {@link org.objectweb.asm.xml.Processor.ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link org.xml.sax.ContentHandler ContentHandler} instances
+ * for subdocuments.
+ * @param entryElement
+ * TODO.
+ * @param isXml
+ * TODO.
+ */
+ OutputSlicingHandler(
+ final ContentHandlerFactory subdocumentHandlerFactory,
+ final EntryElement entryElement, final boolean isXml) {
+ this.subdocumentRoot = "class";
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ this.entryElement = entryElement;
+ this.isXml = isXml;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ String name = list.getValue("name");
+ if (name == null || name.length() == 0) {
+ throw new SAXException(
+ "Class element without name attribute.");
+ }
+ try {
+ entryElement.openEntry(isXml ? name + ".class.xml" : name
+ + ".class");
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ try {
+ entryElement.closeEntry();
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ }
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ private static interface EntryElement {
+
+ OutputStream openEntry(String name) throws IOException;
+
+ void closeEntry() throws IOException;
+
+ }
+
+ private static final class SingleDocElement implements EntryElement {
+ private final OutputStream os;
+
+ SingleDocElement(final OutputStream os) {
+ this.os = os;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ return os;
+ }
+
+ public void closeEntry() throws IOException {
+ os.flush();
+ }
+
+ }
+
+ private static final class ZipEntryElement implements EntryElement {
+ private ZipOutputStream zos;
+
+ ZipEntryElement(final ZipOutputStream zos) {
+ this.zos = zos;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ ZipEntry entry = new ZipEntry(name);
+ zos.putNextEntry(entry);
+ return zos;
+ }
+
+ public void closeEntry() throws IOException {
+ zos.flush();
+ zos.closeEntry();
+ }
+
+ }
+
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/SAXAdapter.java b/parabotv2/src/org/objectweb/asm/xml/SAXAdapter.java
new file mode 100644
index 0000000..0e291ec
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/SAXAdapter.java
@@ -0,0 +1,89 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * SAXAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public class SAXAdapter {
+
+ private final ContentHandler h;
+
+ protected SAXAdapter(final ContentHandler h) {
+ this.h = h;
+ }
+
+ protected ContentHandler getContentHandler() {
+ return h;
+ }
+
+ protected void addDocumentStart() {
+ try {
+ h.startDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected void addDocumentEnd() {
+ try {
+ h.endDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addStart(final String name, final Attributes attrs) {
+ try {
+ h.startElement("", name, name, attrs);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addEnd(final String name) {
+ try {
+ h.endElement("", name, name);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addElement(final String name, final Attributes attrs) {
+ addStart(name, attrs);
+ addEnd(name);
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/SAXAnnotationAdapter.java b/parabotv2/src/org/objectweb/asm/xml/SAXAnnotationAdapter.java
new file mode 100644
index 0000000..a3aebe4
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/SAXAnnotationAdapter.java
@@ -0,0 +1,185 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * SAXAnnotationAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXAnnotationAdapter extends AnnotationVisitor {
+
+ SAXAdapter sa;
+
+ private final String elementName;
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc) {
+ this(Opcodes.ASM4, sa, elementName, visible, desc, name, -1);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final int parameter, final String desc) {
+ this(Opcodes.ASM4, sa, elementName, visible, desc, null, parameter);
+ }
+
+ protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+ final String elementName, final int visible, final String desc,
+ final String name, final int parameter) {
+ super(api);
+ this.sa = sa;
+ this.elementName = elementName;
+
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (visible != 0) {
+ att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
+ : "false");
+ }
+ if (parameter != -1) {
+ att.addAttribute("", "parameter", "parameter", "",
+ Integer.toString(parameter));
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+
+ sa.addStart(elementName, att);
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ Class> c = value.getClass();
+ if (c.isArray()) {
+ AnnotationVisitor av = visitArray(name);
+ if (value instanceof byte[]) {
+ byte[] b = (byte[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Byte(b[i]));
+ }
+
+ } else if (value instanceof char[]) {
+ char[] b = (char[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Character(b[i]));
+ }
+
+ } else if (value instanceof short[]) {
+ short[] b = (short[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Short(b[i]));
+ }
+
+ } else if (value instanceof boolean[]) {
+ boolean[] b = (boolean[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, Boolean.valueOf(b[i]));
+ }
+
+ } else if (value instanceof int[]) {
+ int[] b = (int[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Integer(b[i]));
+ }
+
+ } else if (value instanceof long[]) {
+ long[] b = (long[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Long(b[i]));
+ }
+
+ } else if (value instanceof float[]) {
+ float[] b = (float[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Float(b[i]));
+ }
+
+ } else if (value instanceof double[]) {
+ double[] b = (double[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Double(b[i]));
+ }
+
+ }
+ av.visitEnd();
+ } else {
+ addValueElement("annotationValue", name, Type.getDescriptor(c),
+ value.toString());
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ addValueElement("annotationValueEnum", name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
+ name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
+ null);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd(elementName);
+ }
+
+ private void addValueElement(final String element, final String name,
+ final String desc, final String value) {
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "",
+ SAXClassAdapter.encode(value));
+ }
+
+ sa.addElement(element, att);
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/SAXClassAdapter.java b/parabotv2/src/org/objectweb/asm/xml/SAXClassAdapter.java
new file mode 100644
index 0000000..904be2b
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/SAXClassAdapter.java
@@ -0,0 +1,324 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.objectweb.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
+ * events from the visited class. It can feed any kind of
+ * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
+ * or XQuery engines.
+ *
+ * @see Processor
+ * @see ASMContentHandler
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXClassAdapter extends ClassVisitor {
+
+ SAXAdapter sa;
+
+ private final boolean singleDocument;
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.xml.SAXClassAdapter SAXClassAdapter} object.
+ *
+ * @param h
+ * content handler that will be used to send SAX 2.0 events.
+ * @param singleDocument
+ * if true adapter will not produce
+ * {@link org.xml.sax.ContentHandler#startDocument() startDocument()} and
+ * {@link org.xml.sax.ContentHandler#endDocument() endDocument()} events.
+ */
+ public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
+ super(Opcodes.ASM4);
+ this.sa = new SAXAdapter(h);
+ this.singleDocument = singleDocument;
+ if (!singleDocument) {
+ sa.addDocumentStart();
+ }
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ AttributesImpl att = new AttributesImpl();
+ if (source != null) {
+ att.addAttribute("", "file", "file", "", encode(source));
+ }
+ if (debug != null) {
+ att.addAttribute("", "debug", "debug", "", encode(debug));
+ }
+
+ sa.addElement("source", att);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "owner", "owner", "", owner);
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+
+ sa.addElement("outerclass", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_CLASS, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (superName != null) {
+ att.addAttribute("", "parent", "parent", "", superName);
+ }
+ att.addAttribute("", "major", "major", "",
+ Integer.toString(version & 0xFFFF));
+ att.addAttribute("", "minor", "minor", "",
+ Integer.toString(version >>> 16));
+ sa.addStart("class", att);
+
+ sa.addStart("interfaces", new AttributesImpl());
+ if (interfaces != null && interfaces.length > 0) {
+ for (int i = 0; i < interfaces.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", interfaces[i]);
+ sa.addElement("interface", att2);
+ }
+ }
+ sa.addEnd("interfaces");
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_FIELD, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "", encode(value.toString()));
+ }
+
+ return new SAXFieldAdapter(sa, att);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "", signature);
+ }
+ sa.addStart("method", att);
+
+ sa.addStart("exceptions", new AttributesImpl());
+ if (exceptions != null && exceptions.length > 0) {
+ for (int i = 0; i < exceptions.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", exceptions[i]);
+ sa.addElement("exception", att2);
+ }
+ }
+ sa.addEnd("exceptions");
+
+ return new SAXCodeAdapter(sa, access);
+ }
+
+ @Override
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_INNER, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (outerName != null) {
+ att.addAttribute("", "outerName", "outerName", "", outerName);
+ }
+ if (innerName != null) {
+ att.addAttribute("", "innerName", "innerName", "", innerName);
+ }
+ sa.addElement("innerclass", att);
+ }
+
+ @Override
+ public final void visitEnd() {
+ sa.addEnd("class");
+ if (!singleDocument) {
+ sa.addDocumentEnd();
+ }
+ }
+
+ static final String encode(final String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ sb.append("\\\\");
+ } else if (c < 0x20 || c > 0x7f) {
+ sb.append("\\u");
+ if (c < 0x10) {
+ sb.append("000");
+ } else if (c < 0x100) {
+ sb.append("00");
+ } else if (c < 0x1000) {
+ sb.append('0');
+ }
+ sb.append(Integer.toString(c, 16));
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static void appendAccess(final int access, final StringBuffer sb) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ sb.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ sb.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ sb.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ sb.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ sb.append("static ");
+ }
+ if ((access & Opcodes.ACC_SUPER) != 0) {
+ if ((access & ACCESS_CLASS) == 0) {
+ sb.append("synchronized ");
+ } else {
+ sb.append("super ");
+ }
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("bridge ");
+ } else {
+ sb.append("volatile ");
+ }
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("varargs ");
+ } else {
+ sb.append("transient ");
+ }
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ sb.append("native ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ sb.append("strict ");
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ sb.append("interface ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ sb.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ sb.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ sb.append("annotation ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ sb.append("enum ");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append("deprecated ");
+ }
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/SAXCodeAdapter.java b/parabotv2/src/org/objectweb/asm/xml/SAXCodeAdapter.java
new file mode 100644
index 0000000..c295afe
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/SAXCodeAdapter.java
@@ -0,0 +1,362 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.util.Printer;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.objectweb.asm.MethodVisitor} that generates SAX 2.0 events from the visited
+ * method.
+ *
+ * @see SAXClassAdapter
+ * @see Processor
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXCodeAdapter extends MethodVisitor {
+
+ static final String[] TYPES = { "top", "int", "float", "double", "long",
+ "null", "uninitializedThis" };
+
+ SAXAdapter sa;
+
+ private final Map labelNames;
+
+ /**
+ * Constructs a new {@link org.objectweb.asm.xml.SAXCodeAdapter SAXCodeAdapter} object.
+ *
+ * @param sa
+ * content handler that will be used to send SAX 2.0 events.
+ */
+ public SAXCodeAdapter(final SAXAdapter sa, final int access) {
+ super(Opcodes.ASM4);
+ this.sa = sa;
+ this.labelNames = new HashMap();
+
+ if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
+ sa.addStart("code", new AttributesImpl());
+ }
+ }
+
+ @Override
+ public final void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ AttributesImpl attrs = new AttributesImpl();
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ if (type == Opcodes.F_NEW) {
+ attrs.addAttribute("", "type", "type", "", "NEW");
+ } else {
+ attrs.addAttribute("", "type", "type", "", "FULL");
+ }
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ appendFrameTypes(false, nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ attrs.addAttribute("", "type", "type", "", "APPEND");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ attrs.addAttribute("", "type", "type", "", "CHOP");
+ attrs.addAttribute("", "count", "count", "",
+ Integer.toString(nLocal));
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME:
+ attrs.addAttribute("", "type", "type", "", "SAME");
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME1:
+ attrs.addAttribute("", "type", "type", "", "SAME1");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(false, 1, stack);
+ break;
+ }
+ sa.addEnd("frame");
+ }
+
+ private void appendFrameTypes(final boolean local, final int n,
+ final Object[] types) {
+ for (int i = 0; i < n; ++i) {
+ Object type = types[i];
+ AttributesImpl attrs = new AttributesImpl();
+ if (type instanceof String) {
+ attrs.addAttribute("", "type", "type", "", (String) type);
+ } else if (type instanceof Integer) {
+ attrs.addAttribute("", "type", "type", "",
+ TYPES[((Integer) type).intValue()]);
+ } else {
+ attrs.addAttribute("", "type", "type", "", "uninitialized");
+ attrs.addAttribute("", "label", "label", "",
+ getLabel((Label) type));
+ }
+ sa.addElement(local ? "local" : "stack", attrs);
+ }
+ }
+
+ @Override
+ public final void visitInsn(final int opcode) {
+ sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
+ }
+
+ @Override
+ public final void visitIntInsn(final int opcode, final int operand) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitVarInsn(final int opcode, final int var) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitTypeInsn(final int opcode, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", type);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "bsm", "bsm", "",
+ SAXClassAdapter.encode(bsm.toString()));
+ sa.addStart("INVOKEDYNAMIC", attrs);
+ for (int i = 0; i < bsmArgs.length; i++) {
+ sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
+ }
+ sa.addEnd("INVOKEDYNAMIC");
+ }
+
+ @Override
+ public final void visitJumpInsn(final int opcode, final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "label", "label", "", getLabel(label));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitLabel(final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", getLabel(label));
+ sa.addElement("Label", attrs);
+ }
+
+ @Override
+ public final void visitLdcInsn(final Object cst) {
+ sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
+ }
+
+ private static AttributesImpl getConstantAttribute(final Object cst) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "cst", "cst", "",
+ SAXClassAdapter.encode(cst.toString()));
+ attrs.addAttribute("", "desc", "desc", "",
+ Type.getDescriptor(cst.getClass()));
+ return attrs;
+ }
+
+ @Override
+ public final void visitIincInsn(final int var, final int increment) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
+ sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
+ }
+
+ @Override
+ public final void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "min", "min", "", Integer.toString(min));
+ attrs.addAttribute("", "max", "max", "", Integer.toString(max));
+ attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.TABLESWITCH];
+ sa.addStart(o, attrs);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
+ sa.addStart(o, att);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitMultiANewArrayInsn(final String desc, final int dims) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
+ sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
+ }
+
+ @Override
+ public final void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
+ if (type != null) {
+ attrs.addAttribute("", "type", "type", "", type);
+ }
+ sa.addElement("TryCatch", attrs);
+ }
+
+ @Override
+ public final void visitMaxs(final int maxStack, final int maxLocals) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "maxStack", "maxStack", "",
+ Integer.toString(maxStack));
+ attrs.addAttribute("", "maxLocals", "maxLocals", "",
+ Integer.toString(maxLocals));
+ sa.addElement("Max", attrs);
+
+ sa.addEnd("code");
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ attrs.addAttribute("", "signature", "signature", "",
+ SAXClassAdapter.encode(signature));
+ }
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "var", "var", "", Integer.toString(index));
+ sa.addElement("LocalVar", attrs);
+ }
+
+ @Override
+ public final void visitLineNumber(final int line, final Label start) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "line", "line", "", Integer.toString(line));
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ sa.addElement("LineNumber", attrs);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
+ : -1, parameter, desc);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("method");
+ }
+
+ private final String getLabel(final Label label) {
+ String name = labelNames.get(label);
+ if (name == null) {
+ name = Integer.toString(labelNames.size());
+ labelNames.put(label, name);
+ }
+ return name;
+ }
+
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/SAXFieldAdapter.java b/parabotv2/src/org/objectweb/asm/xml/SAXFieldAdapter.java
new file mode 100644
index 0000000..5de41a8
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/SAXFieldAdapter.java
@@ -0,0 +1,63 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.xml;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Opcodes;
+import org.xml.sax.Attributes;
+
+/**
+ * SAXFieldAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXFieldAdapter extends FieldVisitor {
+
+ SAXAdapter sa;
+
+ public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
+ super(Opcodes.ASM4);
+ this.sa = sa;
+ sa.addStart("field", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("field");
+ }
+}
diff --git a/parabotv2/src/org/objectweb/asm/xml/asm-xml.dtd b/parabotv2/src/org/objectweb/asm/xml/asm-xml.dtd
new file mode 100644
index 0000000..b862085
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/asm-xml.dtd
@@ -0,0 +1,349 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/parabotv2/src/org/objectweb/asm/xml/package.html b/parabotv2/src/org/objectweb/asm/xml/package.html
new file mode 100644
index 0000000..d7bbe66
--- /dev/null
+++ b/parabotv2/src/org/objectweb/asm/xml/package.html
@@ -0,0 +1,96 @@
+
+
+
+Provides SAX 2.0 adapters for ASM
+visitors to convert classes to and from XML.
+These adapters can be chained with other SAX compliant content handlers and
+filters, eg. XSLT or XQuery engines. This package is bundled as
+a separate asm-xml.jar library and requires asm.jar .
+
+ASMContentHandler and SAXClassAdapter/SAXCodeAdapter
+are using asm-xml.dtd .
+Here is the example of bytecode to bytecode XSLT transformation.
+
+
+ SAXTransformerFactory saxtf = ( SAXTransformerFactory) TransformerFactory.newInstance();
+ Templates templates = saxtf.newTemplates( xsltSource);
+
+ TransformerHandler handler = saxtf.newTransformerHandler( templates);
+ handler.setResult( new SAXResult( new ASMContentHandler( outputStream, computeMax)));
+
+ ClassReader cr = new ClassReader( bytecode);
+ cr.accept( new SAXClassAdapter( handler, cr.getVersion(), false), false);
+
+
+See JAXP and SAX documentation for more detils.
+
+
+There are few illustrations of the bytecode transformation with XSLT in
+examples directory. The following XSLT procesors has been tested.
+
+
+
+
+Engine
+ javax.xml.transform.TransformerFactory property
+
+
+
+jd.xslt
+jd.xml.xslt.trax.TransformerFactoryImpl
+
+
+
+Saxon
+net.sf.saxon.TransformerFactoryImpl
+
+
+
+Caucho
+com.caucho.xsl.Xsl
+
+
+
+Xalan interpeter
+org.apache.xalan.processor.TransformerFactory
+
+
+
+Xalan xsltc
+org.apache.xalan.xsltc.trax.TransformerFactoryImpl
+
+
+
+
+@since ASM 1.4.3
+
+
+