tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kao...@apache.org
Subject [07/23] FIXED - TAP5-2214: Make tapestry5 java8 compatible - update ASM source to 5.0.1, should be jdk 1.5 compatible, see ASM bug "317132 ASM 5.0 do not supported JDK 1.5?"
Date Tue, 25 Mar 2014 18:29:55 GMT
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
new file mode 100644
index 0000000..284fbef
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceInterpreter.java
@@ -0,0 +1,198 @@
+/***
+ * 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.FieldInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LdcInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link SourceValue} values.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceInterpreter extends Interpreter<SourceValue> implements
+        Opcodes {
+
+    public SourceInterpreter() {
+        super(ASM5);
+    }
+
+    protected SourceInterpreter(final int api) {
+        super(api);
+    }
+
+    @Override
+    public SourceValue newValue(final Type type) {
+        if (type == Type.VOID_TYPE) {
+            return null;
+        }
+        return new SourceValue(type == null ? 1 : type.getSize());
+    }
+
+    @Override
+    public SourceValue newOperation(final AbstractInsnNode insn) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LCONST_0:
+        case LCONST_1:
+        case DCONST_0:
+        case DCONST_1:
+            size = 2;
+            break;
+        case LDC:
+            Object cst = ((LdcInsnNode) insn).cst;
+            size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+            break;
+        case GETSTATIC:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue copyOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        return new SourceValue(value.getSize(), insn);
+    }
+
+    @Override
+    public SourceValue unaryOperation(final AbstractInsnNode insn,
+            final SourceValue value) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LNEG:
+        case DNEG:
+        case I2L:
+        case I2D:
+        case L2D:
+        case F2L:
+        case F2D:
+        case D2L:
+            size = 2;
+            break;
+        case GETFIELD:
+            size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue binaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2) {
+        int size;
+        switch (insn.getOpcode()) {
+        case LALOAD:
+        case DALOAD:
+        case LADD:
+        case DADD:
+        case LSUB:
+        case DSUB:
+        case LMUL:
+        case DMUL:
+        case LDIV:
+        case DDIV:
+        case LREM:
+        case DREM:
+        case LSHL:
+        case LSHR:
+        case LUSHR:
+        case LAND:
+        case LOR:
+        case LXOR:
+            size = 2;
+            break;
+        default:
+            size = 1;
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public SourceValue ternaryOperation(final AbstractInsnNode insn,
+            final SourceValue value1, final SourceValue value2,
+            final SourceValue value3) {
+        return new SourceValue(1, insn);
+    }
+
+    @Override
+    public SourceValue naryOperation(final AbstractInsnNode insn,
+            final List<? extends SourceValue> values) {
+        int size;
+        int opcode = insn.getOpcode();
+        if (opcode == MULTIANEWARRAY) {
+            size = 1;
+        } else {
+            String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+                    : ((MethodInsnNode) insn).desc;
+            size = Type.getReturnType(desc).getSize();
+        }
+        return new SourceValue(size, insn);
+    }
+
+    @Override
+    public void returnOperation(final AbstractInsnNode insn,
+            final SourceValue value, final SourceValue expected) {
+    }
+
+    @Override
+    public SourceValue merge(final SourceValue d, final SourceValue w) {
+        if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) {
+            Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns)
+                    .union((SmallSet<AbstractInsnNode>) w.insns);
+            if (s == d.insns && d.size == w.size) {
+                return d;
+            } else {
+                return new SourceValue(Math.min(d.size, w.size), s);
+            }
+        }
+        if (d.size != w.size || !d.insns.containsAll(w.insns)) {
+            HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>();
+            s.addAll(d.insns);
+            s.addAll(w.insns);
+            return new SourceValue(Math.min(d.size, w.size), s);
+        }
+        return d;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
new file mode 100644
index 0000000..0cb2f50
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SourceValue.java
@@ -0,0 +1,97 @@
+/***
+ * 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A {@link Value} that is represented by its type in a two types type system.
+ * This type system distinguishes the ONEWORD and TWOWORDS types.
+ * 
+ * @author Eric Bruneton
+ */
+public class SourceValue implements Value {
+
+    /**
+     * The size of this value.
+     */
+    public final int size;
+
+    /**
+     * The instructions that can produce this value. For example, for the Java
+     * code below, the instructions that can produce the value of <tt>i</tt> at
+     * line 5 are the txo ISTORE instructions at line 1 and 3:
+     * 
+     * <pre>
+     * 1: i = 0;
+     * 2: if (...) {
+     * 3:   i = 1;
+     * 4: }
+     * 5: return i;
+     * </pre>
+     * 
+     * This field is a set of {@link AbstractInsnNode} objects.
+     */
+    public final Set<AbstractInsnNode> insns;
+
+    public SourceValue(final int size) {
+        this(size, SmallSet.<AbstractInsnNode> emptySet());
+    }
+
+    public SourceValue(final int size, final AbstractInsnNode insn) {
+        this.size = size;
+        this.insns = new SmallSet<AbstractInsnNode>(insn, null);
+    }
+
+    public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
+        this.size = size;
+        this.insns = insns;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    @Override
+    public boolean equals(final Object value) {
+        if (!(value instanceof SourceValue)) {
+            return false;
+        }
+        SourceValue v = (SourceValue) value;
+        return size == v.size && insns.equals(v.insns);
+    }
+
+    @Override
+    public int hashCode() {
+        return insns.hashCode();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
new file mode 100644
index 0000000..2032d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Subroutine.java
@@ -0,0 +1,90 @@
+/***
+ * 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+
+/**
+ * A method subroutine (corresponds to a JSR instruction).
+ * 
+ * @author Eric Bruneton
+ */
+class Subroutine {
+
+    LabelNode start;
+
+    boolean[] access;
+
+    List<JumpInsnNode> callers;
+
+    private Subroutine() {
+    }
+
+    Subroutine(final LabelNode start, final int maxLocals,
+            final JumpInsnNode caller) {
+        this.start = start;
+        this.access = new boolean[maxLocals];
+        this.callers = new ArrayList<JumpInsnNode>();
+        callers.add(caller);
+    }
+
+    public Subroutine copy() {
+        Subroutine result = new Subroutine();
+        result.start = start;
+        result.access = new boolean[access.length];
+        System.arraycopy(access, 0, result.access, 0, access.length);
+        result.callers = new ArrayList<JumpInsnNode>(callers);
+        return result;
+    }
+
+    public boolean merge(final Subroutine subroutine) throws AnalyzerException {
+        boolean changes = false;
+        for (int i = 0; i < access.length; ++i) {
+            if (subroutine.access[i] && !access[i]) {
+                access[i] = true;
+                changes = true;
+            }
+        }
+        if (subroutine.start == start) {
+            for (int i = 0; i < subroutine.callers.size(); ++i) {
+                JumpInsnNode caller = subroutine.callers.get(i);
+                if (!callers.contains(caller)) {
+                    callers.add(caller);
+                    changes = true;
+                }
+            }
+        }
+        return changes;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
new file mode 100644
index 0000000..b0d657c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Value.java
@@ -0,0 +1,45 @@
+/***
+ * 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+/**
+ * An immutable symbolic value for semantic interpretation of bytecode.
+ * 
+ * @author Eric Bruneton
+ */
+public interface Value {
+
+    /**
+     * Returns the size of this value in words.
+     * 
+     * @return either 1 or 2.
+     */
+    int getSize();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
new file mode 100644
index 0000000..228da02
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/package.html
@@ -0,0 +1,67 @@
+<html>
+<!--
+ * 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.
+-->
+<body>
+
+<p>
+Provides a framework for static code analysis based on the asm.tree package.
+</p>
+
+<p>
+Basic usage:
+</p>
+
+<pre>
+ClassReader cr = new ClassReader(bytecode);
+ClassNode cn = new ClassNode();
+cr.accept(cn, ClassReader.SKIP_DEBUG);
+
+List methods = cn.methods;
+for (int i = 0; i < methods.size(); ++i) {
+    MethodNode method = (MethodNode) methods.get(i);
+    if (method.instructions.size() > 0) {
+        Analyzer a = new Analyzer(new BasicInterpreter());
+        a.analyze(cn.name, method);
+        Frame[] frames = a.getFrames();
+        // Elements of the frames arrray now contains info for each instruction
+        // from the analyzed method. BasicInterpreter creates BasicValue, that
+        // is using simplified type system that distinguishes the UNINITIALZED,
+        // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+        ...
+    }
+}
+</pre>
+
+<p>
+@since ASM 1.4.3
+</p>
+
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
index e1fec58..f8b0b0d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifiable.java
@@ -29,25 +29,28 @@
  */
 package org.apache.tapestry5.internal.plastic.asm.util;
 
-import org.apache.tapestry5.internal.plastic.asm.Label;
-
 import java.util.Map;
 
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
 /**
  * An {@link org.apache.tapestry5.internal.plastic.asm.Attribute Attribute} that can print the ASM code
  * to create an equivalent attribute.
- *
+ * 
  * @author Eugene Kuleshov
  */
 public interface ASMifiable {
 
     /**
      * Prints the ASM code to create an attribute equal to this attribute.
-     *
-     * @param buf a buffer used for printing Java code.
-     * @param varName name of the variable in a printed code used to store
-     *        attribute instance.
-     * @param labelNames map of label instances to their names.
+     * 
+     * @param buf
+     *            a buffer used for printing Java code.
+     * @param varName
+     *            name of the variable in a printed code used to store attribute
+     *            instance.
+     * @param labelNames
+     *            map of label instances to their names.
      */
     void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
new file mode 100644
index 0000000..34829b0
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/ASMifier.java
@@ -0,0 +1,1285 @@
+/***
+ * 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.apache.tapestry5.internal.plastic.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link Printer} that prints the ASM code to generate the classes if visits.
+ * 
+ * @author Eric Bruneton
+ */
+public class ASMifier extends Printer {
+
+    /**
+     * The name of the visitor variable in the produced code.
+     */
+    protected final String name;
+
+    /**
+     * Identifier of the annotation visitor variable in the produced code.
+     */
+    protected final int id;
+
+    /**
+     * The label names. This map associates String values to Label keys. It is
+     * used only in ASMifierMethodVisitor.
+     */
+    protected Map<Label, String> 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 ASMifier}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the
+     * {@link #ASMifier(int, String, int)} version.
+     * 
+     * @throws IllegalStateException
+     *             If a subclass calls this constructor.
+     */
+    public ASMifier() {
+        this(Opcodes.ASM5, "cw", 0);
+        if (getClass() != ASMifier.class) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Constructs a new {@link ASMifier}.
+     * 
+     * @param api
+     *            the ASM API version implemented by this class. Must be one of
+     *            {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     * @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.
+     * <p>
+     * Usage: ASMifier [-debug] &lt;binary 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 {
+        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] "
+                    + "<fully qualified class name or class file name>");
+            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 ASMifier visitClassTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, 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 ASMifier visitFieldTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, 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 void visitParameter(String parameterName, int access) {
+        buf.setLength(0);
+        buf.append(name).append(".visitParameter(");
+        appendString(buf, parameterName);
+        buf.append(", ");
+        appendAccess(access);
+        text.add(buf.append(");\n").toString());
+    }
+
+    @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 visitMethodTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation(typeRef, typePath, 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());
+    }
+
+    @Deprecated
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc) {
+        if (api >= Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc,
+                opcode == Opcodes.INVOKEINTERFACE);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        if (api < Opcodes.ASM5) {
+            super.visitMethodInsn(opcode, owner, name, desc, itf);
+            return;
+        }
+        doVisitMethodInsn(opcode, owner, name, desc, itf);
+    }
+
+    private void doVisitMethodInsn(final int opcode, final String owner,
+            final String name, final String desc, final boolean itf) {
+        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(", ");
+        buf.append(itf ? "true" : "false");
+        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 ASMifier visitInsnAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitInsnAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    @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 ASMifier visitTryCatchAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTryCatchAnnotation", typeRef,
+                typePath, desc, visible);
+    }
+
+    @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 Printer visitLocalVariableAnnotation(int typeRef, TypePath typePath,
+            Label[] start, Label[] end, int[] index, String desc,
+            boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name)
+                .append(".visitLocalVariableAnnotation(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).append("\"), ");
+        buf.append("new Label[] {");
+        for (int i = 0; i < start.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(start[i]);
+        }
+        buf.append(" }, new Label[] {");
+        for (int i = 0; i < end.length; ++i) {
+            buf.append(i == 0 ? " " : ", ");
+            appendLabel(end[i]);
+        }
+        buf.append(" }, new int[] {");
+        for (int i = 0; i < index.length; ++i) {
+            buf.append(i == 0 ? " " : ", ").append(index[i]);
+        }
+        buf.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 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 ASMifier visitTypeAnnotation(final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        return visitTypeAnnotation("visitTypeAnnotation", typeRef, typePath,
+                desc, visible);
+    }
+
+    public ASMifier visitTypeAnnotation(final String method, final int typeRef,
+            final TypePath typePath, final String desc, final boolean visible) {
+        buf.setLength(0);
+        buf.append("{\n").append("av0 = ").append(name).append(".")
+                .append(method).append("(");
+        buf.append(typeRef);
+        buf.append(", TypePath.fromString(\"").append(typePath).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;
+    }
+
+    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<Label, String>();
+            }
+            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.ASM5, 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 ((access & Opcodes.ACC_MANDATED) != 0) {
+            if (!first) {
+                buf.append(" + ");
+            }
+            buf.append("ACC_MANDATED");
+            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 <tt>null</tt>.
+     */
+    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 <tt>null</tt>.
+     */
+    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<Label, String>();
+        }
+        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
+     * <i>must</i> 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));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000..56580d1
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/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.apache.tapestry5.internal.plastic.asm.util;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An {@link 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.ASM5, 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.METHOD) {
+                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");
+        }
+    }
+}


Mime
View raw message