Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/AbstractVisitor.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/AbstractVisitor.java?rev=1089584&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/AbstractVisitor.java (added) +++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/AbstractVisitor.java Wed Apr 6 19:11:34 2011 @@ -0,0 +1,202 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 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; + +/** + * An abstract visitor. + * + * @author Eric Bruneton + */ +public abstract class AbstractVisitor { + + /** + * The names of the Java Virtual Machine opcodes. + */ + public static final String[] OPCODES; + /** + * Types for <code>operand</code> parameter of the + * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when + * <code>opcode</code> is <code>NEWARRAY</code>. + */ + public static final String[] TYPES; + + 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; + } + } + + /** + * 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; + + /** + * A buffer that can be used to create strings. + */ + protected final StringBuffer buf; + + /** + * Constructs a new {@link AbstractVisitor}. + */ + protected AbstractVisitor() { + this.text = new ArrayList(); + this.buf = new StringBuffer(); + } + + /** + * 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()); + } + } + } + + /** + * Returns the default {@link ASMifiable} prototypes. + * + * @return the default {@link ASMifiable} prototypes. + */ + public static Attribute[] getDefaultAttributes() { + return new Attribute[0]; + } +}
Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckAnnotationAdapter.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckAnnotationAdapter.java?rev=1089584&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckAnnotationAdapter.java (added) +++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckAnnotationAdapter.java Wed Apr 6 19:11:34 2011 @@ -0,0 +1,132 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 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.Type; + +/** + * An {@link AnnotationVisitor} that checks that its methods are properly used. + * + * @author Eric Bruneton + */ +public class CheckAnnotationAdapter implements AnnotationVisitor { + + private final AnnotationVisitor av; + + private final boolean named; + + private boolean end; + + public CheckAnnotationAdapter(final AnnotationVisitor av) { + this(av, true); + } + + CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) { + this.av = av; + this.named = named; + } + + 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 (av != null) { + av.visit(name, value); + } + } + + 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); + } + } + + 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)); + } + + public AnnotationVisitor visitArray(final String name) { + checkEnd(); + checkName(name); + return new CheckAnnotationAdapter(av == null + ? null + : av.visitArray(name), false); + } + + 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"); + } + } +} Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckClassAdapter.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckClassAdapter.java?rev=1089584&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckClassAdapter.java (added) +++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckClassAdapter.java Wed Apr 6 19:11:34 2011 @@ -0,0 +1,569 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 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.FieldVisitor; +import org.objectweb.asm.ClassAdapter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.TryCatchBlockNode; +import org.objectweb.asm.tree.analysis.Analyzer; +import org.objectweb.asm.tree.analysis.SimpleVerifier; +import org.objectweb.asm.tree.analysis.Frame; + +/** + * A {@link ClassAdapter} that checks that its methods are properly used. More + * precisely this class adapter checks each method call individually, based + * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i> + * of method calls. For example, the invalid sequence + * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC, + * "i", "D", null)</tt> + * will <i>not</i> be detected by this class adapter. + * + * <p><code>CheckClassAdapter</code> can be also used to verify bytecode + * transformations in order to make sure transformed bytecode is sane. For + * example: + * + * <pre> + * InputStream is = ...; // get bytes for the source class + * ClassReader cr = new ClassReader(is); + * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); + * ClassVisitor cv = new <b>MyClassAdapter</b>(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); + * </pre> + * + * Above code runs transformed bytecode trough the + * <code>CheckClassAdapter</code>. 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. + * + * <p>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): + * + * <pre> + * 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 <b>.</b> I . . . . . . : + * ... + * + * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . : + * ILOAD 1 + * 00072 <b>?</b> + * INVOKESPECIAL java/lang/Integer.<init> (I)V + * ... + * </pre> + * + * In the above output you can see that variable 1 loaded by + * <code>ILOAD 1</code> instruction at position <code>00071</code> is not + * initialized. You can also see that at the beginning of the method (code + * inserted by the transformation) variable 2 is initialized. + * + * <p>Note that when used like that, <code>CheckClassAdapter.verify()</code> + * can trigger additional class loading, because it is using + * <code>SimpleVerifier</code>. + * + * @author Eric Bruneton + */ +public class CheckClassAdapter extends ClassAdapter { + + /** + * The class version number. + */ + private int version; + + /** + * <tt>true</tt> if the visit method has been called. + */ + private boolean start; + + /** + * <tt>true</tt> if the visitSource method has been called. + */ + private boolean source; + + /** + * <tt>true</tt> if the visitOuterClass method has been called. + */ + private boolean outer; + + /** + * <tt>true</tt> 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; + + /** + * <tt>true</tt> if the method code must be checked with a BasicVerifier. + */ + private boolean checkDataFlow; + + /** + * Checks a given class. <p> Usage: CheckClassAdapter <fully qualified + * 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 " + + "<fully qualified class name or class file name>"); + 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 <code>ClassReader</code> that contains bytecode for the + * analysis. + * @param loader a <code>ClassLoader</code> 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 = (MethodNode) 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 <code>ClassReader</code> 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(); + TraceMethodVisitor mv = new TraceMethodVisitor(); + + 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 + " : " + mv.buf); // mv.text.get(j)); + } + for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { + ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv); + pw.print(" " + mv.buf); + } + 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 CheckClassAdapter}. + * + * @param cv the class visitor to which this adapter must delegate calls. + */ + public CheckClassAdapter(final ClassVisitor cv) { + this(cv, true); + } + + /** + * Constructs a new {@link CheckClassAdapter}. + * + * @param cv the class visitor to which this adapter must delegate calls. + * @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or + * <tt>false</tt> to not perform any data flow check (see + * {@link CheckMethodAdapter}). This option requires valid maxLocals + * and maxStack values. + */ + public CheckClassAdapter(final ClassVisitor cv, boolean checkDataFlow) { + super(cv); + this.labels = new HashMap(); + this.checkDataFlow = checkDataFlow; + } + + // ------------------------------------------------------------------------ + // Implementation of the ClassVisitor interface + // ------------------------------------------------------------------------ + + 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) { + CheckMethodAdapter.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; + cv.visit(version, access, name, signature, superName, interfaces); + } + + public void visitSource(final String file, final String debug) { + checkState(); + if (source) { + throw new IllegalStateException("visitSource can be called only once."); + } + source = true; + cv.visitSource(file, debug); + } + + 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); + } + cv.visitOuterClass(owner, name, desc); + } + + 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); + cv.visitInnerClass(name, outerName, innerName, access); + } + + 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) { + CheckMethodAdapter.checkFieldSignature(signature); + } + if (value != null) { + CheckMethodAdapter.checkConstant(value); + } + FieldVisitor av = cv.visitField(access, name, desc, signature, value); + return new CheckFieldAdapter(av); + } + + 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 + CheckMethodAdapter.checkMethodIdentifier(version, name, "method name"); + CheckMethodAdapter.checkMethodDesc(desc); + if (signature != null) { + CheckMethodAdapter.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, + cv.visitMethod(access, name, desc, signature, exceptions), + labels); + } else { + cma = new CheckMethodAdapter(cv.visitMethod(access, + name, + desc, + signature, + exceptions), labels); + } + cma.version = version; + return cma; + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + checkState(); + CheckMethodAdapter.checkDesc(desc, false); + return new CheckAnnotationAdapter(cv.visitAnnotation(desc, visible)); + } + + public void visitAttribute(final Attribute attr) { + checkState(); + if (attr == null) { + throw new IllegalArgumentException("Invalid attribute (must not be null)"); + } + cv.visitAttribute(attr); + } + + public void visitEnd() { + checkState(); + end = true; + cv.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); + } + } +} Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckFieldAdapter.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckFieldAdapter.java?rev=1089584&view=auto ============================================================================== --- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckFieldAdapter.java (added) +++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/util/CheckFieldAdapter.java Wed Apr 6 19:11:34 2011 @@ -0,0 +1,77 @@ +/*** + * ASM: a very small and fast Java bytecode manipulation framework + * Copyright (c) 2000-2007 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; + +/** + * A {@link FieldVisitor} that checks that its methods are properly used. + */ +public class CheckFieldAdapter implements FieldVisitor { + + private final FieldVisitor fv; + + private boolean end; + + public CheckFieldAdapter(final FieldVisitor fv) { + this.fv = fv; + } + + public AnnotationVisitor visitAnnotation( + final String desc, + final boolean visible) + { + checkEnd(); + CheckMethodAdapter.checkDesc(desc, false); + return new CheckAnnotationAdapter(fv.visitAnnotation(desc, visible)); + } + + public void visitAttribute(final Attribute attr) { + checkEnd(); + if (attr == null) { + throw new IllegalArgumentException("Invalid attribute (must not be null)"); + } + fv.visitAttribute(attr); + } + + public void visitEnd() { + checkEnd(); + end = true; + fv.visitEnd(); + } + + private void checkEnd() { + if (end) { + throw new IllegalStateException("Cannot call a visit method after visitEnd has been called"); + } + } +}
