You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/06 21:11:38 UTC

svn commit: r1089584 [17/21] - in /tapestry/tapestry5/trunk/plastic: ./ src/external/ src/external/java/ src/external/java/org/ src/external/java/org/objectweb/ src/external/java/org/objectweb/asm/ src/external/java/org/objectweb/asm/attrs/ src/externa...

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 &lt;fully qualified
+     * class name or class file name&gt;
+     *
+     * @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");
+        }
+    }
+}