You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by ka...@apache.org on 2014/03/25 19:29:49 UTC
[01/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?"
Repository: tapestry-5
Updated Branches:
refs/heads/5.3 1a03c5661 -> a0ac605db
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
new file mode 100644
index 0000000..b862085
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/asm-xml.dtd
@@ -0,0 +1,349 @@
+<!--
+ ASM XML Adapter
+ Copyright (c) 2004-2011, Eugene Kuleshov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+ This DTD must be used to create XML documents to be processed by
+ org.objectweb.asm.xml.ASMContentHandler
+-->
+
+<!--
+ Root element used to aggregate multiple classes into single document.
+-->
+<!ELEMENT classes ( class+ )>
+
+<!--
+ Root element for a single class.
+-->
+<!ELEMENT class ( interfaces, ( field | innerclass | method )*)>
+<!ATTLIST class access CDATA #REQUIRED>
+<!ATTLIST class name CDATA #REQUIRED>
+<!ATTLIST class parent CDATA #REQUIRED>
+<!ATTLIST class major CDATA #REQUIRED>
+<!ATTLIST class minor CDATA #REQUIRED>
+<!ATTLIST class source CDATA #IMPLIED>
+
+<!ELEMENT interfaces ( interface* )>
+<!ELEMENT interface EMPTY>
+<!ATTLIST interface name CDATA #REQUIRED>
+
+<!ELEMENT field EMPTY>
+<!ATTLIST field access CDATA #REQUIRED>
+<!ATTLIST field desc CDATA #REQUIRED>
+<!ATTLIST field name CDATA #REQUIRED>
+<!--
+ All characters out of interval 0x20 to 0x7f (inclusive) must
+ be encoded (\uXXXX) and character '\' must be replaced by "\\"
+-->
+<!ATTLIST field value CDATA #IMPLIED>
+
+<!ELEMENT innerclass EMPTY>
+<!ATTLIST innerclass access CDATA #REQUIRED>
+<!ATTLIST innerclass innerName CDATA #IMPLIED>
+<!ATTLIST innerclass name CDATA #REQUIRED>
+<!ATTLIST innerclass outerName CDATA #IMPLIED>
+
+<!--
+ Root element for method definition.
+-->
+<!ELEMENT method ( exceptions, code? )>
+<!ATTLIST method access CDATA #REQUIRED>
+<!ATTLIST method desc CDATA #REQUIRED>
+<!ATTLIST method name CDATA #REQUIRED>
+
+<!ELEMENT exceptions ( exception* )>
+<!ELEMENT exception EMPTY>
+<!ATTLIST exception name CDATA #REQUIRED>
+
+<!--
+ code element contains bytecode instructions and definitions for labels, line numbers, try/catch and max
+-->
+<!ELEMENT code (( AALOAD | AASTORE | ACONST_NULL | ALOAD | ANEWARRAY | ARETURN | ARRAYLENGTH | ASTORE | ATHROW | BALOAD | BASTORE | BIPUSH | CALOAD | CASTORE | CHECKCAST | D2F | D2I | D2L | DADD | DALOAD | DASTORE | DCMPG | DCMPL | DCONST_0 | DCONST_1 | DDIV | DLOAD | DMUL | DNEG | DREM | DRETURN | DSTORE | DSUB | DUP | DUP2 | DUP2_X1 | DUP2_X2 | DUP_X1 | DUP_X2 | SWAP | F2D | F2I | F2L | FADD | FALOAD | FASTORE | FCMPG | FCMPL | FCONST_0 | FCONST_1 | FCONST_2 | FDIV | FLOAD | FMUL | FNEG | FREM | FRETURN | FSTORE | FSUB | GETFIELD | GETSTATIC | GOTO | I2B | I2C | I2D | I2F | I2L | I2S | IADD | IALOAD | IAND | IASTORE | ICONST_0 | ICONST_1 | ICONST_2 | ICONST_3 | ICONST_4 | ICONST_5 | ICONST_M1 | IDIV | IFEQ | IFGE | IFGT | IFLE | IFLT | IFNE | IFNONNULL | IFNULL | IF_ACMPEQ | IF_ACMPNE | IF_ICMPEQ | IF_ICMPGE | IF_ICMPGT | IF_ICMPLE | IF_ICMPLT | IF_ICMPNE | IINC | ILOAD | IMUL | INEG | INSTANCEOF | INVOKEINTERFACE | INVOKESPECIAL | INVOKESTATIC | INVOKEVIRTUAL | IOR | IREM | IRETU
RN | ISHL | ISHR | ISTORE | ISUB | IUSHR | IXOR | JSR | L2D | L2F | L2I | LADD | LALOAD | LAND | LASTORE | LCMP | LCONST_0 | LCONST_1 | LDC | LDIV | LLOAD | LMUL | LNEG | LOOKUPSWITCH | LOR | LREM | LRETURN | LSHL | LSHR | LSTORE | LSUB | LUSHR | LXOR | MONITORENTER | MONITOREXIT | MULTIANEWARRAY | NEW | NEWARRAY | NOP | POP | POP2 | PUTFIELD | PUTSTATIC | RET | RETURN | SALOAD | SASTORE | SIPUSH | TABLESWITCH | Label | LineNumber | TryCatch )*, Max)>
+
+<!ELEMENT Label EMPTY>
+<!ATTLIST Label name CDATA #REQUIRED>
+
+<!ELEMENT TryCatch EMPTY>
+<!ATTLIST TryCatch end CDATA #REQUIRED>
+<!ATTLIST TryCatch handler CDATA #REQUIRED>
+<!ATTLIST TryCatch start CDATA #REQUIRED>
+<!ATTLIST TryCatch type CDATA #IMPLIED>
+
+<!ELEMENT LineNumber EMPTY>
+<!ATTLIST LineNumber line CDATA #REQUIRED>
+<!ATTLIST LineNumber start CDATA #REQUIRED>
+
+<!ELEMENT Max EMPTY>
+<!ATTLIST Max maxLocals CDATA #REQUIRED>
+<!ATTLIST Max maxStack CDATA #REQUIRED>
+
+<!ELEMENT AALOAD EMPTY>
+<!ELEMENT AASTORE EMPTY>
+<!ELEMENT ACONST_NULL EMPTY>
+<!ELEMENT ALOAD EMPTY>
+<!ATTLIST ALOAD var CDATA #REQUIRED>
+<!ELEMENT ANEWARRAY EMPTY>
+<!ATTLIST ANEWARRAY desc CDATA #REQUIRED>
+<!ELEMENT ARETURN EMPTY>
+<!ELEMENT ARRAYLENGTH EMPTY>
+<!ELEMENT ASTORE EMPTY>
+<!ATTLIST ASTORE var CDATA #REQUIRED>
+<!ELEMENT ATHROW EMPTY>
+<!ELEMENT BALOAD EMPTY>
+<!ELEMENT BASTORE EMPTY>
+<!ELEMENT BIPUSH EMPTY>
+<!ATTLIST BIPUSH value CDATA #REQUIRED>
+<!ELEMENT CALOAD EMPTY>
+<!ELEMENT CASTORE EMPTY>
+<!ELEMENT CHECKCAST EMPTY>
+<!ATTLIST CHECKCAST desc CDATA #REQUIRED>
+<!ELEMENT D2F EMPTY>
+<!ELEMENT D2I EMPTY>
+<!ELEMENT D2L EMPTY>
+<!ELEMENT DADD EMPTY>
+<!ELEMENT DALOAD EMPTY>
+<!ELEMENT DASTORE EMPTY>
+<!ELEMENT DCMPG EMPTY>
+<!ELEMENT DCMPL EMPTY>
+<!ELEMENT DCONST_0 EMPTY>
+<!ELEMENT DCONST_1 EMPTY>
+<!ELEMENT DDIV EMPTY>
+<!ELEMENT DLOAD EMPTY>
+<!ATTLIST DLOAD var CDATA #REQUIRED>
+<!ELEMENT DMUL EMPTY>
+<!ELEMENT DNEG EMPTY>
+<!ELEMENT DREM EMPTY>
+<!ELEMENT DRETURN EMPTY>
+<!ELEMENT DSTORE EMPTY>
+<!ATTLIST DSTORE var CDATA #REQUIRED>
+<!ELEMENT DSUB EMPTY>
+<!ELEMENT DUP EMPTY>
+<!ELEMENT DUP2 EMPTY>
+<!ELEMENT DUP2_X1 EMPTY>
+<!ELEMENT DUP2_X2 EMPTY>
+<!ELEMENT DUP_X1 EMPTY>
+<!ELEMENT DUP_X2 EMPTY>
+<!ELEMENT SWAP EMPTY>
+<!ELEMENT F2D EMPTY>
+<!ELEMENT F2I EMPTY>
+<!ELEMENT F2L EMPTY>
+<!ELEMENT FADD EMPTY>
+<!ELEMENT FALOAD EMPTY>
+<!ELEMENT FASTORE EMPTY>
+<!ELEMENT FCMPG EMPTY>
+<!ELEMENT FCMPL EMPTY>
+<!ELEMENT FCONST_0 EMPTY>
+<!ELEMENT FCONST_1 EMPTY>
+<!ELEMENT FCONST_2 EMPTY>
+<!ELEMENT FDIV EMPTY>
+<!ELEMENT FLOAD EMPTY>
+<!ATTLIST FLOAD var CDATA #REQUIRED>
+<!ELEMENT FMUL EMPTY>
+<!ELEMENT FNEG EMPTY>
+<!ELEMENT FREM EMPTY>
+<!ELEMENT FRETURN EMPTY>
+<!ELEMENT FSTORE EMPTY>
+<!ATTLIST FSTORE var CDATA #REQUIRED>
+<!ELEMENT FSUB EMPTY>
+<!ELEMENT GETFIELD EMPTY>
+<!ATTLIST GETFIELD desc CDATA #REQUIRED>
+<!ATTLIST GETFIELD name CDATA #REQUIRED>
+<!ATTLIST GETFIELD owner CDATA #REQUIRED>
+<!ELEMENT GETSTATIC EMPTY>
+<!ATTLIST GETSTATIC desc CDATA #REQUIRED>
+<!ATTLIST GETSTATIC name CDATA #REQUIRED>
+<!ATTLIST GETSTATIC owner CDATA #REQUIRED>
+<!ELEMENT GOTO EMPTY>
+<!ATTLIST GOTO label CDATA #REQUIRED>
+<!ELEMENT I2B EMPTY>
+<!ELEMENT I2C EMPTY>
+<!ELEMENT I2D EMPTY>
+<!ELEMENT I2F EMPTY>
+<!ELEMENT I2L EMPTY>
+<!ELEMENT I2S EMPTY>
+<!ELEMENT IADD EMPTY>
+<!ELEMENT IALOAD EMPTY>
+<!ELEMENT IAND EMPTY>
+<!ELEMENT IASTORE EMPTY>
+<!ELEMENT ICONST_0 EMPTY>
+<!ELEMENT ICONST_1 EMPTY>
+<!ELEMENT ICONST_2 EMPTY>
+<!ELEMENT ICONST_3 EMPTY>
+<!ELEMENT ICONST_4 EMPTY>
+<!ELEMENT ICONST_5 EMPTY>
+<!ELEMENT ICONST_M1 EMPTY>
+<!ELEMENT IDIV EMPTY>
+<!ELEMENT IFEQ EMPTY>
+<!ATTLIST IFEQ label CDATA #REQUIRED>
+<!ELEMENT IFGE EMPTY>
+<!ATTLIST IFGE label CDATA #REQUIRED>
+<!ELEMENT IFGT EMPTY>
+<!ATTLIST IFGT label CDATA #REQUIRED>
+<!ELEMENT IFLE EMPTY>
+<!ATTLIST IFLE label CDATA #REQUIRED>
+<!ELEMENT IFLT EMPTY>
+<!ATTLIST IFLT label CDATA #REQUIRED>
+<!ELEMENT IFNE EMPTY>
+<!ATTLIST IFNE label CDATA #REQUIRED>
+<!ELEMENT IFNONNULL EMPTY>
+<!ATTLIST IFNONNULL label CDATA #REQUIRED>
+<!ELEMENT IFNULL EMPTY>
+<!ATTLIST IFNULL label CDATA #REQUIRED>
+<!ELEMENT IF_ACMPEQ EMPTY>
+<!ATTLIST IF_ACMPEQ label CDATA #REQUIRED>
+<!ELEMENT IF_ACMPNE EMPTY>
+<!ATTLIST IF_ACMPNE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPEQ EMPTY>
+<!ATTLIST IF_ICMPEQ label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPGE EMPTY>
+<!ATTLIST IF_ICMPGE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPGT EMPTY>
+<!ATTLIST IF_ICMPGT label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPLE EMPTY>
+<!ATTLIST IF_ICMPLE label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPLT EMPTY>
+<!ATTLIST IF_ICMPLT label CDATA #REQUIRED>
+<!ELEMENT IF_ICMPNE EMPTY>
+<!ATTLIST IF_ICMPNE label CDATA #REQUIRED>
+<!ELEMENT IINC EMPTY>
+<!ATTLIST IINC inc CDATA #REQUIRED>
+<!ATTLIST IINC var CDATA #REQUIRED>
+<!ELEMENT ILOAD EMPTY>
+<!ATTLIST ILOAD var CDATA #REQUIRED>
+<!ELEMENT IMUL EMPTY>
+<!ELEMENT INEG EMPTY>
+<!ELEMENT INSTANCEOF EMPTY>
+<!ATTLIST INSTANCEOF desc CDATA #REQUIRED>
+<!ELEMENT INVOKEINTERFACE EMPTY>
+<!ATTLIST INVOKEINTERFACE desc CDATA #REQUIRED>
+<!ATTLIST INVOKEINTERFACE name CDATA #REQUIRED>
+<!ATTLIST INVOKEINTERFACE owner CDATA #REQUIRED>
+<!ELEMENT INVOKESPECIAL EMPTY>
+<!ATTLIST INVOKESPECIAL desc CDATA #REQUIRED>
+<!ATTLIST INVOKESPECIAL name CDATA #REQUIRED>
+<!ATTLIST INVOKESPECIAL owner CDATA #REQUIRED>
+<!ELEMENT INVOKESTATIC EMPTY>
+<!ATTLIST INVOKESTATIC desc CDATA #REQUIRED>
+<!ATTLIST INVOKESTATIC name CDATA #REQUIRED>
+<!ATTLIST INVOKESTATIC owner CDATA #REQUIRED>
+<!ELEMENT INVOKEVIRTUAL EMPTY>
+<!ATTLIST INVOKEVIRTUAL desc CDATA #REQUIRED>
+<!ATTLIST INVOKEVIRTUAL name CDATA #REQUIRED>
+<!ATTLIST INVOKEVIRTUAL owner CDATA #REQUIRED>
+<!ELEMENT INVOKEDYNAMIC ( bsmArgs+ )>
+<!ATTLIST INVOKEDYNAMIC desc CDATA #REQUIRED>
+<!ATTLIST INVOKEDYNAMIC name CDATA #REQUIRED>
+<!ATTLIST INVOKEDYNAMIC bsm CDATA #REQUIRED>
+<!ELEMENT bsmArgs EMPTY>
+<!ATTLIST bsmArgs cst CDATA #REQUIRED>
+<!ATTLIST bsmArgs desc CDATA #REQUIRED>
+<!ELEMENT IOR EMPTY>
+<!ELEMENT IREM EMPTY>
+<!ELEMENT IRETURN EMPTY>
+<!ELEMENT ISHL EMPTY>
+<!ELEMENT ISHR EMPTY>
+<!ELEMENT ISTORE EMPTY>
+<!ATTLIST ISTORE var CDATA #REQUIRED>
+<!ELEMENT ISUB EMPTY>
+<!ELEMENT IUSHR EMPTY>
+<!ELEMENT IXOR EMPTY>
+<!ELEMENT JSR EMPTY>
+<!ATTLIST JSR label CDATA #REQUIRED>
+<!ELEMENT L2D EMPTY>
+<!ELEMENT L2F EMPTY>
+<!ELEMENT L2I EMPTY>
+<!ELEMENT LADD EMPTY>
+<!ELEMENT LALOAD EMPTY>
+<!ELEMENT LAND EMPTY>
+<!ELEMENT LASTORE EMPTY>
+<!ELEMENT LCMP EMPTY>
+<!ELEMENT LCONST_0 EMPTY>
+<!ELEMENT LCONST_1 EMPTY>
+<!ELEMENT LDC EMPTY>
+<!--
+ All characters out of interval 0x20 to 0x7f (inclusive) must
+ be encoded (\uXXXX) and character '\' must be replaced by "\\"
+-->
+<!ATTLIST LDC cst CDATA #REQUIRED>
+<!ATTLIST LDC desc CDATA #REQUIRED>
+<!ELEMENT LDIV EMPTY>
+<!ELEMENT LLOAD EMPTY>
+<!ATTLIST LLOAD var CDATA #REQUIRED>
+<!ELEMENT LMUL EMPTY>
+<!ELEMENT LNEG EMPTY>
+<!ELEMENT LOR EMPTY>
+<!ELEMENT LREM EMPTY>
+<!ELEMENT LRETURN EMPTY>
+<!ELEMENT LSHL EMPTY>
+<!ELEMENT LSHR EMPTY>
+<!ELEMENT LSTORE EMPTY>
+<!ATTLIST LSTORE var CDATA #REQUIRED>
+<!ELEMENT LSUB EMPTY>
+<!ELEMENT LUSHR EMPTY>
+<!ELEMENT LXOR EMPTY>
+<!ELEMENT MONITORENTER EMPTY>
+<!ELEMENT MONITOREXIT EMPTY>
+<!ELEMENT MULTIANEWARRAY EMPTY>
+<!ATTLIST MULTIANEWARRAY desc CDATA #REQUIRED>
+<!ATTLIST MULTIANEWARRAY dims CDATA #REQUIRED>
+<!ELEMENT NEW EMPTY>
+<!ATTLIST NEW desc CDATA #REQUIRED>
+<!ELEMENT NEWARRAY EMPTY>
+<!ATTLIST NEWARRAY value CDATA #REQUIRED>
+<!ELEMENT NOP EMPTY>
+<!ELEMENT POP EMPTY>
+<!ELEMENT POP2 EMPTY>
+<!ELEMENT PUTFIELD EMPTY>
+<!ATTLIST PUTFIELD desc CDATA #REQUIRED>
+<!ATTLIST PUTFIELD name CDATA #REQUIRED>
+<!ATTLIST PUTFIELD owner CDATA #REQUIRED>
+<!ELEMENT PUTSTATIC EMPTY>
+<!ATTLIST PUTSTATIC desc CDATA #REQUIRED>
+<!ATTLIST PUTSTATIC name CDATA #REQUIRED>
+<!ATTLIST PUTSTATIC owner CDATA #REQUIRED>
+<!ELEMENT RET EMPTY>
+<!ATTLIST RET var CDATA #REQUIRED>
+<!ELEMENT RETURN EMPTY>
+<!ELEMENT SALOAD EMPTY>
+<!ELEMENT SASTORE EMPTY>
+<!ELEMENT SIPUSH EMPTY>
+<!ATTLIST SIPUSH value CDATA #REQUIRED>
+
+<!ELEMENT LOOKUPSWITCH ( label+ )>
+<!ATTLIST LOOKUPSWITCH dflt CDATA #REQUIRED>
+
+<!ELEMENT TABLESWITCH ( label+ )>
+<!ATTLIST TABLESWITCH dflt CDATA #REQUIRED>
+<!ATTLIST TABLESWITCH max CDATA #REQUIRED>
+<!ATTLIST TABLESWITCH min CDATA #REQUIRED>
+
+<!ELEMENT label EMPTY>
+<!ATTLIST label key CDATA #IMPLIED>
+<!ATTLIST label name CDATA #REQUIRED>
+
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
new file mode 100644
index 0000000..d7bbe66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/package.html
@@ -0,0 +1,96 @@
+<html>
+<!--
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides <a href="http://sax.sourceforge.net/">SAX 2.0</a> adapters for ASM
+visitors to convert classes to and from XML.
+These adapters can be chained with other SAX compliant content handlers and
+filters, eg. XSLT or XQuery engines. This package is bundled as
+a separate <tt>asm-xml.jar</tt> library and requires <tt>asm.jar</tt>.
+<p>
+<tt>ASMContentHandler</tt> and <tt>SAXClassAdapter/SAXCodeAdapter</tt>
+are using <a href="asm-xml.dtd">asm-xml.dtd</a>.
+Here is the example of bytecode to bytecode XSLT transformation.
+
+<pre>
+ SAXTransformerFactory saxtf = ( SAXTransformerFactory) TransformerFactory.newInstance();
+ Templates templates = saxtf.newTemplates( xsltSource);
+
+ TransformerHandler handler = saxtf.newTransformerHandler( templates);
+ handler.setResult( new SAXResult( new ASMContentHandler( outputStream, computeMax)));
+
+ ClassReader cr = new ClassReader( bytecode);
+ cr.accept( new SAXClassAdapter( handler, cr.getVersion(), false), false);
+</pre>
+
+See JAXP and SAX documentation for more detils.
+
+<p>
+There are few illustrations of the bytecode transformation with XSLT in
+examples directory. The following XSLT procesors has been tested.
+
+<blockquote>
+<table border="1" cellspacing="0" cellpadding="3">
+<tr>
+<th>Engine</td>
+<th>javax.xml.transform.TransformerFactory property</td>
+</tr>
+
+<tr>
+<td>jd.xslt</td>
+<td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+</tr>
+
+<tr>
+<td>Saxon</td>
+<td>net.sf.saxon.TransformerFactoryImpl</td>
+</tr>
+
+<tr>
+<td>Caucho</td>
+<td>com.caucho.xsl.Xsl</td>
+</tr>
+
+<tr>
+<td>Xalan interpeter</td>
+<td>org.apache.xalan.processor.TransformerFactory</td>
+</tr>
+
+<tr>
+<td>Xalan xsltc</td>
+<td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+</tr>
+</table>
+</blockquote>
+
+@since ASM 1.4.3
+
+</body>
+</html>
[15/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
new file mode 100644
index 0000000..ceb051f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
@@ -0,0 +1,1628 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} with convenient methods to generate
+ * code. For example, using this adapter, the class below
+ *
+ * <pre>
+ * public class Example {
+ * public static void main(String[] args) {
+ * System.out.println("Hello world!");
+ * }
+ * }
+ * </pre>
+ *
+ * can be generated as follows:
+ *
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
+ *
+ * Method m = Method.getMethod("void <init> ()");
+ * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
+ * mg.loadThis();
+ * mg.invokeConstructor(Type.getType(Object.class), m);
+ * mg.returnValue();
+ * mg.endMethod();
+ *
+ * m = Method.getMethod("void main (String[])");
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
+ * mg.push("Hello world!");
+ * mg.invokeVirtual(Type.getType(PrintStream.class),
+ * Method.getMethod("void println (String)"));
+ * mg.returnValue();
+ * mg.endMethod();
+ *
+ * cw.visitEnd();
+ * </pre>
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ * @author Prashant Deva
+ */
+public class GeneratorAdapter extends LocalVariablesSorter {
+
+ private static final String CLDESC = "Ljava/lang/Class;";
+
+ private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
+
+ private static final Type BOOLEAN_TYPE = Type
+ .getObjectType("java/lang/Boolean");
+
+ private static final Type SHORT_TYPE = Type
+ .getObjectType("java/lang/Short");
+
+ private static final Type CHARACTER_TYPE = Type
+ .getObjectType("java/lang/Character");
+
+ private static final Type INTEGER_TYPE = Type
+ .getObjectType("java/lang/Integer");
+
+ private static final Type FLOAT_TYPE = Type
+ .getObjectType("java/lang/Float");
+
+ private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
+
+ private static final Type DOUBLE_TYPE = Type
+ .getObjectType("java/lang/Double");
+
+ private static final Type NUMBER_TYPE = Type
+ .getObjectType("java/lang/Number");
+
+ private static final Type OBJECT_TYPE = Type
+ .getObjectType("java/lang/Object");
+
+ private static final Method BOOLEAN_VALUE = Method
+ .getMethod("boolean booleanValue()");
+
+ private static final Method CHAR_VALUE = Method
+ .getMethod("char charValue()");
+
+ private static final Method INT_VALUE = Method.getMethod("int intValue()");
+
+ private static final Method FLOAT_VALUE = Method
+ .getMethod("float floatValue()");
+
+ private static final Method LONG_VALUE = Method
+ .getMethod("long longValue()");
+
+ private static final Method DOUBLE_VALUE = Method
+ .getMethod("double doubleValue()");
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int ADD = Opcodes.IADD;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SUB = Opcodes.ISUB;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int MUL = Opcodes.IMUL;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int DIV = Opcodes.IDIV;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int REM = Opcodes.IREM;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int NEG = Opcodes.INEG;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SHL = Opcodes.ISHL;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SHR = Opcodes.ISHR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int USHR = Opcodes.IUSHR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int AND = Opcodes.IAND;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int OR = Opcodes.IOR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int XOR = Opcodes.IXOR;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int EQ = Opcodes.IFEQ;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int NE = Opcodes.IFNE;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int LT = Opcodes.IFLT;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int GE = Opcodes.IFGE;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int GT = Opcodes.IFGT;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int LE = Opcodes.IFLE;
+
+ /**
+ * Access flags of the method visited by this adapter.
+ */
+ private final int access;
+
+ /**
+ * Return type of the method visited by this adapter.
+ */
+ private final Type returnType;
+
+ /**
+ * Argument types of the method visited by this adapter.
+ */
+ private final Type[] argumentTypes;
+
+ /**
+ * Types of the local variables of the method visited by this adapter.
+ */
+ private final List<Type> localTypes = new ArrayList<Type>();
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public GeneratorAdapter(final MethodVisitor mv, final int access,
+ final String name, final String desc) {
+ this(Opcodes.ASM5, mv, access, name, desc);
+ if (getClass() != GeneratorAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ protected GeneratorAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc) {
+ super(api, access, desc, mv);
+ this.access = access;
+ this.returnType = Type.getReturnType(desc);
+ this.argumentTypes = Type.getArgumentTypes(desc);
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param method
+ * the adapted method.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(final int access, final Method method,
+ final MethodVisitor mv) {
+ this(mv, access, null, method.getDescriptor());
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param method
+ * the adapted method.
+ * @param signature
+ * the signature of the adapted method (may be <tt>null</tt>).
+ * @param exceptions
+ * the exceptions thrown by the adapted method (may be
+ * <tt>null</tt>).
+ * @param cv
+ * the class visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(final int access, final Method method,
+ final String signature, final Type[] exceptions,
+ final ClassVisitor cv) {
+ this(access, method, cv
+ .visitMethod(access, method.getName(), method.getDescriptor(),
+ signature, getInternalNames(exceptions)));
+ }
+
+ /**
+ * Returns the internal names of the given types.
+ *
+ * @param types
+ * a set of types.
+ * @return the internal names of the given types.
+ */
+ private static String[] getInternalNames(final Type[] types) {
+ if (types == null) {
+ return null;
+ }
+ String[] names = new String[types.length];
+ for (int i = 0; i < names.length; ++i) {
+ names[i] = types[i].getInternalName();
+ }
+ return names;
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to push constants on the stack
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final boolean value) {
+ push(value ? 1 : 0);
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final int value) {
+ if (value >= -1 && value <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + value);
+ } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, value);
+ } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, value);
+ } else {
+ mv.visitLdcInsn(new Integer(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final long value) {
+ if (value == 0L || value == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Long(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final float value) {
+ int bits = Float.floatToIntBits(value);
+ if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Float(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final double value) {
+ long bits = Double.doubleToLongBits(value);
+ if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Double(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack. May be <tt>null</tt>.
+ */
+ public void push(final String value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final Type value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ switch (value.getSort()) {
+ case Type.BOOLEAN:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
+ "TYPE", CLDESC);
+ break;
+ case Type.CHAR:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
+ "TYPE", CLDESC);
+ break;
+ case Type.BYTE:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
+ CLDESC);
+ break;
+ case Type.SHORT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
+ CLDESC);
+ break;
+ case Type.INT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
+ "TYPE", CLDESC);
+ break;
+ case Type.FLOAT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
+ CLDESC);
+ break;
+ case Type.LONG:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
+ CLDESC);
+ break;
+ case Type.DOUBLE:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
+ "TYPE", CLDESC);
+ break;
+ default:
+ mv.visitLdcInsn(value);
+ }
+ }
+ }
+
+ /**
+ * Generates the instruction to push a handle on the stack.
+ *
+ * @param handle
+ * the handle to be pushed on the stack.
+ */
+ public void push(final Handle handle) {
+ mv.visitLdcInsn(handle);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store method arguments
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the index of the given method argument in the frame's local
+ * variables array.
+ *
+ * @param arg
+ * the index of a method argument.
+ * @return the index of the given method argument in the frame's local
+ * variables array.
+ */
+ private int getArgIndex(final int arg) {
+ int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+ for (int i = 0; i < arg; i++) {
+ index += argumentTypes[i].getSize();
+ }
+ return index;
+ }
+
+ /**
+ * Generates the instruction to push a local variable on the stack.
+ *
+ * @param type
+ * the type of the local variable to be loaded.
+ * @param index
+ * an index in the frame's local variables array.
+ */
+ private void loadInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a local
+ * variable.
+ *
+ * @param type
+ * the type of the local variable to be stored.
+ * @param index
+ * an index in the frame's local variables array.
+ */
+ private void storeInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
+ }
+
+ /**
+ * Generates the instruction to load 'this' on the stack.
+ */
+ public void loadThis() {
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ throw new IllegalStateException(
+ "no 'this' pointer within static method");
+ }
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ }
+
+ /**
+ * Generates the instruction to load the given method argument on the stack.
+ *
+ * @param arg
+ * the index of a method argument.
+ */
+ public void loadArg(final int arg) {
+ loadInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ /**
+ * Generates the instructions to load the given method arguments on the
+ * stack.
+ *
+ * @param arg
+ * the index of the first method argument to be loaded.
+ * @param count
+ * the number of method arguments to be loaded.
+ */
+ public void loadArgs(final int arg, final int count) {
+ int index = getArgIndex(arg);
+ for (int i = 0; i < count; ++i) {
+ Type t = argumentTypes[arg + i];
+ loadInsn(t, index);
+ index += t.getSize();
+ }
+ }
+
+ /**
+ * Generates the instructions to load all the method arguments on the stack.
+ */
+ public void loadArgs() {
+ loadArgs(0, argumentTypes.length);
+ }
+
+ /**
+ * Generates the instructions to load all the method arguments on the stack,
+ * as a single object array.
+ */
+ public void loadArgArray() {
+ push(argumentTypes.length);
+ newArray(OBJECT_TYPE);
+ for (int i = 0; i < argumentTypes.length; i++) {
+ dup();
+ push(i);
+ loadArg(i);
+ box(argumentTypes[i]);
+ arrayStore(OBJECT_TYPE);
+ }
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given
+ * method argument.
+ *
+ * @param arg
+ * the index of a method argument.
+ */
+ public void storeArg(final int arg) {
+ storeInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store local variables
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the type of the given local variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @return the type of the given local variable.
+ */
+ public Type getLocalType(final int local) {
+ return localTypes.get(local - firstLocal);
+ }
+
+ @Override
+ protected void setLocalType(final int local, final Type type) {
+ int index = local - firstLocal;
+ while (localTypes.size() < index + 1) {
+ localTypes.add(null);
+ }
+ localTypes.set(index, type);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void loadLocal(final int local) {
+ loadInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @param type
+ * the type of this local variable.
+ */
+ public void loadLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ loadInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local
+ * variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void storeLocal(final int local) {
+ storeInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local
+ * variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @param type
+ * the type of this local variable.
+ */
+ public void storeLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ storeInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to load an element from an array.
+ *
+ * @param type
+ * the type of the array element to be loaded.
+ */
+ public void arrayLoad(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ /**
+ * Generates the instruction to store an element in an array.
+ *
+ * @param type
+ * the type of the array element to be stored.
+ */
+ public void arrayStore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to manage the stack
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a POP instruction.
+ */
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ /**
+ * Generates a POP2 instruction.
+ */
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ /**
+ * Generates a DUP instruction.
+ */
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ /**
+ * Generates a DUP2 instruction.
+ */
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ /**
+ * Generates a DUP_X1 instruction.
+ */
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ /**
+ * Generates a DUP_X2 instruction.
+ */
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ /**
+ * Generates a DUP2_X1 instruction.
+ */
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ /**
+ * Generates a DUP2_X2 instruction.
+ */
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ /**
+ * Generates a SWAP instruction.
+ */
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ /**
+ * Generates the instructions to swap the top two stack values.
+ *
+ * @param prev
+ * type of the top - 1 stack value.
+ * @param type
+ * type of the top stack value.
+ */
+ public void swap(final Type prev, final Type type) {
+ if (type.getSize() == 1) {
+ if (prev.getSize() == 1) {
+ swap(); // same as dupX1(), pop();
+ } else {
+ dupX2();
+ pop();
+ }
+ } else {
+ if (prev.getSize() == 1) {
+ dup2X1();
+ pop2();
+ } else {
+ dup2X2();
+ pop2();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to do mathematical and logical operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to do the specified mathematical or logical
+ * operation.
+ *
+ * @param op
+ * a mathematical or logical operation. Must be one of ADD, SUB,
+ * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
+ * @param type
+ * the type of the operand(s) for this operation.
+ */
+ public void math(final int op, final Type type) {
+ mv.visitInsn(type.getOpcode(op));
+ }
+
+ /**
+ * Generates the instructions to compute the bitwise negation of the top
+ * stack value.
+ */
+ public void not() {
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ }
+
+ /**
+ * Generates the instruction to increment the given local variable.
+ *
+ * @param local
+ * the local variable to be incremented.
+ * @param amount
+ * the amount by which the local variable must be incremented.
+ */
+ public void iinc(final int local, final int amount) {
+ mv.visitIincInsn(local, amount);
+ }
+
+ /**
+ * Generates the instructions to cast a numerical value from one type to
+ * another.
+ *
+ * @param from
+ * the type of the top stack value
+ * @param to
+ * the type into which this value must be cast.
+ */
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
+ } else {
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
+ } else {
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to do boxing and unboxing operations
+ // ------------------------------------------------------------------------
+
+ private static Type getBoxedType(final Type type) {
+ switch (type.getSort()) {
+ case Type.BYTE:
+ return BYTE_TYPE;
+ case Type.BOOLEAN:
+ return BOOLEAN_TYPE;
+ case Type.SHORT:
+ return SHORT_TYPE;
+ case Type.CHAR:
+ return CHARACTER_TYPE;
+ case Type.INT:
+ return INTEGER_TYPE;
+ case Type.FLOAT:
+ return FLOAT_TYPE;
+ case Type.LONG:
+ return LONG_TYPE;
+ case Type.DOUBLE:
+ return DOUBLE_TYPE;
+ }
+ return type;
+ }
+
+ /**
+ * Generates the instructions to box the top stack value. This value is
+ * replaced by its boxed equivalent on top of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void box(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxed = getBoxedType(type);
+ newInstance(boxed);
+ if (type.getSize() == 2) {
+ // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+ dupX2();
+ dupX2();
+ pop();
+ } else {
+ // p -> po -> opo -> oop -> o
+ dupX1();
+ swap();
+ }
+ invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
+ new Type[] { type }));
+ }
+ }
+
+ /**
+ * Generates the instructions to box the top stack value using Java 5's
+ * valueOf() method. This value is replaced by its boxed equivalent on top
+ * of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void valueOf(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxed = getBoxedType(type);
+ invokeStatic(boxed, new Method("valueOf", boxed,
+ new Type[] { type }));
+ }
+ }
+
+ /**
+ * Generates the instructions to unbox the top stack value. This value is
+ * replaced by its unboxed equivalent on top of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void unbox(final Type type) {
+ Type t = NUMBER_TYPE;
+ Method sig = null;
+ switch (type.getSort()) {
+ case Type.VOID:
+ return;
+ case Type.CHAR:
+ t = CHARACTER_TYPE;
+ sig = CHAR_VALUE;
+ break;
+ case Type.BOOLEAN:
+ t = BOOLEAN_TYPE;
+ sig = BOOLEAN_VALUE;
+ break;
+ case Type.DOUBLE:
+ sig = DOUBLE_VALUE;
+ break;
+ case Type.FLOAT:
+ sig = FLOAT_VALUE;
+ break;
+ case Type.LONG:
+ sig = LONG_VALUE;
+ break;
+ case Type.INT:
+ case Type.SHORT:
+ case Type.BYTE:
+ sig = INT_VALUE;
+ }
+ if (sig == null) {
+ checkCast(type);
+ } else {
+ checkCast(t);
+ invokeVirtual(t, sig);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to jump to other instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new {@link Label}.
+ *
+ * @return a new {@link Label}.
+ */
+ public Label newLabel() {
+ return new Label();
+ }
+
+ /**
+ * Marks the current code position with the given label.
+ *
+ * @param label
+ * a label.
+ */
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+
+ /**
+ * Marks the current code position with a new label.
+ *
+ * @return the label that was created to mark the current code position.
+ */
+ public Label mark() {
+ Label label = new Label();
+ mv.visitLabel(label);
+ return label;
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top two stack values.
+ *
+ * @param type
+ * the type of the top two stack values.
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifCmp(final Type type, final int mode, final Label label) {
+ switch (type.getSort()) {
+ case Type.LONG:
+ mv.visitInsn(Opcodes.LCMP);
+ break;
+ case Type.DOUBLE:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
+ : Opcodes.DCMPG);
+ break;
+ case Type.FLOAT:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
+ : Opcodes.FCMPG);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ switch (mode) {
+ case EQ:
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ return;
+ case NE:
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ return;
+ }
+ throw new IllegalArgumentException("Bad comparison for type "
+ + type);
+ default:
+ int intOp = -1;
+ switch (mode) {
+ case EQ:
+ intOp = Opcodes.IF_ICMPEQ;
+ break;
+ case NE:
+ intOp = Opcodes.IF_ICMPNE;
+ break;
+ case GE:
+ intOp = Opcodes.IF_ICMPGE;
+ break;
+ case LT:
+ intOp = Opcodes.IF_ICMPLT;
+ break;
+ case LE:
+ intOp = Opcodes.IF_ICMPLE;
+ break;
+ case GT:
+ intOp = Opcodes.IF_ICMPGT;
+ break;
+ }
+ mv.visitJumpInsn(intOp, label);
+ return;
+ }
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top two integer stack values.
+ *
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifICmp(final int mode, final Label label) {
+ ifCmp(Type.INT_TYPE, mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top integer stack value with zero.
+ *
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifZCmp(final int mode, final Label label) {
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack
+ * value is null.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void ifNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack
+ * value is not null.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void ifNonNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ /**
+ * Generates a RET instruction.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void ret(final int local) {
+ mv.visitVarInsn(Opcodes.RET, local);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys
+ * the switch case keys.
+ * @param generator
+ * a generator to generate the code for the switch cases.
+ */
+ public void tableSwitch(final int[] keys,
+ final TableSwitchGenerator generator) {
+ float density;
+ if (keys.length == 0) {
+ density = 0;
+ } else {
+ density = (float) keys.length
+ / (keys[keys.length - 1] - keys[0] + 1);
+ }
+ tableSwitch(keys, generator, density >= 0.5f);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys
+ * the switch case keys.
+ * @param generator
+ * a generator to generate the code for the switch cases.
+ * @param useTable
+ * <tt>true</tt> to use a TABLESWITCH instruction, or
+ * <tt>false</tt> to use a LOOKUPSWITCH instruction.
+ */
+ public void tableSwitch(final int[] keys,
+ final TableSwitchGenerator generator, final boolean useTable) {
+ for (int i = 1; i < keys.length; ++i) {
+ if (keys[i] < keys[i - 1]) {
+ throw new IllegalArgumentException(
+ "keys must be sorted ascending");
+ }
+ }
+ Label def = newLabel();
+ Label end = newLabel();
+ if (keys.length > 0) {
+ int len = keys.length;
+ int min = keys[0];
+ int max = keys[len - 1];
+ int range = max - min + 1;
+ if (useTable) {
+ Label[] labels = new Label[range];
+ Arrays.fill(labels, def);
+ for (int i = 0; i < len; ++i) {
+ labels[keys[i] - min] = newLabel();
+ }
+ mv.visitTableSwitchInsn(min, max, def, labels);
+ for (int i = 0; i < range; ++i) {
+ Label label = labels[i];
+ if (label != def) {
+ mark(label);
+ generator.generateCase(i + min, end);
+ }
+ }
+ } else {
+ Label[] labels = new Label[len];
+ for (int i = 0; i < len; ++i) {
+ labels[i] = newLabel();
+ }
+ mv.visitLookupSwitchInsn(def, keys, labels);
+ for (int i = 0; i < len; ++i) {
+ mark(labels[i]);
+ generator.generateCase(keys[i], end);
+ }
+ }
+ }
+ mark(def);
+ generator.generateDefault();
+ mark(end);
+ }
+
+ /**
+ * Generates the instruction to return the top stack value to the caller.
+ */
+ public void returnValue() {
+ mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a get field or set field instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param ownerType
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param fieldType
+ * the type of the field.
+ */
+ private void fieldInsn(final int opcode, final Type ownerType,
+ final String name, final Type fieldType) {
+ mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
+ fieldType.getDescriptor());
+ }
+
+ /**
+ * Generates the instruction to push the value of a static field on the
+ * stack.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void getStatic(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.GETSTATIC, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a static field.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void putStatic(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to push the value of a non static field on the
+ * stack.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void getField(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.GETFIELD, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a non static
+ * field.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void putField(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.PUTFIELD, owner, name, type);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to invoke methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates an invoke method instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param type
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ private void invokeInsn(final int opcode, final Type type,
+ final Method method, final boolean itf) {
+ String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
+ : type.getInternalName();
+ mv.visitMethodInsn(opcode, owner, method.getName(),
+ method.getDescriptor(), itf);
+ }
+
+ /**
+ * Generates the instruction to invoke a normal method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeVirtual(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke a constructor.
+ *
+ * @param type
+ * the class in which the constructor is defined.
+ * @param method
+ * the constructor to be invoked.
+ */
+ public void invokeConstructor(final Type type, final Method method) {
+ invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke a static method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeStatic(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke an interface method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeInterface(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
+ }
+
+ /**
+ * Generates an invokedynamic instruction.
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the
+ * array so a caller should expect that this array may change.
+ */
+ public void invokeDynamic(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to create objects and arrays
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a type dependent instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param type
+ * the instruction's operand.
+ */
+ private void typeInsn(final int opcode, final Type type) {
+ mv.visitTypeInsn(opcode, type.getInternalName());
+ }
+
+ /**
+ * Generates the instruction to create a new object.
+ *
+ * @param type
+ * the class of the object to be created.
+ */
+ public void newInstance(final Type type) {
+ typeInsn(Opcodes.NEW, type);
+ }
+
+ /**
+ * Generates the instruction to create a new array.
+ *
+ * @param type
+ * the type of the array elements.
+ */
+ public void newArray(final Type type) {
+ int typ;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ typ = Opcodes.T_BOOLEAN;
+ break;
+ case Type.CHAR:
+ typ = Opcodes.T_CHAR;
+ break;
+ case Type.BYTE:
+ typ = Opcodes.T_BYTE;
+ break;
+ case Type.SHORT:
+ typ = Opcodes.T_SHORT;
+ break;
+ case Type.INT:
+ typ = Opcodes.T_INT;
+ break;
+ case Type.FLOAT:
+ typ = Opcodes.T_FLOAT;
+ break;
+ case Type.LONG:
+ typ = Opcodes.T_LONG;
+ break;
+ case Type.DOUBLE:
+ typ = Opcodes.T_DOUBLE;
+ break;
+ default:
+ typeInsn(Opcodes.ANEWARRAY, type);
+ return;
+ }
+ mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+ }
+
+ // ------------------------------------------------------------------------
+ // Miscelaneous instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to compute the length of an array.
+ */
+ public void arrayLength() {
+ mv.visitInsn(Opcodes.ARRAYLENGTH);
+ }
+
+ /**
+ * Generates the instruction to throw an exception.
+ */
+ public void throwException() {
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+
+ /**
+ * Generates the instructions to create and throw an exception. The
+ * exception class must have a constructor with a single String argument.
+ *
+ * @param type
+ * the class of the exception to be thrown.
+ * @param msg
+ * the detailed message of the exception.
+ */
+ public void throwException(final Type type, final String msg) {
+ newInstance(type);
+ dup();
+ push(msg);
+ invokeConstructor(type, Method.getMethod("void <init> (String)"));
+ throwException();
+ }
+
+ /**
+ * Generates the instruction to check that the top stack value is of the
+ * given type.
+ *
+ * @param type
+ * a class or interface type.
+ */
+ public void checkCast(final Type type) {
+ if (!type.equals(OBJECT_TYPE)) {
+ typeInsn(Opcodes.CHECKCAST, type);
+ }
+ }
+
+ /**
+ * Generates the instruction to test if the top stack value is of the given
+ * type.
+ *
+ * @param type
+ * a class or interface type.
+ */
+ public void instanceOf(final Type type) {
+ typeInsn(Opcodes.INSTANCEOF, type);
+ }
+
+ /**
+ * Generates the instruction to get the monitor of the top stack value.
+ */
+ public void monitorEnter() {
+ mv.visitInsn(Opcodes.MONITORENTER);
+ }
+
+ /**
+ * Generates the instruction to release the monitor of the top stack value.
+ */
+ public void monitorExit() {
+ mv.visitInsn(Opcodes.MONITOREXIT);
+ }
+
+ // ------------------------------------------------------------------------
+ // Non instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Marks the end of the visited method.
+ */
+ public void endMethod() {
+ if ((access & Opcodes.ACC_ABSTRACT) == 0) {
+ mv.visitMaxs(0, 0);
+ }
+ mv.visitEnd();
+ }
+
+ /**
+ * Marks the start of an exception handler.
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param exception
+ * internal name of the type of exceptions handled by the
+ * handler.
+ */
+ public void catchException(final Label start, final Label end,
+ final Type exception) {
+ if (exception == null) {
+ mv.visitTryCatchBlock(start, end, mark(), null);
+ } else {
+ mv.visitTryCatchBlock(start, end, mark(),
+ exception.getInternalName());
+ }
+ }
+}
[21/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
index dced23c..8c8e29b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
@@ -30,19 +30,20 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java class. The methods of this class must be called
- * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * A visitor to visit a Java class. The methods of this class must be called in
+ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
- * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
- *
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
+ * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
+ * <tt>visitEnd</tt>.
+ *
* @author Eric Bruneton
*/
public abstract class ClassVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -54,9 +55,10 @@ public abstract class ClassVisitor {
/**
* Constructs a new {@link ClassVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassVisitor(final int api) {
this(api, null);
@@ -64,47 +66,49 @@ public abstract class ClassVisitor {
/**
* Constructs a new {@link ClassVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param cv the class visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param cv
+ * the class visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.cv = cv;
}
/**
* Visits the header of the class.
- *
- * @param version the class version.
- * @param access the class's access flags (see {@link Opcodes}). This
- * parameter also indicates if the class is deprecated.
- * @param name the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param signature the signature of this class. May be <tt>null</tt> if
- * the class is not a generic one, and does not extend or implement
- * generic classes or interfaces.
- * @param superName the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For interfaces,
- * the super class is {@link Object}. May be <tt>null</tt>, but
- * only for the {@link Object} class.
- * @param interfaces the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param version
+ * the class version.
+ * @param access
+ * the class's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the class is deprecated.
+ * @param name
+ * the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param signature
+ * the signature of this class. May be <tt>null</tt> if the class
+ * is not a generic one, and does not extend or implement generic
+ * classes or interfaces.
+ * @param superName
+ * the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For
+ * interfaces, the super class is {@link Object}. May be
+ * <tt>null</tt>, but only for the {@link Object} class.
+ * @param interfaces
+ * the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- public void visit(
- int version,
- int access,
- String name,
- String signature,
- String superName,
- String[] interfaces)
- {
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
}
@@ -112,12 +116,14 @@ public abstract class ClassVisitor {
/**
* Visits the source of the class.
- *
- * @param source the name of the source file from which the class was
- * compiled. May be <tt>null</tt>.
- * @param debug additional debug information to compute the correspondance
- * between source and compiled elements of the class. May be
- * <tt>null</tt>.
+ *
+ * @param source
+ * the name of the source file from which the class was compiled.
+ * May be <tt>null</tt>.
+ * @param debug
+ * additional debug information to compute the correspondance
+ * between source and compiled elements of the class. May be
+ * <tt>null</tt>.
*/
public void visitSource(String source, String debug) {
if (cv != null) {
@@ -128,26 +134,31 @@ public abstract class ClassVisitor {
/**
* Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class.
- *
- * @param owner internal name of the enclosing class of the class.
- * @param name the name of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- * @param desc the descriptor of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
+ *
+ * @param owner
+ * internal name of the enclosing class of the class.
+ * @param name
+ * the name of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ * @param desc
+ * the descriptor of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
- if (cv != null) {
+ if (cv != null) {
cv.visitOuterClass(owner, name, desc);
}
}
/**
* Visits an annotation of the class.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -159,9 +170,43 @@ public abstract class ClassVisitor {
}
/**
+ * Visits an annotation on a type in the class signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
+ * CLASS_TYPE_PARAMETER},
+ * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
+ * CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (cv != null) {
+ return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a non standard attribute of the class.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (cv != null) {
@@ -172,24 +217,23 @@ public abstract class ClassVisitor {
/**
* Visits information about an inner class. This inner class is not
* necessarily a member of the class being visited.
- *
- * @param name the internal name of an inner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param outerName the internal name of the class to which the inner class
- * belongs (see {@link Type#getInternalName() getInternalName}). May
- * be <tt>null</tt> for not member classes.
- * @param innerName the (simple) name of the inner class inside its
- * enclosing class. May be <tt>null</tt> for anonymous inner
- * classes.
- * @param access the access flags of the inner class as originally declared
- * in the enclosing class.
+ *
+ * @param name
+ * the internal name of an inner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param outerName
+ * the internal name of the class to which the inner class
+ * belongs (see {@link Type#getInternalName() getInternalName}).
+ * May be <tt>null</tt> for not member classes.
+ * @param innerName
+ * the (simple) name of the inner class inside its enclosing
+ * class. May be <tt>null</tt> for anonymous inner classes.
+ * @param access
+ * the access flags of the inner class as originally declared in
+ * the enclosing class.
*/
- public void visitInnerClass(
- String name,
- String outerName,
- String innerName,
- int access)
- {
+ public void visitInnerClass(String name, String outerName,
+ String innerName, int access) {
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
@@ -197,34 +241,33 @@ public abstract class ClassVisitor {
/**
* Visits a field of the class.
- *
- * @param access the field's access flags (see {@link Opcodes}). This
- * parameter also indicates if the field is synthetic and/or
- * deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- * @param signature the field's signature. May be <tt>null</tt> if the
- * field's type does not use generic types.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must
- * be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String} (for <tt>int</tt>,
- * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
- * respectively). <i>This parameter is only used for static fields</i>.
- * Its value is ignored for non static fields, which must be
- * initialized through bytecode instructions in constructors or
- * methods.
+ *
+ * @param access
+ * the field's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt> if the field's
+ * type does not use generic types.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String} (for <tt>int</tt>,
+ * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+ * respectively). <i>This parameter is only used for static
+ * fields</i>. Its value is ignored for non static fields, which
+ * must be initialized through bytecode instructions in
+ * constructors or methods.
* @return a visitor to visit field annotations and attributes, or
- * <tt>null</tt> if this class visitor is not interested in
- * visiting these annotations and attributes.
+ * <tt>null</tt> if this class visitor is not interested in visiting
+ * these annotations and attributes.
*/
- public FieldVisitor visitField(
- int access,
- String name,
- String desc,
- String signature,
- Object value)
- {
+ public FieldVisitor visitField(int access, String name, String desc,
+ String signature, Object value) {
if (cv != null) {
return cv.visitField(access, name, desc, signature, value);
}
@@ -233,31 +276,31 @@ public abstract class ClassVisitor {
/**
* Visits a method of the class. This method <i>must</i> return a new
- * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
- * called, i.e., it should not return a previously returned visitor.
- *
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param signature the method's signature. May be <tt>null</tt> if the
- * method parameters, return type and exceptions do not use generic
- * types.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
+ * i.e., it should not return a previously returned visitor.
+ *
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt> if the method
+ * parameters, return type and exceptions do not use generic
+ * types.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
* @return an object to visit the byte code of the method, or <tt>null</tt>
* if this class visitor is not interested in visiting the code of
* this method.
*/
- public MethodVisitor visitMethod(
- int access,
- String name,
- String desc,
- String signature,
- String[] exceptions)
- {
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, desc, signature, exceptions);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
index ab7547b..6cd89a5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -35,7 +35,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* file format. It can be used alone, to generate a Java class "from scratch",
* or with one or more {@link ClassReader ClassReader} and adapter class visitor
* to generate a modified class from one or more existing Java classes.
- *
+ *
* @author Eric Bruneton
*/
public class ClassWriter extends ClassVisitor {
@@ -47,7 +47,7 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
* method will be ignored, and computed automatically from the signature and
* the bytecode of each method.
- *
+ *
* @see #ClassWriter(int)
*/
public static final int COMPUTE_MAXS = 1;
@@ -60,18 +60,24 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies
* computeMaxs.
- *
+ *
* @see #ClassWriter(int)
*/
public static final int COMPUTE_FRAMES = 2;
/**
- * Pseudo access flag to distinguish between the synthetic attribute and
- * the synthetic access flag.
+ * Pseudo access flag to distinguish between the synthetic attribute and the
+ * synthetic access flag.
*/
static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
/**
+ * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
+ */
+ static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
+ / Opcodes.ACC_SYNTHETIC;
+
+ /**
* The type of instructions without any argument.
*/
static final int NOARG_INSN = 0;
@@ -238,8 +244,8 @@ public class ClassWriter extends ClassVisitor {
/**
* The base value for all CONSTANT_MethodHandle constant pool items.
- * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
- * 9 different items.
+ * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
+ * different items.
*/
static final int HANDLE_BASE = 20;
@@ -266,9 +272,8 @@ public class ClassWriter extends ClassVisitor {
static final int TYPE_MERGED = 32;
/**
- * The type of BootstrapMethods items. These items are stored in a
- * special class attribute named BootstrapMethods and
- * not in the constant pool.
+ * The type of BootstrapMethods items. These items are stored in a special
+ * class attribute named BootstrapMethods and not in the constant pool.
*/
static final int BSM = 33;
@@ -327,10 +332,10 @@ public class ClassWriter extends ClassVisitor {
* necessarily be stored in the constant pool. This type table is used by
* the control flow and data flow analysis algorithm used to compute stack
* map frames from scratch. This array associates to each index <tt>i</tt>
- * the Item whose index is <tt>i</tt>. All Item objects stored in this
- * array are also stored in the {@link #items} hash table. These two arrays
- * allow to retrieve an Item from its index or, conversely, to get the index
- * of an Item from its value. Each Item stores an internal name in its
+ * the Item whose index is <tt>i</tt>. All Item objects stored in this array
+ * are also stored in the {@link #items} hash table. These two arrays allow
+ * to retrieve an Item from its index or, conversely, to get the index of an
+ * Item from its value. Each Item stores an internal name in its
* {@link Item#strVal1} field.
*/
Item[] typeTable;
@@ -412,6 +417,16 @@ public class ClassWriter extends ClassVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this class.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this class.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The non standard attributes of this class.
*/
private Attribute attrs;
@@ -439,16 +454,16 @@ public class ClassWriter extends ClassVisitor {
/**
* The fields of this class. These fields are stored in a linked list of
* {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the first element of
- * this list.
+ * {@link FieldWriter#fv} field. This field stores the first element of this
+ * list.
*/
FieldWriter firstField;
/**
* The fields of this class. These fields are stored in a linked list of
* {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the last element of
- * this list.
+ * {@link FieldWriter#fv} field. This field stores the last element of this
+ * list.
*/
FieldWriter lastField;
@@ -463,8 +478,8 @@ public class ClassWriter extends ClassVisitor {
/**
* The methods of this class. These methods are stored in a linked list of
* {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the last element of
- * this list.
+ * {@link MethodWriter#mv} field. This field stores the last element of this
+ * list.
*/
MethodWriter lastMethod;
@@ -472,12 +487,12 @@ public class ClassWriter extends ClassVisitor {
* <tt>true</tt> if the maximum stack size and number of local variables
* must be automatically computed.
*/
- private final boolean computeMaxs;
+ private boolean computeMaxs;
/**
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
*/
- private final boolean computeFrames;
+ private boolean computeFrames;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
@@ -583,12 +598,14 @@ public class ClassWriter extends ClassVisitor {
/**
* Constructs a new {@link ClassWriter} object.
- *
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ *
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
index = 1;
pool = new ByteVector();
items = new Item[256];
@@ -605,27 +622,33 @@ public class ClassWriter extends ClassVisitor {
* Constructs a new {@link ClassWriter} object and enables optimizations for
* "mostly add" bytecode transformations. These optimizations are the
* following:
- *
- * <ul> <li>The constant pool from the original class is copied as is in the
- * new class, which saves time. New constant pool entries will be added at
- * the end if necessary, but unused constant pool entries <i>won't be
- * removed</i>.</li> <li>Methods that are not transformed are copied as is
- * in the new class, directly from the original class bytecode (i.e. without
- * emitting visit events for all the method instructions), which saves a
- * <i>lot</i> of time. Untransformed methods are detected by the fact that
- * the {@link ClassReader} receives {@link MethodVisitor} objects that come
- * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
- * instance).</li> </ul>
- *
- * @param classReader the {@link ClassReader} used to read the original
- * class. It will be used to copy the entire constant pool from the
- * original class and also to copy other fragments of original
- * bytecode where applicable.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. <i>These option flags do not affect methods that
- * are copied as is in the new class. This means that the maximum
- * stack size nor the stack frames will be computed for these
- * methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ *
+ * <ul>
+ * <li>The constant pool from the original class is copied as is in the new
+ * class, which saves time. New constant pool entries will be added at the
+ * end if necessary, but unused constant pool entries <i>won't be
+ * removed</i>.</li>
+ * <li>Methods that are not transformed are copied as is in the new class,
+ * directly from the original class bytecode (i.e. without emitting visit
+ * events for all the method instructions), which saves a <i>lot</i> of
+ * time. Untransformed methods are detected by the fact that the
+ * {@link ClassReader} receives {@link MethodVisitor} objects that come from
+ * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+ * instance).</li>
+ * </ul>
+ *
+ * @param classReader
+ * the {@link ClassReader} used to read the original class. It
+ * will be used to copy the entire constant pool from the
+ * original class and also to copy other fragments of original
+ * bytecode where applicable.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. <i>These option flags do not affect methods
+ * that are copied as is in the new class. This means that the
+ * maximum stack size nor the stack frames will be computed for
+ * these methods</i>. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final ClassReader classReader, final int flags) {
this(flags);
@@ -638,14 +661,9 @@ public class ClassWriter extends ClassVisitor {
// ------------------------------------------------------------------------
@Override
- public final void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public final void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces) {
this.version = version;
this.access = access;
this.name = newClass(name);
@@ -669,16 +687,14 @@ public class ClassWriter extends ClassVisitor {
sourceFile = newUTF8(file);
}
if (debug != null) {
- sourceDebug = new ByteVector().putUTF8(debug);
+ sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+ Integer.MAX_VALUE);
}
}
@Override
- public final void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public final void visitOuterClass(final String owner, final String name,
+ final String desc) {
enclosingMethodOwner = newClass(owner);
if (name != null && desc != null) {
enclosingMethod = newNameType(name, desc);
@@ -686,10 +702,8 @@ public class ClassWriter extends ClassVisitor {
}
@Override
- public final AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public final AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -708,55 +722,76 @@ public class ClassWriter extends ClassVisitor {
}
@Override
+ public final AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public final void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
}
@Override
- public final void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
if (innerClasses == null) {
innerClasses = new ByteVector();
}
- ++innerClassesCount;
- innerClasses.putShort(name == null ? 0 : newClass(name));
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
+ // �4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+ // constant_pool table which represents a class or interface C that is
+ // not a package member must have exactly one corresponding entry in the
+ // classes array". To avoid duplicates we keep track in the intVal field
+ // of the Item of each CONSTANT_Class_info entry C whether an inner
+ // class entry has already been added for C (this field is unused for
+ // class entries, and changing its value does not change the hashcode
+ // and equality tests). If so we store the index of this inner class
+ // entry (plus one) in intVal. This hack allows duplicate detection in
+ // O(1) time.
+ Item nameItem = newClassItem(name);
+ if (nameItem.intVal == 0) {
+ ++innerClassesCount;
+ innerClasses.putShort(nameItem.index);
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ nameItem.intVal = innerClassesCount;
+ } else {
+ // Compare the inner classes entry nameItem.intVal - 1 with the
+ // arguments of this method and throw an exception if there is a
+ // difference?
+ }
}
@Override
- public final FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public final FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
return new FieldWriter(this, access, name, desc, signature, value);
}
@Override
- public final MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- return new MethodWriter(this,
- access,
- name,
- desc,
- signature,
- exceptions,
- computeMaxs,
- computeFrames);
+ public final MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ return new MethodWriter(this, access, name, desc, signature,
+ exceptions, computeMaxs, computeFrames);
}
@Override
@@ -769,11 +804,11 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the bytecode of the class that was build with this class writer.
- *
+ *
* @return the bytecode of the class that was build with this class writer.
*/
public byte[] toByteArray() {
- if (index > Short.MAX_VALUE) {
+ if (index > 0xFFFF) {
throw new RuntimeException("Class file too large!");
}
// computes the real size of the bytecode of this class
@@ -793,8 +828,9 @@ public class ClassWriter extends ClassVisitor {
mb = (MethodWriter) mb.mv;
}
int attributeCount = 0;
- if (bootstrapMethods != null) { // we put it as first argument in order
- // to improve a bit ClassReader.copyBootstrapMethods
+ if (bootstrapMethods != null) {
+ // we put it as first attribute in order to improve a bit
+ // ClassReader.copyBootstrapMethods
++attributeCount;
size += 8 + bootstrapMethods.length;
newUTF8("BootstrapMethods");
@@ -811,7 +847,7 @@ public class ClassWriter extends ClassVisitor {
}
if (sourceDebug != null) {
++attributeCount;
- size += sourceDebug.length + 4;
+ size += sourceDebug.length + 6;
newUTF8("SourceDebugExtension");
}
if (enclosingMethodOwner != 0) {
@@ -824,12 +860,13 @@ public class ClassWriter extends ClassVisitor {
size += 6;
newUTF8("Deprecated");
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
- size += 6;
- newUTF8("Synthetic");
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Synthetic");
+ }
}
if (innerClasses != null) {
++attributeCount;
@@ -846,6 +883,16 @@ public class ClassWriter extends ClassVisitor {
size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations");
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ size += 8 + tanns.getSize();
+ newUTF8("RuntimeVisibleTypeAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ size += 8 + itanns.getSize();
+ newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
@@ -856,9 +903,8 @@ public class ClassWriter extends ClassVisitor {
ByteVector out = new ByteVector(size);
out.putInt(0xCAFEBABE).putInt(version);
out.putShort(index).putByteArray(pool.data, 0, pool.length);
- int mask = Opcodes.ACC_DEPRECATED
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
out.putShort(access & ~mask).putShort(name).putShort(superName);
out.putShort(interfaceCount);
for (int i = 0; i < interfaceCount; ++i) {
@@ -877,9 +923,10 @@ public class ClassWriter extends ClassVisitor {
mb = (MethodWriter) mb.mv;
}
out.putShort(attributeCount);
- if (bootstrapMethods != null) { // should be the first class attribute ?
+ if (bootstrapMethods != null) {
out.putShort(newUTF8("BootstrapMethods"));
- out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+ out.putInt(bootstrapMethods.length + 2).putShort(
+ bootstrapMethodsCount);
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
}
if (ClassReader.SIGNATURES && signature != 0) {
@@ -889,9 +936,9 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
}
if (sourceDebug != null) {
- int len = sourceDebug.length - 2;
+ int len = sourceDebug.length;
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
- out.putByteArray(sourceDebug.data, 2, len);
+ out.putByteArray(sourceDebug.data, 0, len);
}
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
@@ -900,10 +947,11 @@ public class ClassWriter extends ClassVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(newUTF8("Deprecated")).putInt(0);
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(newUTF8("Synthetic")).putInt(0);
+ }
}
if (innerClasses != null) {
out.putShort(newUTF8("InnerClasses"));
@@ -918,13 +966,34 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
- ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
- new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
- return cw.toByteArray();
+ anns = null;
+ ianns = null;
+ attrs = null;
+ innerClassesCount = 0;
+ innerClasses = null;
+ bootstrapMethodsCount = 0;
+ bootstrapMethods = null;
+ firstField = null;
+ lastField = null;
+ firstMethod = null;
+ lastMethod = null;
+ computeMaxs = false;
+ computeFrames = true;
+ invalidFrames = false;
+ new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+ return toByteArray();
}
return out.data;
}
@@ -936,11 +1005,12 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
- *
- * @param cst the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double}, a {@link String} or a
- * {@link Type}.
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double}, a {@link String} or a
+ * {@link Type}.
* @return a new or already existing constant item with the given value.
*/
Item newConstItem(final Object cst) {
@@ -973,12 +1043,12 @@ public class ClassWriter extends ClassVisitor {
} else if (cst instanceof Type) {
Type t = (Type) cst;
int s = t.getSort();
- if (s == Type.ARRAY) {
- return newClassItem(t.getDescriptor());
- } else if (s == Type.OBJECT) {
+ if (s == Type.OBJECT) {
return newClassItem(t.getInternalName());
- } else { // s == Type.METHOD
+ } else if (s == Type.METHOD) {
return newMethodTypeItem(t.getDescriptor());
+ } else { // s == primitive type or array
+ return newClassItem(t.getDescriptor());
}
} else if (cst instanceof Handle) {
Handle h = (Handle) cst;
@@ -993,10 +1063,11 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param cst the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
* @return the index of a new or already existing constant item with the
* given value.
*/
@@ -1009,8 +1080,9 @@ public class ClassWriter extends ClassVisitor {
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
- *
- * @param value the String value.
+ *
+ * @param value
+ * the String value.
* @return the index of a new or already existing UTF8 item.
*/
public int newUTF8(final String value) {
@@ -1029,8 +1101,9 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param value the internal name of the class.
+ *
+ * @param value
+ * the internal name of the class.
* @return a new or already existing class reference item.
*/
Item newClassItem(final String value) {
@@ -1049,8 +1122,9 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param value the internal name of the class.
+ *
+ * @param value
+ * the internal name of the class.
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
@@ -1062,8 +1136,9 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc method descriptor of the method type.
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
* @return a new or already existing method type reference item.
*/
Item newMethodTypeItem(final String methodDesc) {
@@ -1082,8 +1157,9 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc method descriptor of the method type.
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
* @return the index of a new or already existing method type reference
* item.
*/
@@ -1096,34 +1172,35 @@ public class ClassWriter extends ClassVisitor {
* if the constant pool already contains a similar item. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
- *
- * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method owner class.
- * @param name the name of the field or method.
- * @param desc the descriptor of the field or method.
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
* @return a new or an already existing method type reference item.
*/
- Item newHandleItem(
- final int tag,
- final String owner,
- final String name,
- final String desc)
- {
+ Item newHandleItem(final int tag, final String owner, final String name,
+ final String desc) {
key4.set(HANDLE_BASE + tag, owner, name, desc);
Item result = get(key4);
if (result == null) {
if (tag <= Opcodes.H_PUTSTATIC) {
put112(HANDLE, tag, newField(owner, name, desc));
} else {
- put112(HANDLE, tag, newMethod(owner,
- name,
- desc,
- tag == Opcodes.H_INVOKEINTERFACE));
+ put112(HANDLE,
+ tag,
+ newMethod(owner, name, desc,
+ tag == Opcodes.H_INVOKEINTERFACE));
}
result = new Item(index++, key4);
put(result);
@@ -1132,29 +1209,30 @@ public class ClassWriter extends ClassVisitor {
}
/**
- * Adds a handle to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method owner class.
- * @param name the name of the field or method.
- * @param desc the descriptor of the field or method.
+ * Adds a handle to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
* @return the index of a new or already existing method type reference
* item.
*/
- public int newHandle(
- final int tag,
- final String owner,
- final String name,
- final String desc)
- {
+ public int newHandle(final int tag, final String owner, final String name,
+ final String desc) {
return newHandleItem(tag, owner, name, desc).index;
}
@@ -1163,20 +1241,20 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param name name of the invoked method.
- * @param desc descriptor of the invoke method.
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments.
- *
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
* @return a new or an already existing invokedynamic type reference item.
*/
- Item newInvokeDynamicItem(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ Item newInvokeDynamicItem(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
// cache for performance
ByteVector bootstrapMethods = this.bootstrapMethods;
if (bootstrapMethods == null) {
@@ -1186,9 +1264,7 @@ public class ClassWriter extends ClassVisitor {
int position = bootstrapMethods.length; // record current position
int hashCode = bsm.hashCode();
- bootstrapMethods.putShort(newHandle(bsm.tag,
- bsm.owner,
- bsm.name,
+ bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
bsm.desc));
int argsLength = bsmArgs.length;
@@ -1249,35 +1325,37 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param name name of the invoked method.
- * @param desc descriptor of the invoke method.
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments.
- *
- * @return the index of a new or already existing invokedynamic
- * reference item.
- */
- public int newInvokeDynamic(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
+ * @return the index of a new or already existing invokedynamic reference
+ * item.
+ */
+ public int newInvokeDynamic(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
}
/**
* Adds a field reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
- *
- * @param owner the internal name of the field's owner class.
- * @param name the field's name.
- * @param desc the field's descriptor.
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
* @return a new or already existing field reference item.
*/
- Item newFieldItem(final String owner, final String name, final String desc)
- {
+ Item newFieldItem(final String owner, final String name, final String desc) {
key3.set(FIELD, owner, name, desc);
Item result = get(key3);
if (result == null) {
@@ -1293,33 +1371,35 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the field's owner class.
- * @param name the field's name.
- * @param desc the field's descriptor.
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
* @return the index of a new or already existing field reference item.
*/
- public int newField(final String owner, final String name, final String desc)
- {
+ public int newField(final String owner, final String name, final String desc) {
return newFieldItem(owner, name, desc).index;
}
/**
* Adds a method reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
* @return a new or already existing method reference item.
*/
- Item newMethodItem(
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
+ Item newMethodItem(final String owner, final String name,
+ final String desc, final boolean itf) {
int type = itf ? IMETH : METH;
key3.set(type, owner, name, desc);
Item result = get(key3);
@@ -1336,27 +1416,28 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
* @return the index of a new or already existing method reference item.
*/
- public int newMethod(
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
+ public int newMethod(final String owner, final String name,
+ final String desc, final boolean itf) {
return newMethodItem(owner, name, desc, itf).index;
}
/**
* Adds an integer to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
- *
- * @param value the int value.
+ *
+ * @param value
+ * the int value.
* @return a new or already existing int item.
*/
Item newInteger(final int value) {
@@ -1373,8 +1454,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a float to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the float value.
+ *
+ * @param value
+ * the float value.
* @return a new or already existing float item.
*/
Item newFloat(final float value) {
@@ -1391,8 +1473,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a long to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the long value.
+ *
+ * @param value
+ * the long value.
* @return a new or already existing long item.
*/
Item newLong(final long value) {
@@ -1410,8 +1493,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a double to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the double value.
+ *
+ * @param value
+ * the double value.
* @return a new or already existing double item.
*/
Item newDouble(final double value) {
@@ -1429,8 +1513,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a string to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the String value.
+ *
+ * @param value
+ * the String value.
* @return a new or already existing string item.
*/
private Item newString(final String value) {
@@ -1449,9 +1534,11 @@ public class ClassWriter extends ClassVisitor {
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
- *
- * @param name a name.
- * @param desc a type descriptor.
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
* @return the index of a new or already existing name and type item.
*/
public int newNameType(final String name, final String desc) {
@@ -1461,9 +1548,11 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
- *
- * @param name a name.
- * @param desc a type descriptor.
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
* @return a new or already existing name and type item.
*/
Item newNameTypeItem(final String name, final String desc) {
@@ -1480,8 +1569,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds the given internal name to {@link #typeTable} and returns its index.
* Does nothing if the type table already contains this internal name.
- *
- * @param type the internal name to be added to the type table.
+ *
+ * @param type
+ * the internal name to be added to the type table.
* @return the index of this internal name in the type table.
*/
int addType(final String type) {
@@ -1497,10 +1587,12 @@ public class ClassWriter extends ClassVisitor {
* Adds the given "uninitialized" type to {@link #typeTable} and returns its
* index. This method is used for UNINITIALIZED types, made of an internal
* name and a bytecode offset.
- *
- * @param type the internal name to be added to the type table.
- * @param offset the bytecode offset of the NEW instruction that created
- * this UNINITIALIZED type value.
+ *
+ * @param type
+ * the internal name to be added to the type table.
+ * @param offset
+ * the bytecode offset of the NEW instruction that created this
+ * UNINITIALIZED type value.
* @return the index of this internal name in the type table.
*/
int addUninitializedType(final String type, final int offset) {
@@ -1517,8 +1609,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds the given Item to {@link #typeTable}.
- *
- * @param item the value to be added to the type table.
+ *
+ * @param item
+ * the value to be added to the type table.
* @return the added Item, which a new Item instance with the same value as
* the given Item.
*/
@@ -1543,9 +1636,11 @@ public class ClassWriter extends ClassVisitor {
* method calls {@link #getCommonSuperClass} and caches the result in the
* {@link #items} hash table to speedup future calls with the same
* parameters.
- *
- * @param type1 index of an internal name in {@link #typeTable}.
- * @param type2 index of an internal name in {@link #typeTable}.
+ *
+ * @param type1
+ * index of an internal name in {@link #typeTable}.
+ * @param type2
+ * index of an internal name in {@link #typeTable}.
* @return the index of the common super type of the two given types.
*/
int getMergedType(final int type1, final int type2) {
@@ -1565,20 +1660,21 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the common super type of the two given types. The default
- * implementation of this method <i>loads<i> the two given classes and uses
+ * implementation of this method <i>loads</i> the two given classes and uses
* the java.lang.Class methods to find the common super class. It can be
* overridden to compute this common super type in other ways, in particular
* without actually loading any class, or to take into account the class
* that is currently being generated by this ClassWriter, which can of
* course not be loaded since it is under construction.
- *
- * @param type1 the internal name of a class.
- * @param type2 the internal name of another class.
+ *
+ * @param type1
+ * the internal name of a class.
+ * @param type2
+ * the internal name of another class.
* @return the internal name of the common super class of the two given
* classes.
*/
- protected String getCommonSuperClass(final String type1, final String type2)
- {
+ protected String getCommonSuperClass(final String type1, final String type2) {
Class<?> c, d;
ClassLoader classLoader = getClass().getClassLoader();
try {
@@ -1606,8 +1702,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the constant pool's hash table item which is equal to the given
* item.
- *
- * @param key a constant pool item.
+ *
+ * @param key
+ * a constant pool item.
* @return the constant pool's hash table item which is equal to the given
* item, or <tt>null</tt> if there is no such item.
*/
@@ -1622,8 +1719,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts the given item in the constant pool's hash table. The hash table
* <i>must</i> not already contains this item.
- *
- * @param i the item to be added to the constant pool's hash table.
+ *
+ * @param i
+ * the item to be added to the constant pool's hash table.
*/
private void put(final Item i) {
if (index + typeCount > threshold) {
@@ -1650,10 +1748,13 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts one byte and two shorts into the constant pool.
- *
- * @param b a byte.
- * @param s1 a short.
- * @param s2 another short.
+ *
+ * @param b
+ * a byte.
+ * @param s1
+ * a short.
+ * @param s2
+ * another short.
*/
private void put122(final int b, final int s1, final int s2) {
pool.put12(b, s1).putShort(s2);
@@ -1661,10 +1762,13 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts two bytes and one short into the constant pool.
- *
- * @param b1 a byte.
- * @param b2 another byte.
- * @param s a short.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
+ * @param s
+ * a short.
*/
private void put112(final int b1, final int b2, final int s) {
pool.put11(b1, b2).putShort(s);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
new file mode 100644
index 0000000..27983d6
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
@@ -0,0 +1,145 @@
+/***
+ * 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;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ *
+ * @author Eric Bruneton
+ */
+class Context {
+
+ /**
+ * Prototypes of the attributes that must be parsed for this class.
+ */
+ Attribute[] attrs;
+
+ /**
+ * The {@link ClassReader} option flags for the parsing of this class.
+ */
+ int flags;
+
+ /**
+ * The buffer used to read strings.
+ */
+ char[] buffer;
+
+ /**
+ * The start index of each bootstrap method.
+ */
+ int[] bootstrapMethods;
+
+ /**
+ * The access flags of the method currently being parsed.
+ */
+ int access;
+
+ /**
+ * The name of the method currently being parsed.
+ */
+ String name;
+
+ /**
+ * The descriptor of the method currently being parsed.
+ */
+ String desc;
+
+ /**
+ * The label objects, indexed by bytecode offset, of the method currently
+ * being parsed (only bytecode offsets for which a label is needed have a
+ * non null associated Label object).
+ */
+ Label[] labels;
+
+ /**
+ * The target of the type annotation currently being parsed.
+ */
+ int typeRef;
+
+ /**
+ * The path of the type annotation currently being parsed.
+ */
+ TypePath typePath;
+
+ /**
+ * The offset of the latest stack map frame that has been parsed.
+ */
+ int offset;
+
+ /**
+ * The labels corresponding to the start of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] start;
+
+ /**
+ * The labels corresponding to the end of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] end;
+
+ /**
+ * The local variable indices for each local variable range in the local
+ * variable type annotation currently being parsed.
+ */
+ int[] index;
+
+ /**
+ * The encoding of the latest stack map frame that has been parsed.
+ */
+ int mode;
+
+ /**
+ * The number of locals in the latest stack map frame that has been parsed.
+ */
+ int localCount;
+
+ /**
+ * The number locals in the latest stack map frame that has been parsed,
+ * minus the number of locals in the previous frame.
+ */
+ int localDiff;
+
+ /**
+ * The local values of the latest stack map frame that has been parsed.
+ */
+ Object[] local;
+
+ /**
+ * The stack size of the latest stack map frame that has been parsed.
+ */
+ int stackCount;
+
+ /**
+ * The stack values of the latest stack map frame that has been parsed.
+ */
+ Object[] stack;
+}
\ 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/Edge.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
index 80222bc..9347888 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An edge in the control flow graph of a method body. See {@link Label Label}.
- *
+ *
* @author Eric Bruneton
*/
class Edge {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
index 32c23d1..107af8f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
@@ -30,17 +30,17 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java field. The methods of this class must be called
- * in the following order: ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java field. The methods of this class must be called in
+ * the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
* @author Eric Bruneton
*/
public abstract class FieldVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -52,9 +52,10 @@ public abstract class FieldVisitor {
/**
* Constructs a new {@link FieldVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public FieldVisitor(final int api) {
this(api, null);
@@ -62,25 +63,29 @@ public abstract class FieldVisitor {
/**
* Constructs a new {@link FieldVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param fv the field visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param fv
+ * the field visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.fv = fv;
}
/**
* Visits an annotation of the field.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -92,9 +97,39 @@ public abstract class FieldVisitor {
}
/**
+ * Visits an annotation on the type of the field.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#FIELD FIELD}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (fv != null) {
+ return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a non standard attribute of the field.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (fv != null) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
index b61105a..4a5f406 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
+ *
* @author Eric Bruneton
*/
final class FieldWriter extends FieldVisitor {
@@ -81,6 +81,17 @@ final class FieldWriter extends FieldVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this field. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The non standard attributes of this field. May be <tt>null</tt>.
*/
private Attribute attrs;
@@ -91,23 +102,23 @@ final class FieldWriter extends FieldVisitor {
/**
* Constructs a new {@link FieldWriter}.
- *
- * @param cw the class writer to which this field must be added.
- * @param access the field's access flags (see {@link Opcodes}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type}).
- * @param signature the field's signature. May be <tt>null</tt>.
- * @param value the field's constant value. May be <tt>null</tt>.
+ *
+ * @param cw
+ * the class writer to which this field must be added.
+ * @param access
+ * the field's access flags (see {@link Opcodes}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt>.
+ * @param value
+ * the field's constant value. May be <tt>null</tt>.
*/
- FieldWriter(
- final ClassWriter cw,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- super(Opcodes.ASM4);
+ FieldWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ super(Opcodes.ASM5);
if (cw.firstField == null) {
cw.firstField = this;
} else {
@@ -131,10 +142,8 @@ final class FieldWriter extends FieldVisitor {
// ------------------------------------------------------------------------
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -153,6 +162,29 @@ final class FieldWriter extends FieldVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
@@ -168,7 +200,7 @@ final class FieldWriter extends FieldVisitor {
/**
* Returns the size of this field.
- *
+ *
* @return the size of this field.
*/
int getSize() {
@@ -177,11 +209,12 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("ConstantValue");
size += 8;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- cw.newUTF8("Synthetic");
- size += 6;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
@@ -199,6 +232,14 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
@@ -207,22 +248,24 @@ final class FieldWriter extends FieldVisitor {
/**
* Puts the content of this field into the given byte vector.
- *
- * @param out where the content of this field must be put.
+ *
+ * @param out
+ * where the content of this field must be put.
*/
void put(final ByteVector out) {
- int mask = Opcodes.ACC_DEPRECATED
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
int attributeCount = 0;
if (value != 0) {
++attributeCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
@@ -236,6 +279,12 @@ final class FieldWriter extends FieldVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
if (attrs != null) {
attributeCount += attrs.getCount();
}
@@ -244,10 +293,11 @@ final class FieldWriter extends FieldVisitor {
out.putShort(cw.newUTF8("ConstantValue"));
out.putInt(2).putShort(value);
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
@@ -264,6 +314,14 @@ final class FieldWriter extends FieldVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
[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?"
Posted by ka...@apache.org.
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] <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err
+ .println("Prints the ASM code to generate the given class.");
+ System.err.println("Usage: ASMifier [-debug] "
+ + "<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");
+ }
+ }
+}
[16/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
new file mode 100644
index 0000000..c256825
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -0,0 +1,947 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between
+ * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
+ * adapter must be used with the
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each
+ * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
+ * and then simulates the effect of this instruction on the stack map frame,
+ * represented by {@link #locals} and {@link #stack}. The next visitor in the
+ * chain can get the state of the stack map frame <i>before</i> each instruction
+ * by reading the value of these fields in its visit<i>X</i> methods (this
+ * requires a reference to the AnalyzerAdapter that is before it in the chain).
+ * If this adapter is used with a class that does not contain stack map table
+ * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
+ * compute the stack map frame for each instruction. In this case no exception
+ * is thrown but the {@link #locals} and {@link #stack} fields will be null for
+ * these instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class AnalyzerAdapter extends MethodVisitor {
+
+ /**
+ * <code>List</code> of the local variable slots for current execution
+ * frame. Primitive types are represented by {@link Opcodes#TOP},
+ * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+ * two elements, the second one being TOP). Reference types are represented
+ * by String objects (representing internal names), and uninitialized types
+ * by Label objects (this label designates the NEW instruction that created
+ * this uninitialized value). This field is <tt>null</tt> for unreachable
+ * instructions.
+ */
+ public List<Object> locals;
+
+ /**
+ * <code>List</code> of the operand stack slots for current execution frame.
+ * Primitive types are represented by {@link Opcodes#TOP},
+ * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+ * two elements, the second one being TOP). Reference types are represented
+ * by String objects (representing internal names), and uninitialized types
+ * by Label objects (this label designates the NEW instruction that created
+ * this uninitialized value). This field is <tt>null</tt> for unreachable
+ * instructions.
+ */
+ public List<Object> stack;
+
+ /**
+ * The labels that designate the next instruction to be visited. May be
+ * <tt>null</tt>.
+ */
+ private List<Label> labels;
+
+ /**
+ * Information about uninitialized types in the current execution frame.
+ * This map associates internal names to Label objects. Each label
+ * designates a NEW instruction that created the currently uninitialized
+ * types, and the associated internal name represents the NEW operand, i.e.
+ * the final, initialized type value.
+ */
+ public Map<Object, Object> uninitializedTypes;
+
+ /**
+ * The maximum stack size of this method.
+ */
+ private int maxStack;
+
+ /**
+ * The maximum number of local variables of this method.
+ */
+ private int maxLocals;
+
+ /**
+ * The owner's class name.
+ */
+ private String owner;
+
+ /**
+ * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
+ * version.
+ *
+ * @param owner
+ * the owner's class name.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls. May
+ * be <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public AnalyzerAdapter(final String owner, final int access,
+ final String name, final String desc, final MethodVisitor mv) {
+ this(Opcodes.ASM5, owner, access, name, desc, mv);
+ if (getClass() != AnalyzerAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link AnalyzerAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param owner
+ * the owner's class name.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls. May
+ * be <tt>null</tt>.
+ */
+ protected AnalyzerAdapter(final int api, final String owner,
+ final int access, final String name, final String desc,
+ final MethodVisitor mv) {
+ super(api, mv);
+ this.owner = owner;
+ locals = new ArrayList<Object>();
+ stack = new ArrayList<Object>();
+ uninitializedTypes = new HashMap<Object, Object>();
+
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ locals.add(Opcodes.UNINITIALIZED_THIS);
+ } else {
+ locals.add(owner);
+ }
+ }
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; ++i) {
+ Type type = types[i];
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ locals.add(Opcodes.INTEGER);
+ break;
+ case Type.FLOAT:
+ locals.add(Opcodes.FLOAT);
+ break;
+ case Type.LONG:
+ locals.add(Opcodes.LONG);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.DOUBLE:
+ locals.add(Opcodes.DOUBLE);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.ARRAY:
+ locals.add(types[i].getDescriptor());
+ break;
+ // case Type.OBJECT:
+ default:
+ locals.add(types[i].getInternalName());
+ }
+ }
+ maxLocals = locals.size();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // uncompressed frame
+ throw new IllegalStateException(
+ "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+ }
+
+ if (mv != null) {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ if (this.locals != null) {
+ this.locals.clear();
+ this.stack.clear();
+ } else {
+ this.locals = new ArrayList<Object>();
+ this.stack = new ArrayList<Object>();
+ }
+ visitFrameTypes(nLocal, local, this.locals);
+ visitFrameTypes(nStack, stack, this.stack);
+ maxStack = Math.max(maxStack, this.stack.size());
+ }
+
+ private static void visitFrameTypes(final int n, final Object[] types,
+ final List<Object> result) {
+ for (int i = 0; i < n; ++i) {
+ Object type = types[i];
+ result.add(type);
+ if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
+ result.add(Opcodes.TOP);
+ }
+ }
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ execute(opcode, 0, null);
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+ || opcode == Opcodes.ATHROW) {
+ this.locals = null;
+ this.stack = null;
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ execute(opcode, operand, null);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ execute(opcode, var, null);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ if (opcode == Opcodes.NEW) {
+ if (labels == null) {
+ Label l = new Label();
+ labels = new ArrayList<Label>(3);
+ labels.add(l);
+ if (mv != null) {
+ mv.visitLabel(l);
+ }
+ }
+ for (int i = 0; i < labels.size(); ++i) {
+ uninitializedTypes.put(labels.get(i), type);
+ }
+ }
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ execute(opcode, 0, desc);
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ pop(desc);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ Object t = pop();
+ if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
+ Object u;
+ if (t == Opcodes.UNINITIALIZED_THIS) {
+ u = this.owner;
+ } else {
+ u = uninitializedTypes.get(t);
+ }
+ for (int i = 0; i < locals.size(); ++i) {
+ if (locals.get(i) == t) {
+ locals.set(i, u);
+ }
+ }
+ for (int i = 0; i < stack.size(); ++i) {
+ if (stack.get(i) == t) {
+ stack.set(i, u);
+ }
+ }
+ }
+ }
+ pushDesc(desc);
+ labels = null;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ pop(desc);
+ pushDesc(desc);
+ labels = null;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ execute(opcode, 0, null);
+ if (opcode == Opcodes.GOTO) {
+ this.locals = null;
+ this.stack = null;
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ if (labels == null) {
+ labels = new ArrayList<Label>(3);
+ }
+ labels.add(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ if (cst instanceof Integer) {
+ push(Opcodes.INTEGER);
+ } else if (cst instanceof Long) {
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ } else if (cst instanceof Float) {
+ push(Opcodes.FLOAT);
+ } else if (cst instanceof Double) {
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ } else if (cst instanceof String) {
+ push("java/lang/String");
+ } else if (cst instanceof Type) {
+ int sort = ((Type) cst).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ push("java/lang/Class");
+ } else if (sort == Type.METHOD) {
+ push("java/lang/invoke/MethodType");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ } else if (cst instanceof Handle) {
+ push("java/lang/invoke/MethodHandle");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ labels = null;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ execute(Opcodes.IINC, var, null);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ execute(Opcodes.TABLESWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ execute(Opcodes.LOOKUPSWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ execute(Opcodes.MULTIANEWARRAY, dims, desc);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (mv != null) {
+ this.maxStack = Math.max(this.maxStack, maxStack);
+ this.maxLocals = Math.max(this.maxLocals, maxLocals);
+ mv.visitMaxs(this.maxStack, this.maxLocals);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ private Object get(final int local) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+ }
+
+ private void set(final int local, final Object type) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ while (local >= locals.size()) {
+ locals.add(Opcodes.TOP);
+ }
+ locals.set(local, type);
+ }
+
+ private void push(final Object type) {
+ stack.add(type);
+ maxStack = Math.max(maxStack, stack.size());
+ }
+
+ private void pushDesc(final String desc) {
+ int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+ switch (desc.charAt(index)) {
+ case 'V':
+ return;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ push(Opcodes.INTEGER);
+ return;
+ case 'F':
+ push(Opcodes.FLOAT);
+ return;
+ case 'J':
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ return;
+ case 'D':
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ return;
+ case '[':
+ if (index == 0) {
+ push(desc);
+ } else {
+ push(desc.substring(index, desc.length()));
+ }
+ break;
+ // case 'L':
+ default:
+ if (index == 0) {
+ push(desc.substring(1, desc.length() - 1));
+ } else {
+ push(desc.substring(index + 1, desc.length() - 1));
+ }
+ }
+ }
+
+ private Object pop() {
+ return stack.remove(stack.size() - 1);
+ }
+
+ private void pop(final int n) {
+ int size = stack.size();
+ int end = size - n;
+ for (int i = size - 1; i >= end; --i) {
+ stack.remove(i);
+ }
+ }
+
+ private void pop(final String desc) {
+ char c = desc.charAt(0);
+ if (c == '(') {
+ int n = 0;
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; ++i) {
+ n += types[i].getSize();
+ }
+ pop(n);
+ } else if (c == 'J' || c == 'D') {
+ pop(2);
+ } else {
+ pop(1);
+ }
+ }
+
+ private void execute(final int opcode, final int iarg, final String sarg) {
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ Object t1, t2, t3, t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(Opcodes.NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.ALOAD:
+ push(get(iarg));
+ break;
+ case Opcodes.LLOAD:
+ case Opcodes.DLOAD:
+ push(get(iarg));
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ if (t1 instanceof String) {
+ pushDesc(((String) t1).substring(1));
+ } else {
+ push("java/lang/Object");
+ }
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(iarg, t1);
+ if (iarg > 0) {
+ t2 = get(iarg - 1);
+ if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+ set(iarg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(iarg, t1);
+ set(iarg + 1, Opcodes.TOP);
+ if (iarg > 0) {
+ t2 = get(iarg - 1);
+ if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+ set(iarg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IINC:
+ set(iarg, Opcodes.INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException("JSR/RET are not supported");
+ case Opcodes.GETSTATIC:
+ pushDesc(sarg);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(sarg);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ pushDesc(sarg);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(sarg);
+ pop();
+ break;
+ case Opcodes.NEW:
+ push(labels.get(0));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (iarg) {
+ case Opcodes.T_BOOLEAN:
+ pushDesc("[Z");
+ break;
+ case Opcodes.T_CHAR:
+ pushDesc("[C");
+ break;
+ case Opcodes.T_BYTE:
+ pushDesc("[B");
+ break;
+ case Opcodes.T_SHORT:
+ pushDesc("[S");
+ break;
+ case Opcodes.T_INT:
+ pushDesc("[I");
+ break;
+ case Opcodes.T_FLOAT:
+ pushDesc("[F");
+ break;
+ case Opcodes.T_DOUBLE:
+ pushDesc("[D");
+ break;
+ // case Opcodes.T_LONG:
+ default:
+ pushDesc("[J");
+ break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ pop();
+ pushDesc("[" + Type.getObjectType(sarg));
+ break;
+ case Opcodes.CHECKCAST:
+ pop();
+ pushDesc(Type.getObjectType(sarg).getDescriptor());
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(iarg);
+ pushDesc(sarg);
+ break;
+ }
+ labels = null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
new file mode 100644
index 0000000..d146a36
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
@@ -0,0 +1,238 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link MethodVisitor} that can be used to approximate method size.
+ *
+ * @author Eugene Kuleshov
+ */
+public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
+
+ private int minSize;
+
+ private int maxSize;
+
+ public CodeSizeEvaluator(final MethodVisitor mv) {
+ this(Opcodes.ASM5, mv);
+ }
+
+ protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
+ super(api, mv);
+ }
+
+ public int getMinSize() {
+ return this.minSize;
+ }
+
+ public int getMaxSize() {
+ return this.maxSize;
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ minSize += 1;
+ maxSize += 1;
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (opcode == SIPUSH) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ if (var < 4 && opcode != RET) {
+ minSize += 1;
+ maxSize += 1;
+ } else if (var >= 256) {
+ minSize += 4;
+ maxSize += 4;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ minSize += 3;
+ maxSize += 3;
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ minSize += 3;
+ maxSize += 3;
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (opcode == INVOKEINTERFACE) {
+ minSize += 5;
+ maxSize += 5;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ minSize += 5;
+ maxSize += 5;
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ minSize += 3;
+ if (opcode == GOTO || opcode == JSR) {
+ maxSize += 5;
+ } else {
+ maxSize += 8;
+ }
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (cst instanceof Long || cst instanceof Double) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (var > 255 || increment > 127 || increment < -128) {
+ minSize += 6;
+ maxSize += 6;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ minSize += 13 + labels.length * 4;
+ maxSize += 16 + labels.length * 4;
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ minSize += 9 + keys.length * 8;
+ maxSize += 12 + keys.length * 8;
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ minSize += 4;
+ maxSize += 4;
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+}
[22/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
index 4801b61..4b9c65e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
@@ -37,7 +37,7 @@ import java.io.InputStream;
* This class parses a byte array conforming to the Java class file format and
* calls the appropriate visit methods of a given class visitor for each field,
* method and bytecode instruction encountered.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -112,9 +112,8 @@ public class ClassReader {
public final byte[] b;
/**
- * The start index of each constant pool item in {@link #b b}, plus one.
- * The one byte offset skips the constant pool item tag that indicates its
- * type.
+ * The start index of each constant pool item in {@link #b b}, plus one. The
+ * one byte offset skips the constant pool item tag that indicates its type.
*/
private final int[] items;
@@ -146,8 +145,9 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
+ *
+ * @param b
+ * the bytecode of the class to be read.
*/
public ClassReader(final byte[] b) {
this(b, 0, b.length);
@@ -155,15 +155,18 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- * @param off the start offset of the class data.
- * @param len the length of the class data.
+ *
+ * @param b
+ * the bytecode of the class to be read.
+ * @param off
+ * the start offset of the class data.
+ * @param len
+ * the length of the class data.
*/
public ClassReader(final byte[] b, final int off, final int len) {
this.b = b;
// checks the class version
- if (readShort(6) > Opcodes.V1_7) {
+ if (readShort(off + 6) > Opcodes.V1_8) {
throw new IllegalArgumentException();
}
// parses the constant pool
@@ -176,35 +179,35 @@ public class ClassReader {
items[i] = index + 1;
int size;
switch (b[index]) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- case ClassWriter.INDY:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- if (size > max) {
- max = size;
- }
- break;
- case ClassWriter.HANDLE:
- size = 4;
- break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
- // case ClassWriter.MTYPE
- default:
- size = 3;
- break;
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ case ClassWriter.NAME_TYPE:
+ case ClassWriter.INDY:
+ size = 5;
+ break;
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8:
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max) {
+ max = size;
+ }
+ break;
+ case ClassWriter.HANDLE:
+ size = 4;
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ // case ClassWriter.MTYPE
+ default:
+ size = 3;
+ break;
}
index += size;
}
@@ -217,9 +220,9 @@ public class ClassReader {
* Returns the class's access flags (see {@link Opcodes}). This value may
* not reflect Deprecated and Synthetic flags when bytecode is before 1.5
* and those flags are represented by attributes.
- *
+ *
* @return the class access flags
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public int getAccess() {
@@ -229,9 +232,9 @@ public class ClassReader {
/**
* Returns the internal name of the class (see
* {@link Type#getInternalName() getInternalName}).
- *
+ *
* @return the internal class name
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String getClassName() {
@@ -242,24 +245,23 @@ public class ClassReader {
* Returns the internal of name of the super class (see
* {@link Type#getInternalName() getInternalName}). For interfaces, the
* super class is {@link Object}.
- *
+ *
* @return the internal name of super class, or <tt>null</tt> for
* {@link Object} class.
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String getSuperName() {
- int n = items[readUnsignedShort(header + 4)];
- return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+ return readClass(header + 4, new char[maxStringLength]);
}
/**
* Returns the internal names of the class's interfaces (see
* {@link Type#getInternalName() getInternalName}).
- *
+ *
* @return the array of internal names for all implemented interfaces or
* <tt>null</tt>.
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String[] getInterfaces() {
@@ -279,8 +281,9 @@ public class ClassReader {
/**
* Copies the constant pool data into the given {@link ClassWriter}. Should
* be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter the {@link ClassWriter} to copy constant pool into.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy constant pool into.
*/
void copyPool(final ClassWriter classWriter) {
char[] buf = new char[maxStringLength];
@@ -292,82 +295,63 @@ public class ClassReader {
Item item = new Item(i);
int nameType;
switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- nameType = items[readUnsignedShort(index + 2)];
- item.set(tag,
- readClass(index, buf),
- readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
- break;
-
- case ClassWriter.INT:
- item.set(readInt(index));
- break;
-
- case ClassWriter.FLOAT:
- item.set(Float.intBitsToFloat(readInt(index)));
- break;
-
- case ClassWriter.NAME_TYPE:
- item.set(tag,
- readUTF8(index, buf),
- readUTF8(index + 2, buf),
- null);
- break;
-
- case ClassWriter.LONG:
- item.set(readLong(index));
- ++i;
- break;
-
- case ClassWriter.DOUBLE:
- item.set(Double.longBitsToDouble(readLong(index)));
- ++i;
- break;
-
- case ClassWriter.UTF8: {
- String s = strings[i];
- if (s == null) {
- index = items[i];
- s = strings[i] = readUTF(index + 2,
- readUnsignedShort(index),
- buf);
- }
- item.set(tag, s, null, null);
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+ break;
+ case ClassWriter.INT:
+ item.set(readInt(index));
+ break;
+ case ClassWriter.FLOAT:
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+ case ClassWriter.NAME_TYPE:
+ item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
+ null);
+ break;
+ case ClassWriter.LONG:
+ item.set(readLong(index));
+ ++i;
+ break;
+ case ClassWriter.DOUBLE:
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+ case ClassWriter.UTF8: {
+ String s = strings[i];
+ if (s == null) {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2,
+ readUnsignedShort(index), buf);
}
- break;
-
- case ClassWriter.HANDLE: {
- int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
- nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
- item.set(ClassWriter.HANDLE_BASE + readByte(index),
- readClass(fieldOrMethodRef, buf),
- readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
-
+ item.set(tag, s, null, null);
+ break;
+ }
+ case ClassWriter.HANDLE: {
+ int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+ nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+ item.set(ClassWriter.HANDLE_BASE + readByte(index),
+ readClass(fieldOrMethodRef, buf),
+ readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+ break;
+ }
+ case ClassWriter.INDY:
+ if (classWriter.bootstrapMethods == null) {
+ copyBootstrapMethods(classWriter, items2, buf);
}
- break;
-
-
- case ClassWriter.INDY:
- if (classWriter.bootstrapMethods == null) {
- copyBootstrapMethods(classWriter, items2, buf);
- }
- nameType = items[readUnsignedShort(index + 2)];
- item.set(readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf),
- readUnsignedShort(index));
- break;
-
-
- // case ClassWriter.STR:
- // case ClassWriter.CLASS:
- // case ClassWriter.MTYPE
- default:
- item.set(tag, readUTF8(index, buf), null, null);
- break;
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
+ readUnsignedShort(index));
+ break;
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ // case ClassWriter.MTYPE
+ default:
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
}
int index2 = item.hashCode % items2.length;
@@ -382,77 +366,59 @@ public class ClassReader {
classWriter.index = ll;
}
- private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
- int i, j, k, u, v;
-
- // skip class header
- v = header;
- v += 8 + (readUnsignedShort(v + 6) << 1);
-
- // skips fields and methods
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
+ /**
+ * Copies the bootstrap method data into the given {@link ClassWriter}.
+ * Should be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy bootstrap methods into.
+ */
+ private void copyBootstrapMethods(final ClassWriter classWriter,
+ final Item[] items, final char[] c) {
+ // finds the "BootstrapMethods" attribute
+ int u = getAttributes();
+ boolean found = false;
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("BootstrapMethods".equals(attrName)) {
+ found = true;
+ break;
}
+ u += 6 + readInt(u + 4);
}
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
+ if (!found) {
+ return;
}
-
- // read class attributes
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- String attrName = readUTF8(v, buf);
- int size = readInt(v + 2);
- if ("BootstrapMethods".equals(attrName)) {
- int boostrapMethodCount = readUnsignedShort(v + 6);
- int x = v + 8;
- for (j = 0; j < boostrapMethodCount; j++) {
- int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
- k = readUnsignedShort(x + 2);
- u = x + 4;
- for(; k > 0; --k) {
- hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
- u += 2;
- }
- Item item = new Item(j);
- item.set(x - v - 8, hashCode & 0x7FFFFFFF);
-
- int index2 = item.hashCode % items2.length;
- item.next = items2[index2];
- items2[index2] = item;
-
- x = u;
- }
-
- classWriter.bootstrapMethodsCount = boostrapMethodCount;
- ByteVector bootstrapMethods = new ByteVector(size + 62);
- bootstrapMethods.putByteArray(b, v + 8, size - 2);
- classWriter.bootstrapMethods = bootstrapMethods;
- return;
+ // copies the bootstrap methods in the class writer
+ int boostrapMethodCount = readUnsignedShort(u + 8);
+ for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
+ int position = v - u - 10;
+ int hashCode = readConst(readUnsignedShort(v), c).hashCode();
+ for (int k = readUnsignedShort(v + 2); k > 0; --k) {
+ hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
+ v += 2;
}
- v += 6 + size;
+ v += 4;
+ Item item = new Item(j);
+ item.set(position, hashCode & 0x7FFFFFFF);
+ int index = item.hashCode % items.length;
+ item.next = items[index];
+ items[index] = item;
}
-
- // we are in trouble !!!
+ int attrSize = readInt(u + 4);
+ ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
+ bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
+ classWriter.bootstrapMethodsCount = boostrapMethodCount;
+ classWriter.bootstrapMethods = bootstrapMethods;
}
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param is an input stream from which to read the class.
- * @throws IOException if a problem occurs during reading.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @throws IOException
+ * if a problem occurs during reading.
*/
public ClassReader(final InputStream is) throws IOException {
this(readClass(is, false));
@@ -460,26 +426,31 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param name the binary qualified name of the class to be read.
- * @throws IOException if an exception occurs during reading.
+ *
+ * @param name
+ * the binary qualified name of the class to be read.
+ * @throws IOException
+ * if an exception occurs during reading.
*/
public ClassReader(final String name) throws IOException {
- this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
- + ".class"), true));
+ this(readClass(
+ ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ + ".class"), true));
}
/**
* Reads the bytecode of a class.
- *
- * @param is an input stream from which to read the class.
- * @param close true to close the input stream after reading.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @param close
+ * true to close the input stream after reading.
* @return the bytecode read from the given input stream.
- * @throws IOException if a problem occurs during reading.
+ * @throws IOException
+ * if a problem occurs during reading.
*/
private static byte[] readClass(final InputStream is, boolean close)
- throws IOException
- {
+ throws IOException {
if (is == null) {
throw new IOException("Class not found");
}
@@ -520,14 +491,16 @@ public class ClassReader {
// ------------------------------------------------------------------------
/**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
+ * Makes the given visitor visit the Java class of this {@link ClassReader}
+ * . This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
*/
public void accept(final ClassVisitor classVisitor, final int flags) {
accept(classVisitor, new Attribute[0], flags);
@@ -537,1118 +510,1220 @@ public class ClassReader {
* Makes the given visitor visit the Java class of this {@link ClassReader}.
* This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the
- * type of one the prototypes will not be parsed: its byte array
- * value will be passed unchanged to the ClassWriter. <i>This may
- * corrupt it if this value contains references to the constant pool,
- * or has syntactic or semantic links with a class element that has
- * been transformed by a class adapter between the reader and the
- * writer</i>.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param attrs
+ * prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to
+ * the type of one the prototypes will not be parsed: its byte
+ * array value will be passed unchanged to the ClassWriter.
+ * <i>This may corrupt it if this value contains references to
+ * the constant pool, or has syntactic or semantic links with a
+ * class element that has been transformed by a class adapter
+ * between the reader and the writer</i>.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
*/
- public void accept(
- final ClassVisitor classVisitor,
- final Attribute[] attrs,
- final int flags)
- {
- byte[] b = this.b; // the bytecode array
+ public void accept(final ClassVisitor classVisitor,
+ final Attribute[] attrs, final int flags) {
+ int u = header; // current offset in the class file
char[] c = new char[maxStringLength]; // buffer used to read strings
- int i, j, k; // loop variables
- int u, v, w; // indexes in b
- Attribute attr;
-
- int access;
- String name;
- String desc;
- String attrName;
- String signature;
- int anns = 0;
- int ianns = 0;
- Attribute cattrs = null;
-
- // visits the header
- u = header;
- access = readUnsignedShort(u);
- name = readClass(u + 2, c);
- v = items[readUnsignedShort(u + 4)];
- String superClassName = v == 0 ? null : readUTF8(v, c);
- String[] implementedItfs = new String[readUnsignedShort(u + 6)];
- w = 0;
+
+ Context context = new Context();
+ context.attrs = attrs;
+ context.flags = flags;
+ context.buffer = c;
+
+ // reads the class declaration
+ int access = readUnsignedShort(u);
+ String name = readClass(u + 2, c);
+ String superClass = readClass(u + 4, c);
+ String[] interfaces = new String[readUnsignedShort(u + 6)];
u += 8;
- for (i = 0; i < implementedItfs.length; ++i) {
- implementedItfs[i] = readClass(u, c);
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfaces[i] = readClass(u, c);
u += 2;
}
- boolean skipCode = (flags & SKIP_CODE) != 0;
- boolean skipDebug = (flags & SKIP_DEBUG) != 0;
- boolean unzip = (flags & EXPAND_FRAMES) != 0;
-
- // skips fields and methods
- v = u;
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- // reads the class's attributes
- signature = null;
+ // reads the class attributes
+ String signature = null;
String sourceFile = null;
String sourceDebug = null;
String enclosingOwner = null;
String enclosingName = null;
String enclosingDesc = null;
- int[] bootstrapMethods = null; // start indexed of the bsms
-
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- attrName = readUTF8(v, c);
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int innerClasses = 0;
+ Attribute attributes = null;
+
+ u = getAttributes();
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
// tests are sorted in decreasing frequency order
// (based on frequencies observed on typical classes)
if ("SourceFile".equals(attrName)) {
- sourceFile = readUTF8(v + 6, c);
+ sourceFile = readUTF8(u + 8, c);
} else if ("InnerClasses".equals(attrName)) {
- w = v + 6;
+ innerClasses = u + 8;
} else if ("EnclosingMethod".equals(attrName)) {
- enclosingOwner = readClass(v + 6, c);
- int item = readUnsignedShort(v + 8);
+ enclosingOwner = readClass(u + 8, c);
+ int item = readUnsignedShort(u + 10);
if (item != 0) {
enclosingName = readUTF8(items[item], c);
enclosingDesc = readUTF8(items[item] + 2, c);
}
} else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(v + 6, c);
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = v + 6;
+ signature = readUTF8(u + 8, c);
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if ("SourceDebugExtension".equals(attrName)) {
- int len = readInt(v + 2);
- sourceDebug = readUTF(v + 6, len, new char[len]);
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = v + 6;
+ int len = readInt(u + 4);
+ sourceDebug = readUTF(u + 8, len, new char[len]);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
} else if ("BootstrapMethods".equals(attrName)) {
- int boostrapMethodCount = readUnsignedShort(v + 6);
- bootstrapMethods = new int[boostrapMethodCount];
- int x = v + 8;
- for (j = 0; j < boostrapMethodCount; j++) {
- bootstrapMethods[j] = x;
- x += 2 + readUnsignedShort(x + 2) << 1;
+ int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
+ for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
+ bootstrapMethods[j] = v;
+ v += 2 + readUnsignedShort(v + 2) << 1;
}
+ context.bootstrapMethods = bootstrapMethods;
} else {
- attr = readAttribute(attrs,
- attrName,
- v + 6,
- readInt(v + 2),
- c,
- -1,
- null);
+ Attribute attr = readAttribute(attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
+ attr.next = attributes;
+ attributes = attr;
}
}
- v += 6 + readInt(v + 2);
- }
- // calls the visit method
- classVisitor.visit(readInt(4),
- access,
- name,
- signature,
- superClassName,
- implementedItfs);
-
- // calls the visitSource method
- if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+ u += 6 + readInt(u + 4);
+ }
+
+ // visits the class declaration
+ classVisitor.visit(readInt(items[1] - 7), access, name, signature,
+ superClass, interfaces);
+
+ // visits the source and debug info
+ if ((flags & SKIP_DEBUG) == 0
+ && (sourceFile != null || sourceDebug != null)) {
classVisitor.visitSource(sourceFile, sourceDebug);
}
- // calls the visitOuterClass method
+ // visits the outer class
if (enclosingOwner != null) {
- classVisitor.visitOuterClass(enclosingOwner,
- enclosingName,
+ classVisitor.visitOuterClass(enclosingOwner, enclosingName,
enclosingDesc);
}
- // visits the class annotations
- if (ANNOTATIONS) {
- for (i = 1; i >= 0; --i) {
- v = i == 0 ? ianns : anns;
- if (v != 0) {
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
- }
- }
+ // visits the class annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
}
}
- // visits the class attributes
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- classVisitor.visitAttribute(cattrs);
- cattrs = attr;
+ // visits the attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ classVisitor.visitAttribute(attributes);
+ attributes = attr;
}
- // calls the visitInnerClass method
- if (w != 0) {
- i = readUnsignedShort(w);
- w += 2;
- for (; i > 0; --i) {
- classVisitor.visitInnerClass(readUnsignedShort(w) == 0
- ? null
- : readClass(w, c), readUnsignedShort(w + 2) == 0
- ? null
- : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
- ? null
- : readUTF8(w + 4, c), readUnsignedShort(w + 6));
- w += 8;
+ // visits the inner classes
+ if (innerClasses != 0) {
+ int v = innerClasses + 2;
+ for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
+ classVisitor.visitInnerClass(readClass(v, c),
+ readClass(v + 2, c), readUTF8(v + 4, c),
+ readUnsignedShort(v + 6));
+ v += 8;
}
}
- // visits the fields
- i = readUnsignedShort(u);
+ // visits the fields and methods
+ u = header + 10 + 2 * interfaces.length;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readField(classVisitor, context, u);
+ }
u += 2;
- for (; i > 0; --i) {
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- // visits the field's attributes and looks for a ConstantValue
- // attribute
- int fieldValueItem = 0;
- signature = null;
- anns = 0;
- ianns = 0;
- cattrs = null;
-
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("ConstantValue".equals(attrName)) {
- fieldValueItem = readUnsignedShort(u + 6);
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 6, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 6;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 6;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u + 6,
- readInt(u + 2),
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readMethod(classVisitor, context, u);
+ }
+
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
+
+ /**
+ * Reads a field and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the field.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the field in the class file.
+ * @return the offset of the first byte following the field in the class.
+ */
+ private int readField(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the field declaration
+ char[] c = context.buffer;
+ int access = readUnsignedShort(u);
+ String name = readUTF8(u + 2, c);
+ String desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the field attributes
+ String signature = null;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ Object value = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName)) {
+ int item = readUnsignedShort(u + 8);
+ value = item == 0 ? null : readConst(item, c);
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else {
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
- u += 6 + readInt(u + 2);
}
- // visits the field
- FieldVisitor fv = classVisitor.visitField(access,
- name,
- desc,
- signature,
- fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
- // visits the field annotations and attributes
- if (fv != null) {
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- v = j == 0 ? ianns : anns;
- if (v != 0) {
- k = readUnsignedShort(v);
- v += 2;
- for (; k > 0; --k) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- fv.visitAnnotation(readUTF8(v, c), j != 0));
- }
- }
- }
- }
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- fv.visitAttribute(cattrs);
- cattrs = attr;
- }
- fv.visitEnd();
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // visits the field declaration
+ FieldVisitor fv = classVisitor.visitField(access, name, desc,
+ signature, value);
+ if (fv == null) {
+ return u;
+ }
+
+ // visits the field annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
}
}
- // visits the methods
- i = readUnsignedShort(u);
- u += 2;
- for (; i > 0; --i) {
- int u0 = u + 6;
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- signature = null;
- anns = 0;
- ianns = 0;
- int dann = 0;
- int mpanns = 0;
- int impanns = 0;
- cattrs = null;
- v = 0;
- w = 0;
-
- // looks for Code and Exceptions attributes
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- int attrSize = readInt(u + 2);
- u += 6;
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("Code".equals(attrName)) {
- if (!skipCode) {
- v = u;
- }
- } else if ("Exceptions".equals(attrName)) {
- w = u;
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u;
- } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
- dann = u;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u;
- } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
- {
- mpanns = u;
- } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
- {
- impanns = u;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u,
- attrSize,
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
+ // visits the field attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ fv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the end of the field
+ fv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads a method and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the method.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the method in the class file.
+ * @return the offset of the first byte following the method in the class.
+ */
+ private int readMethod(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the method declaration
+ char[] c = context.buffer;
+ context.access = readUnsignedShort(u);
+ context.name = readUTF8(u + 2, c);
+ context.desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the method attributes
+ int code = 0;
+ int exception = 0;
+ String[] exceptions = null;
+ String signature = null;
+ int methodParameters = 0;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ int firstAttribute = u;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName)) {
+ if ((context.flags & SKIP_CODE) == 0) {
+ code = u + 8;
}
- u += attrSize;
- }
- // reads declared exceptions
- String[] exceptions;
- if (w == 0) {
- exceptions = null;
+ } else if ("Exceptions".equals(attrName)) {
+ exceptions = new String[readUnsignedShort(u + 8)];
+ exception = u + 10;
+ for (int j = 0; j < exceptions.length; ++j) {
+ exceptions[j] = readClass(exception, c);
+ exception += 2;
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ context.access |= Opcodes.ACC_DEPRECATED;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+ dann = u + 8;
+ } else if ("Synthetic".equals(attrName)) {
+ context.access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
+ mpanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
+ impanns = u + 8;
+ } else if ("MethodParameters".equals(attrName)) {
+ methodParameters = u + 8;
} else {
- exceptions = new String[readUnsignedShort(w)];
- w += 2;
- for (j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(w, c);
- w += 2;
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
}
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
- // visits the method's code, if any
- MethodVisitor mv = classVisitor.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
+ // visits the method declaration
+ MethodVisitor mv = classVisitor.visitMethod(context.access,
+ context.name, context.desc, signature, exceptions);
+ if (mv == null) {
+ return u;
+ }
- if (mv != null) {
- /*
- * if the returned MethodVisitor is in fact a MethodWriter, it
- * means there is no method adapter between the reader and the
- * writer. If, in addition, the writer's constant pool was
- * copied from this reader (mw.cw.cr == this), and the signature
- * and exceptions of the method have not been changed, then it
- * is possible to skip all visit events and just copy the
- * original code of the method to the writer (the access, name
- * and descriptor can have been changed, this is not important
- * since they are not copied as is from the reader).
- */
- if (WRITER && mv instanceof MethodWriter) {
- MethodWriter mw = (MethodWriter) mv;
- if (mw.cw.cr == this) {
- if (signature == mw.signature) {
- boolean sameExceptions = false;
- if (exceptions == null) {
- sameExceptions = mw.exceptionCount == 0;
- } else {
- if (exceptions.length == mw.exceptionCount) {
- sameExceptions = true;
- for (j = exceptions.length - 1; j >= 0; --j)
- {
- w -= 2;
- if (mw.exceptions[j] != readUnsignedShort(w))
- {
- sameExceptions = false;
- break;
- }
- }
- }
- }
- if (sameExceptions) {
- /*
- * we do not copy directly the code into
- * MethodWriter to save a byte array copy
- * operation. The real copy will be done in
- * ClassWriter.toByteArray().
- */
- mw.classReaderOffset = u0;
- mw.classReaderLength = u - u0;
- continue;
- }
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it means
+ * there is no method adapter between the reader and the writer. If, in
+ * addition, the writer's constant pool was copied from this reader
+ * (mw.cw.cr == this), and the signature and exceptions of the method
+ * have not been changed, then it is possible to skip all visit events
+ * and just copy the original code of the method to the writer (the
+ * access, name and descriptor can have been changed, this is not
+ * important since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter) {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this && signature == mw.signature) {
+ boolean sameExceptions = false;
+ if (exceptions == null) {
+ sameExceptions = mw.exceptionCount == 0;
+ } else if (exceptions.length == mw.exceptionCount) {
+ sameExceptions = true;
+ for (int j = exceptions.length - 1; j >= 0; --j) {
+ exception -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(exception)) {
+ sameExceptions = false;
+ break;
}
}
}
-
- if (ANNOTATIONS && dann != 0) {
- AnnotationVisitor dv = mv.visitAnnotationDefault();
- readAnnotationValue(dann, c, null, dv);
- if (dv != null) {
- dv.visitEnd();
- }
- }
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- w = j == 0 ? ianns : anns;
- if (w != 0) {
- k = readUnsignedShort(w);
- w += 2;
- for (; k > 0; --k) {
- w = readAnnotationValues(w + 2,
- c,
- true,
- mv.visitAnnotation(readUTF8(w, c), j != 0));
- }
- }
- }
+ if (sameExceptions) {
+ /*
+ * we do not copy directly the code into MethodWriter to
+ * save a byte array copy operation. The real copy will be
+ * done in ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = firstAttribute;
+ mw.classReaderLength = u - firstAttribute;
+ return u;
}
- if (ANNOTATIONS && mpanns != 0) {
- readParameterAnnotations(mpanns, desc, c, true, mv);
+ }
+ }
+
+ // visit the method parameters
+ if (methodParameters != 0) {
+ for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
+ mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
+ }
+ }
+
+ // visits the method annotations
+ if (ANNOTATIONS && dann != 0) {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null) {
+ dv.visitEnd();
+ }
+ }
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0) {
+ readParameterAnnotations(mv, context, mpanns, true);
+ }
+ if (ANNOTATIONS && impanns != 0) {
+ readParameterAnnotations(mv, context, impanns, false);
+ }
+
+ // visits the method attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ mv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the method code
+ if (code != 0) {
+ mv.visitCode();
+ readCode(mv, context, code);
+ }
+
+ // visits the end of the method
+ mv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads the bytecode of a method and makes the given visitor visit it.
+ *
+ * @param mv
+ * the visitor that must visit the method's code.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the code attribute in the class file.
+ */
+ private void readCode(final MethodVisitor mv, final Context context, int u) {
+ // reads the header
+ byte[] b = this.b;
+ char[] c = context.buffer;
+ int maxStack = readUnsignedShort(u);
+ int maxLocals = readUnsignedShort(u + 2);
+ int codeLength = readInt(u + 4);
+ u += 8;
+
+ // reads the bytecode to find the labels
+ int codeStart = u;
+ int codeEnd = u + codeLength;
+ Label[] labels = context.labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ readLabel(offset + readShort(u + 1), labels);
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ readLabel(offset + readInt(u + 1), labels);
+ u += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
}
- if (ANNOTATIONS && impanns != 0) {
- readParameterAnnotations(impanns, desc, c, false, mv);
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 4;
}
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- mv.visitAttribute(cattrs);
- cattrs = attr;
+ u += 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 4); i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 8;
}
+ u += 8;
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ u += 4;
+ break;
}
+ }
- if (mv != null && v != 0) {
- int maxStack = readUnsignedShort(v);
- int maxLocals = readUnsignedShort(v + 2);
- int codeLength = readInt(v + 4);
- v += 8;
+ // reads the try catch entries to find the labels, and also visits them
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ Label start = readLabel(readUnsignedShort(u + 2), labels);
+ Label end = readLabel(readUnsignedShort(u + 4), labels);
+ Label handler = readLabel(readUnsignedShort(u + 6), labels);
+ String type = readUTF8(items[readUnsignedShort(u + 8)], c);
+ mv.visitTryCatchBlock(start, end, handler, type);
+ u += 8;
+ }
+ u += 2;
- int codeStart = v;
- int codeEnd = v + codeLength;
-
- mv.visitCode();
-
- // 1st phase: finds the labels
- int label;
- Label[] labels = new Label[codeLength + 2];
- readLabel(codeLength + 1, labels);
- while (v < codeEnd) {
- w = v - codeStart;
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- readLabel(w + readShort(v + 1), labels);
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- readLabel(w + readInt(v + 1), labels);
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- v += 6;
- } else {
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 8) - readInt(v + 4) + 1;
- v += 12;
- for (; j > 0; --j) {
- readLabel(w + readInt(v), labels);
- v += 4;
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 4);
- v += 8;
- for (; j > 0; --j) {
- readLabel(w + readInt(v + 4), labels);
- v += 8;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- v += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- v += 5;
- break;
- // case MANA_INSN:
- default:
- v += 4;
- break;
- }
- }
- // parses the try catch entries
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- Label start = readLabel(readUnsignedShort(v), labels);
- Label end = readLabel(readUnsignedShort(v + 2), labels);
- Label handler = readLabel(readUnsignedShort(v + 4), labels);
- int type = readUnsignedShort(v + 6);
- if (type == 0) {
- mv.visitTryCatchBlock(start, end, handler, null);
- } else {
- mv.visitTryCatchBlock(start,
- end,
- handler,
- readUTF8(items[type], c));
- }
- v += 8;
- }
- // parses the local variable, line number tables, and code
- // attributes
- int varTable = 0;
- int varTypeTable = 0;
- int stackMap = 0;
- int stackMapSize = 0;
- int frameCount = 0;
- int frameMode = 0;
- int frameOffset = 0;
- int frameLocalCount = 0;
- int frameLocalDiff = 0;
- int frameStackCount = 0;
- Object[] frameLocal = null;
- Object[] frameStack = null;
- boolean zip = true;
- cattrs = null;
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- attrName = readUTF8(v, c);
- if ("LocalVariableTable".equals(attrName)) {
- if (!skipDebug) {
- varTable = v + 6;
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- label += readUnsignedShort(w + 2);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- w += 10;
- }
- }
- } else if ("LocalVariableTypeTable".equals(attrName)) {
- varTypeTable = v + 6;
- } else if ("LineNumberTable".equals(attrName)) {
- if (!skipDebug) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- labels[label].line = readUnsignedShort(w + 2);
- w += 4;
- }
- }
- } else if (FRAMES && "StackMapTable".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- stackMapSize = readInt(v + 2);
- frameCount = readUnsignedShort(v + 6);
+ // reads the code attributes
+ int[] tanns = null; // start index of each visible type annotation
+ int[] itanns = null; // start index of each invisible type annotation
+ int tann = 0; // current index in tanns array
+ int itann = 0; // current index in itanns array
+ int ntoff = -1; // next visible type annotation code offset
+ int nitoff = -1; // next invisible type annotation code offset
+ int varTable = 0;
+ int varTypeTable = 0;
+ boolean zip = true;
+ boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
+ int stackMap = 0;
+ int stackMapSize = 0;
+ int frameCount = 0;
+ Context frame = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("LocalVariableTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ varTable = u + 8;
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- /*
- * here we do not extract the labels corresponding to
- * the attribute content. This would require a full
- * parsing of the attribute, which would need to be
- * repeated in the second phase (see below). Instead the
- * content of the attribute is read one frame at a time
- * (i.e. after a frame has been visited, the next frame
- * is read), and the labels it contains are also
- * extracted one frame at a time. Thanks to the ordering
- * of frames, having only a "one frame lookahead" is not
- * a problem, i.e. it is not possible to see an offset
- * smaller than the offset of the current insn and for
- * which no Label exist.
- */
- /*
- * This is not true for UNINITIALIZED type offsets. We
- * solve this by parsing the stack map table without a
- * full decoding (see below).
- */
- } else if (FRAMES && "StackMap".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- stackMapSize = readInt(v + 2);
- frameCount = readUnsignedShort(v + 6);
- zip = false;
- }
- /*
- * IMPORTANT! here we assume that the frames are
- * ordered, as in the StackMapTable attribute, although
- * this is not guaranteed by the attribute format.
- */
- } else {
- for (k = 0; k < attrs.length; ++k) {
- if (attrs[k].type.equals(attrName)) {
- attr = attrs[k].read(this,
- v + 6,
- readInt(v + 2),
- c,
- codeStart - 8,
- labels);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
+ label += readUnsignedShort(v + 12);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
+ v += 10;
}
- v += 6 + readInt(v + 2);
}
-
- // 2nd phase: visits each instruction
- if (FRAMES && stackMap != 0) {
- // creates the very first (implicit) frame from the method
- // descriptor
- frameLocal = new Object[maxLocals];
- frameStack = new Object[maxStack];
- if (unzip) {
- int local = 0;
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
- } else {
- frameLocal[local++] = readClass(header + 2, c);
- }
- }
- j = 1;
- loop: while (true) {
- k = j;
- switch (desc.charAt(j++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- frameLocal[local++] = Opcodes.INTEGER;
- break;
- case 'F':
- frameLocal[local++] = Opcodes.FLOAT;
- break;
- case 'J':
- frameLocal[local++] = Opcodes.LONG;
- break;
- case 'D':
- frameLocal[local++] = Opcodes.DOUBLE;
- break;
- case '[':
- while (desc.charAt(j) == '[') {
- ++j;
- }
- if (desc.charAt(j) == 'L') {
- ++j;
- while (desc.charAt(j) != ';') {
- ++j;
- }
- }
- frameLocal[local++] = desc.substring(k, ++j);
- break;
- case 'L':
- while (desc.charAt(j) != ';') {
- ++j;
- }
- frameLocal[local++] = desc.substring(k + 1,
- j++);
- break;
- default:
- break loop;
- }
+ } else if ("LocalVariableTypeTable".equals(attrName)) {
+ varTypeTable = u + 8;
+ } else if ("LineNumberTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- frameLocalCount = local;
+ labels[label].line = readUnsignedShort(v + 12);
+ v += 4;
}
- /*
- * for the first explicit frame the offset is not
- * offset_delta + 1 but only offset_delta; setting the
- * implicit frame offset to -1 allow the use of the
- * "offset_delta + 1" rule in all cases
- */
- frameOffset = -1;
- /*
- * Finds labels for UNINITIALIZED frame types. Instead of
- * decoding each element of the stack map table, we look
- * for 3 consecutive bytes that "look like" an UNINITIALIZED
- * type (tag 8, offset within code bounds, NEW instruction
- * at this offset). We may find false positives (i.e. not
- * real UNINITIALIZED types), but this should be rare, and
- * the only consequence will be the creation of an unneeded
- * label. This is better than creating a label for each NEW
- * instruction, and faster than fully decoding the whole
- * stack map table.
- */
- for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
- if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
- k = readUnsignedShort(j + 1);
- if (k >= 0 && k < codeLength) { // potential offset
- if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
- readLabel(k, labels);
- }
- }
+ }
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = readTypeAnnotations(mv, context, u + 8, true);
+ ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
+ : readUnsignedShort(tanns[0] + 1);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = readTypeAnnotations(mv, context, u + 8, false);
+ nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
+ : readUnsignedShort(itanns[0] + 1);
+ } else if (FRAMES && "StackMapTable".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * here we do not extract the labels corresponding to the
+ * attribute content. This would require a full parsing of the
+ * attribute, which would need to be repeated in the second
+ * phase (see below). Instead the content of the attribute is
+ * read one frame at a time (i.e. after a frame has been
+ * visited, the next frame is read), and the labels it contains
+ * are also extracted one frame at a time. Thanks to the
+ * ordering of frames, having only a "one frame lookahead" is
+ * not a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for which no
+ * Label exist.
+ */
+ /*
+ * This is not true for UNINITIALIZED type offsets. We solve
+ * this by parsing the stack map table without a full decoding
+ * (see below).
+ */
+ } else if (FRAMES && "StackMap".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ zip = false;
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are ordered, as in
+ * the StackMapTable attribute, although this is not guaranteed
+ * by the attribute format.
+ */
+ } else {
+ for (int j = 0; j < context.attrs.length; ++j) {
+ if (context.attrs[j].type.equals(attrName)) {
+ Attribute attr = context.attrs[j].read(this, u + 8,
+ readInt(u + 4), c, codeStart - 8, labels);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
}
}
- v = codeStart;
- Label l;
- while (v < codeEnd) {
- w = v - codeStart;
-
- l = labels[w];
- if (l != null) {
- mv.visitLabel(l);
- if (!skipDebug && l.line > 0) {
- mv.visitLineNumber(l.line, l);
+ }
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // generates the first (implicit) stack map frame
+ if (FRAMES && stackMap != 0) {
+ /*
+ * for the first explicit frame the offset is not offset_delta + 1
+ * but only offset_delta; setting the implicit frame offset to -1
+ * allow the use of the "offset_delta + 1" rule in all cases
+ */
+ frame = context;
+ frame.offset = -1;
+ frame.mode = 0;
+ frame.localCount = 0;
+ frame.localDiff = 0;
+ frame.stackCount = 0;
+ frame.local = new Object[maxLocals];
+ frame.stack = new Object[maxStack];
+ if (unzip) {
+ getImplicitFrame(context);
+ }
+ /*
+ * Finds labels for UNINITIALIZED frame types. Instead of decoding
+ * each element of the stack map table, we look for 3 consecutive
+ * bytes that "look like" an UNINITIALIZED type (tag 8, offset
+ * within code bounds, NEW instruction at this offset). We may find
+ * false positives (i.e. not real UNINITIALIZED types), but this
+ * should be rare, and the only consequence will be the creation of
+ * an unneeded label. This is better than creating a label for each
+ * NEW instruction, and faster than fully decoding the whole stack
+ * map table.
+ */
+ for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
+ if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
+ int v = readUnsignedShort(i + 1);
+ if (v >= 0 && v < codeLength) {
+ if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
+ readLabel(v, labels);
}
}
+ }
+ }
+ }
- while (FRAMES && frameLocal != null
- && (frameOffset == w || frameOffset == -1))
- {
- // if there is a frame for this offset,
- // makes the visitor visit it,
- // and reads the next frame if there is one.
- if (!zip || unzip) {
- mv.visitFrame(Opcodes.F_NEW,
- frameLocalCount,
- frameLocal,
- frameStackCount,
- frameStack);
- } else if (frameOffset != -1) {
- mv.visitFrame(frameMode,
- frameLocalDiff,
- frameLocal,
- frameStackCount,
- frameStack);
- }
+ // visits the instructions
+ u = codeStart;
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+
+ // visits the label and line number for this offset, if any
+ Label l = labels[offset];
+ if (l != null) {
+ mv.visitLabel(l);
+ if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
+ mv.visitLineNumber(l.line, l);
+ }
+ }
- if (frameCount > 0) {
- int tag, delta, n;
- if (zip) {
- tag = b[stackMap++] & 0xFF;
- } else {
- tag = MethodWriter.FULL_FRAME;
- frameOffset = -1;
- }
- frameLocalDiff = 0;
- if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
- {
- delta = tag;
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.RESERVED) {
- delta = tag
- - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else {
- delta = readUnsignedShort(stackMap);
- stackMap += 2;
- if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- {
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else if (tag >= MethodWriter.CHOP_FRAME
- && tag < MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_CHOP;
- frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
- - tag;
- frameLocalCount -= frameLocalDiff;
- frameStackCount = 0;
- } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.FULL_FRAME) {
- j = unzip ?
<TRUNCATED>
[18/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
index 70b26b8..3128ff6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* A {@link MethodVisitor} that generates methods in bytecode form. Each visit
* method of this class appends the bytecode corresponding to the visited
* instruction to a byte vector, in the order these methods are called.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -42,7 +42,7 @@ class MethodWriter extends MethodVisitor {
/**
* Pseudo access flag used to denote constructors.
*/
- static final int ACC_CONSTRUCTOR = 262144;
+ static final int ACC_CONSTRUCTOR = 0x80000;
/**
* Frame has exactly the same locals as the previous stack map frame and
@@ -96,7 +96,7 @@ class MethodWriter extends MethodVisitor {
* Indicates that the stack map frames must be recomputed from scratch. In
* this case the maximum stack size and number of local variables is also
* recomputed from scratch.
- *
+ *
* @see #compute
*/
private static final int FRAMES = 0;
@@ -104,14 +104,14 @@ class MethodWriter extends MethodVisitor {
/**
* Indicates that the maximum stack size and number of local variables must
* be automatically computed.
- *
+ *
* @see #compute
*/
private static final int MAXS = 1;
/**
* Indicates that nothing must be automatically computed.
- *
+ *
* @see #compute
*/
private static final int NOTHING = 2;
@@ -192,6 +192,18 @@ class MethodWriter extends MethodVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this method. May be <tt>null</tt>
+ * .
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The runtime visible parameter annotations of this method. May be
* <tt>null</tt>.
*/
@@ -229,7 +241,7 @@ class MethodWriter extends MethodVisitor {
private int maxLocals;
/**
- * Number of local variables in the current stack map frame.
+ * Number of local variables in the current stack map frame.
*/
private int currentLocals;
@@ -251,17 +263,12 @@ class MethodWriter extends MethodVisitor {
/**
* The last frame that was written in the StackMapTable attribute.
- *
+ *
* @see #frame
*/
private int[] previousFrame;
/**
- * Index of the next element to be added in {@link #frame}.
- */
- private int frameIndex;
-
- /**
* The current stack map frame. The first element contains the offset of the
* instruction to which the frame corresponds, the second element is the
* number of locals and the third one is the number of stack elements. The
@@ -288,6 +295,16 @@ class MethodWriter extends MethodVisitor {
private Handler lastHandler;
/**
+ * Number of entries in the MethodParameters attribute.
+ */
+ private int methodParametersCount;
+
+ /**
+ * The MethodParameters attribute.
+ */
+ private ByteVector methodParameters;
+
+ /**
* Number of entries in the LocalVariableTable attribute.
*/
private int localVarCount;
@@ -318,6 +335,21 @@ class MethodWriter extends MethodVisitor {
private ByteVector lineNumber;
/**
+ * The start offset of the last visited instruction.
+ */
+ private int lastCodeOffset;
+
+ /**
+ * The runtime visible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ctanns;
+
+ /**
+ * The runtime invisible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ictanns;
+
+ /**
* The non standard attributes of the method's code.
*/
private Attribute cattrs;
@@ -346,7 +378,7 @@ class MethodWriter extends MethodVisitor {
/**
* Indicates what must be automatically computed.
- *
+ *
* @see #FRAMES
* @see #MAXS
* @see #NOTHING
@@ -357,7 +389,8 @@ class MethodWriter extends MethodVisitor {
* A list of labels. This list is the list of basic blocks in the method,
* i.e. a list of Label objects linked to each other by their
* {@link Label#successor} field, in the order they are visited by
- * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+ * {@link MethodVisitor#visitLabel}, and starting with the first basic
+ * block.
*/
private Label labels;
@@ -395,30 +428,32 @@ class MethodWriter extends MethodVisitor {
/**
* Constructs a new {@link MethodWriter}.
- *
- * @param cw the class writer in which the method must be added.
- * @param access the method's access flags (see {@link Opcodes}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exceptions. May be
- * <tt>null</tt>.
- * @param computeMaxs <tt>true</tt> if the maximum stack size and number
- * of local variables must be automatically computed.
- * @param computeFrames <tt>true</tt> if the stack map tables must be
- * recomputed from scratch.
- */
- MethodWriter(
- final ClassWriter cw,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions,
- final boolean computeMaxs,
- final boolean computeFrames)
- {
- super(Opcodes.ASM4);
+ *
+ * @param cw
+ * the class writer in which the method must be added.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exceptions. May be
+ * <tt>null</tt>.
+ * @param computeMaxs
+ * <tt>true</tt> if the maximum stack size and number of local
+ * variables must be automatically computed.
+ * @param computeFrames
+ * <tt>true</tt> if the stack map tables must be recomputed from
+ * scratch.
+ */
+ MethodWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions, final boolean computeMaxs,
+ final boolean computeFrames) {
+ super(Opcodes.ASM5);
if (cw.firstMethod == null) {
cw.firstMethod = this;
} else {
@@ -427,6 +462,9 @@ class MethodWriter extends MethodVisitor {
cw.lastMethod = this;
this.cw = cw;
this.access = access;
+ if ("<init>".equals(name)) {
+ this.access |= ACC_CONSTRUCTOR;
+ }
this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc);
this.descriptor = desc;
@@ -442,9 +480,6 @@ class MethodWriter extends MethodVisitor {
}
this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
if (computeMaxs || computeFrames) {
- if (computeFrames && "<init>".equals(name)) {
- this.access |= ACC_CONSTRUCTOR;
- }
// updates maxLocals
int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
if ((access & Opcodes.ACC_STATIC) != 0) {
@@ -464,6 +499,16 @@ class MethodWriter extends MethodVisitor {
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(String name, int access) {
+ if (methodParameters == null) {
+ methodParameters = new ByteVector();
+ }
+ ++methodParametersCount;
+ methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
+ .putShort(access);
+ }
+
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
if (!ClassReader.ANNOTATIONS) {
return null;
@@ -473,10 +518,8 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -495,11 +538,31 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -545,20 +608,18 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
if (!ClassReader.FRAMES || compute == FRAMES) {
return;
}
if (type == Opcodes.F_NEW) {
+ if (previousFrame == null) {
+ visitImplicitFirstFrame();
+ }
currentLocals = nLocal;
- startFrame(code.length, nLocal, nStack);
+ int frameIndex = startFrame(code.length, nLocal, nStack);
for (int i = 0; i < nLocal; ++i) {
if (local[i] instanceof String) {
frame[frameIndex++] = Frame.OBJECT
@@ -601,48 +662,44 @@ class MethodWriter extends MethodVisitor {
}
switch (type) {
- case Opcodes.F_FULL:
- currentLocals = nLocal;
- stackMap.putByte(FULL_FRAME)
- .putShort(delta)
- .putShort(nLocal);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- stackMap.putShort(nStack);
- for (int i = 0; i < nStack; ++i) {
- writeFrameType(stack[i]);
- }
- break;
- case Opcodes.F_APPEND:
- currentLocals += nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
- .putShort(delta);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- break;
- case Opcodes.F_CHOP:
- currentLocals -= nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+ case Opcodes.F_FULL:
+ currentLocals = nLocal;
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ stackMap.putShort(nStack);
+ for (int i = 0; i < nStack; ++i) {
+ writeFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ currentLocals += nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ currentLocals -= nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
+ break;
+ case Opcodes.F_SAME:
+ if (delta < 64) {
+ stackMap.putByte(delta);
+ } else {
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (delta < 64) {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ } else {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
.putShort(delta);
- break;
- case Opcodes.F_SAME:
- if (delta < 64) {
- stackMap.putByte(delta);
- } else {
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- }
- break;
- case Opcodes.F_SAME1:
- if (delta < 64) {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- } else {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- }
- writeFrameType(stack[0]);
- break;
+ }
+ writeFrameType(stack[0]);
+ break;
}
previousFrameOffset = code.length;
@@ -655,6 +712,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitInsn(final int opcode) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
code.putByte(opcode);
// update currentBlock
@@ -672,8 +730,7 @@ class MethodWriter extends MethodVisitor {
}
// if opcode == ATHROW or xRETURN, ends current block (no successor)
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW)
- {
+ || opcode == Opcodes.ATHROW) {
noSuccessor();
}
}
@@ -681,6 +738,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIntInsn(final int opcode, final int operand) {
+ lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -705,6 +763,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitVarInsn(final int opcode, final int var) {
+ lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -731,8 +790,7 @@ class MethodWriter extends MethodVisitor {
// updates max locals
int n;
if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
- || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
- {
+ || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
n = var + 2;
} else {
n = var + 1;
@@ -764,6 +822,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitTypeInsn(final int opcode, final String type) {
+ lastCodeOffset = code.length;
Item i = cw.newClassItem(type);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -784,12 +843,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ lastCodeOffset = code.length;
Item i = cw.newFieldItem(owner, name, desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -800,19 +856,19 @@ class MethodWriter extends MethodVisitor {
// computes the stack size variation
char c = desc.charAt(0);
switch (opcode) {
- case Opcodes.GETSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
- break;
- case Opcodes.PUTSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
- break;
- case Opcodes.GETFIELD:
- size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
- break;
- // case Constants.PUTFIELD:
- default:
- size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
- break;
+ case Opcodes.GETSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+ break;
+ case Opcodes.PUTSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+ break;
+ case Opcodes.GETFIELD:
+ size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+ break;
+ // case Constants.PUTFIELD:
+ default:
+ size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+ break;
}
// updates current and max stack sizes
if (size > maxStackSize) {
@@ -826,13 +882,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ lastCodeOffset = code.length;
Item i = cw.newMethodItem(owner, name, desc, itf);
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
@@ -870,7 +922,7 @@ class MethodWriter extends MethodVisitor {
}
}
// adds the instruction to the bytecode of the method
- if (itf) {
+ if (opcode == Opcodes.INVOKEINTERFACE) {
if (argSize == 0) {
argSize = Type.getArgumentsAndReturnSizes(desc);
i.intVal = argSize;
@@ -882,12 +934,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitInvokeDynamicInsn(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
+ lastCodeOffset = code.length;
Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
@@ -927,6 +976,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitJumpInsn(final int opcode, final Label label) {
+ lastCodeOffset = code.length;
Label nextInsn = null;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -967,8 +1017,7 @@ class MethodWriter extends MethodVisitor {
}
// adds the instruction to the bytecode of the method
if ((label.status & Label.RESOLVED) != 0
- && label.position - code.length < Short.MIN_VALUE)
- {
+ && label.position - code.length < Short.MIN_VALUE) {
/*
* case of a backward jump with an offset < -32768. In this case we
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
@@ -986,8 +1035,7 @@ class MethodWriter extends MethodVisitor {
if (nextInsn != null) {
nextInsn.status |= Label.TARGET;
}
- code.putByte(opcode <= 166
- ? ((opcode + 1) ^ 1) - 1
+ code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1);
code.putShort(8); // jump offset
code.putByte(200); // GOTO_W
@@ -1074,6 +1122,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitLdcInsn(final Object cst) {
+ lastCodeOffset = code.length;
Item i = cw.newConstItem(cst);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1082,8 +1131,7 @@ class MethodWriter extends MethodVisitor {
} else {
int size;
// computes the stack size variation
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
- {
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
size = stackSize + 2;
} else {
size = stackSize + 1;
@@ -1108,6 +1156,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIincInsn(final int var, final int increment) {
+ lastCodeOffset = code.length;
if (currentBlock != null) {
if (compute == FRAMES) {
currentBlock.frame.execute(Opcodes.IINC, var, null, null);
@@ -1122,8 +1171,7 @@ class MethodWriter extends MethodVisitor {
}
// adds the instruction to the bytecode of the method
if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /* WIDE */)
- .put12(Opcodes.IINC, var)
+ code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
.putShort(increment);
} else {
code.putByte(Opcodes.IINC).put11(var, increment);
@@ -1131,12 +1179,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.TABLESWITCH);
@@ -1151,11 +1196,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.LOOKUPSWITCH);
@@ -1198,6 +1241,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ lastCodeOffset = code.length;
Item i = cw.newClassItem(desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1214,12 +1258,32 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
++handlerCount;
Handler h = new Handler();
h.start = start;
@@ -1236,14 +1300,32 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
if (signature != null) {
if (localVarType == null) {
localVarType = new ByteVector();
@@ -1251,8 +1333,7 @@ class MethodWriter extends MethodVisitor {
++localVarTypeCount;
localVarType.putShort(start.position)
.putShort(end.position - start.position)
- .putShort(cw.newUTF8(name))
- .putShort(cw.newUTF8(signature))
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
.putShort(index);
}
if (localVar == null) {
@@ -1261,8 +1342,7 @@ class MethodWriter extends MethodVisitor {
++localVarCount;
localVar.putShort(start.position)
.putShort(end.position - start.position)
- .putShort(cw.newUTF8(name))
- .putShort(cw.newUTF8(desc))
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
.putShort(index);
if (compute != NOTHING) {
// updates max locals
@@ -1275,6 +1355,41 @@ class MethodWriter extends MethodVisitor {
}
@Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ bv.putByte(typeRef >>> 24).putShort(start.length);
+ for (int i = 0; i < start.length; ++i) {
+ bv.putShort(start[i].position)
+ .putShort(end[i].position - start[i].position)
+ .putShort(index[i]);
+ }
+ if (typePath == null) {
+ bv.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ bv.putByteArray(typePath.b, typePath.offset, length);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public void visitLineNumber(final int line, final Label start) {
if (lineNumber == null) {
lineNumber = new ByteVector();
@@ -1286,6 +1401,14 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
if (ClassReader.FRAMES && compute == FRAMES) {
// completes the control flow graph with exception handler blocks
Handler handler = firstHandler;
@@ -1294,8 +1417,7 @@ class MethodWriter extends MethodVisitor {
Label h = handler.handler.getFirst();
Label e = handler.end.getFirst();
// computes the kind of the edges to 'h'
- String t = handler.desc == null
- ? "java/lang/Throwable"
+ String t = handler.desc == null ? "java/lang/Throwable"
: handler.desc;
int kind = Frame.OBJECT | cw.addType(t);
// h is an exception handler
@@ -1382,11 +1504,12 @@ class MethodWriter extends MethodVisitor {
}
code.data[end] = (byte) Opcodes.ATHROW;
// emits a frame for this unreachable block
- startFrame(start, 0, 1);
- frame[frameIndex++] = Frame.OBJECT
+ int frameIndex = startFrame(start, 0, 1);
+ frame[frameIndex] = Frame.OBJECT
| cw.addType("java/lang/Throwable");
endFrame();
- // removes the start-end range from the exception handlers
+ // removes the start-end range from the exception
+ // handlers
firstHandler = Handler.remove(firstHandler, l, k);
}
}
@@ -1534,9 +1657,11 @@ class MethodWriter extends MethodVisitor {
/**
* Adds a successor to the {@link #currentBlock currentBlock} block.
- *
- * @param info information about the control flow edge to be added.
- * @param successor the successor block to be added to the current block.
+ *
+ * @param info
+ * information about the control flow edge to be added.
+ * @param successor
+ * the successor block to be added to the current block.
*/
private void addSuccessor(final int info, final Label successor) {
// creates and initializes an Edge object...
@@ -1572,8 +1697,9 @@ class MethodWriter extends MethodVisitor {
/**
* Visits a frame that has been computed from scratch.
- *
- * @param f the frame that must be visited.
+ *
+ * @param f
+ * the frame that must be visited.
*/
private void visitFrame(final Frame f) {
int i, t;
@@ -1606,7 +1732,7 @@ class MethodWriter extends MethodVisitor {
}
}
// visits the frame and its content
- startFrame(f.owner.position, nLocal, nStack);
+ int frameIndex = startFrame(f.owner.position, nLocal, nStack);
for (i = 0; nLocal > 0; ++i, --nLocal) {
t = locals[i];
frame[frameIndex++] = t;
@@ -1625,15 +1751,78 @@ class MethodWriter extends MethodVisitor {
}
/**
+ * Visit the implicit first frame of this method.
+ */
+ private void visitImplicitFirstFrame() {
+ // There can be at most descriptor.length() + 1 locals
+ int frameIndex = startFrame(0, descriptor.length() + 1, 0);
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & ACC_CONSTRUCTOR) == 0) {
+ frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
+ } else {
+ frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+ }
+ }
+ int i = 1;
+ loop: while (true) {
+ int j = i;
+ switch (descriptor.charAt(i++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ frame[frameIndex++] = 1; // Opcodes.INTEGER;
+ break;
+ case 'F':
+ frame[frameIndex++] = 2; // Opcodes.FLOAT;
+ break;
+ case 'J':
+ frame[frameIndex++] = 4; // Opcodes.LONG;
+ break;
+ case 'D':
+ frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (descriptor.charAt(i) == '[') {
+ ++i;
+ }
+ if (descriptor.charAt(i) == 'L') {
+ ++i;
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j, ++i));
+ break;
+ case 'L':
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j + 1, i++));
+ break;
+ default:
+ break loop;
+ }
+ }
+ frame[1] = frameIndex - 3;
+ endFrame();
+ }
+
+ /**
* Starts the visit of a stack map frame.
- *
- * @param offset the offset of the instruction to which the frame
- * corresponds.
- * @param nLocal the number of local variables in the frame.
- * @param nStack the number of stack elements in the frame.
- */
- private void startFrame(final int offset, final int nLocal, final int nStack)
- {
+ *
+ * @param offset
+ * the offset of the instruction to which the frame corresponds.
+ * @param nLocal
+ * the number of local variables in the frame.
+ * @param nStack
+ * the number of stack elements in the frame.
+ * @return the index of the next element to be written in this frame.
+ */
+ private int startFrame(final int offset, final int nLocal, final int nStack) {
int n = 3 + nLocal + nStack;
if (frame == null || frame.length < n) {
frame = new int[n];
@@ -1641,7 +1830,7 @@ class MethodWriter extends MethodVisitor {
frame[0] = offset;
frame[1] = nLocal;
frame[2] = nStack;
- frameIndex = 3;
+ return 3;
}
/**
@@ -1686,24 +1875,23 @@ class MethodWriter extends MethodVisitor {
if (cstackSize == 0) {
k = clocalsSize - localsSize;
switch (k) {
- case -3:
- case -2:
- case -1:
- type = CHOP_FRAME;
- localsSize = clocalsSize;
- break;
- case 0:
- type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
- break;
- case 1:
- case 2:
- case 3:
- type = APPEND_FRAME;
- break;
+ case -3:
+ case -2:
+ case -1:
+ type = CHOP_FRAME;
+ localsSize = clocalsSize;
+ break;
+ case 0:
+ type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ type = APPEND_FRAME;
+ break;
}
} else if (clocalsSize == localsSize && cstackSize == 1) {
- type = delta < 63
- ? SAME_LOCALS_1_STACK_ITEM_FRAME
+ type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
: SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
}
if (type != FULL_FRAME) {
@@ -1718,36 +1906,34 @@ class MethodWriter extends MethodVisitor {
}
}
switch (type) {
- case SAME_FRAME:
- stackMap.putByte(delta);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_FRAME_EXTENDED:
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- break;
- case CHOP_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- break;
- case APPEND_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- writeFrameTypes(3 + localsSize, 3 + clocalsSize);
- break;
- // case FULL_FRAME:
- default:
- stackMap.putByte(FULL_FRAME)
- .putShort(delta)
- .putShort(clocalsSize);
- writeFrameTypes(3, 3 + clocalsSize);
- stackMap.putShort(cstackSize);
- writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ case SAME_FRAME:
+ stackMap.putByte(delta);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
+ delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_FRAME_EXTENDED:
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ break;
+ case CHOP_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ break;
+ case APPEND_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+ break;
+ // case FULL_FRAME:
+ default:
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
}
}
@@ -1756,9 +1942,11 @@ class MethodWriter extends MethodVisitor {
* StackMapTableAttribute. This method converts types from the format used
* in {@link Label} to the format used in StackMapTable attributes. In
* particular, it converts type table indexes to constant pool indexes.
- *
- * @param start index of the first type in {@link #frame} to write.
- * @param end index of last type in {@link #frame} to write (exclusive).
+ *
+ * @param start
+ * index of the first type in {@link #frame} to write.
+ * @param end
+ * index of last type in {@link #frame} to write (exclusive).
*/
private void writeFrameTypes(final int start, final int end) {
for (int i = start; i < end; ++i) {
@@ -1767,15 +1955,15 @@ class MethodWriter extends MethodVisitor {
if (d == 0) {
int v = t & Frame.BASE_VALUE;
switch (t & Frame.BASE_KIND) {
- case Frame.OBJECT:
- stackMap.putByte(7)
- .putShort(cw.newClass(cw.typeTable[v].strVal1));
- break;
- case Frame.UNINITIALIZED:
- stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
- break;
- default:
- stackMap.putByte(v);
+ case Frame.OBJECT:
+ stackMap.putByte(7).putShort(
+ cw.newClass(cw.typeTable[v].strVal1));
+ break;
+ case Frame.UNINITIALIZED:
+ stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+ break;
+ default:
+ stackMap.putByte(v);
}
} else {
StringBuffer buf = new StringBuffer();
@@ -1789,29 +1977,29 @@ class MethodWriter extends MethodVisitor {
buf.append(';');
} else {
switch (t & 0xF) {
- case 1:
- buf.append('I');
- break;
- case 2:
- buf.append('F');
- break;
- case 3:
- buf.append('D');
- break;
- case 9:
- buf.append('Z');
- break;
- case 10:
- buf.append('B');
- break;
- case 11:
- buf.append('C');
- break;
- case 12:
- buf.append('S');
- break;
- default:
- buf.append('J');
+ case 1:
+ buf.append('I');
+ break;
+ case 2:
+ buf.append('F');
+ break;
+ case 3:
+ buf.append('D');
+ break;
+ case 9:
+ buf.append('Z');
+ break;
+ case 10:
+ buf.append('B');
+ break;
+ case 11:
+ buf.append('C');
+ break;
+ case 12:
+ buf.append('S');
+ break;
+ default:
+ buf.append('J');
}
}
stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
@@ -1835,21 +2023,13 @@ class MethodWriter extends MethodVisitor {
/**
* Returns the size of the bytecode of this method.
- *
+ *
* @return the size of the bytecode of this method.
*/
final int getSize() {
if (classReaderOffset != 0) {
return 6 + classReaderLength;
}
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- if (ClassReader.RESIZE) {
- resizeInstructions();
- } else {
- throw new RuntimeException("Method code too large!");
- }
- }
int size = 8;
if (code.length > 0) {
if (code.length > 65536) {
@@ -1874,11 +2054,16 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(zip ? "StackMapTable" : "StackMap");
size += 8 + stackMap.length;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + ictanns.getSize();
+ }
if (cattrs != null) {
- size += cattrs.getSize(cw,
- code.data,
- code.length,
- maxStack,
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
}
}
@@ -1886,11 +2071,12 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8("Exceptions");
size += 8 + 2 * exceptionCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- cw.newUTF8("Synthetic");
- size += 6;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
@@ -1901,6 +2087,10 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(signature);
size += 8;
}
+ if (methodParameters != null) {
+ cw.newUTF8("MethodParameters");
+ size += 7 + methodParameters.length;
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
cw.newUTF8("AnnotationDefault");
size += 6 + annd.length;
@@ -1913,6 +2103,14 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
cw.newUTF8("RuntimeVisibleParameterAnnotations");
size += 7 + 2 * (panns.length - synthetics);
@@ -1935,14 +2133,16 @@ class MethodWriter extends MethodVisitor {
/**
* Puts the bytecode of this method in the given byte vector.
- *
- * @param out the byte vector into which the bytecode of this method must be
- * copied.
+ *
+ * @param out
+ * the byte vector into which the bytecode of this method must be
+ * copied.
*/
final void put(final ByteVector out) {
- int mask = Opcodes.ACC_DEPRECATED
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
if (classReaderOffset != 0) {
out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
@@ -1955,10 +2155,11 @@ class MethodWriter extends MethodVisitor {
if (exceptionCount > 0) {
++attributeCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
@@ -1966,6 +2167,9 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.SIGNATURES && signature != null) {
++attributeCount;
}
+ if (methodParameters != null) {
+ ++attributeCount;
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
++attributeCount;
}
@@ -1975,6 +2179,12 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
++attributeCount;
}
@@ -1999,11 +2209,14 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
size += 8 + stackMap.length;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ size += 8 + ictanns.getSize();
+ }
if (cattrs != null) {
- size += cattrs.getSize(cw,
- code.data,
- code.length,
- maxStack,
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
}
out.putShort(cw.newUTF8("Code")).putInt(size);
@@ -2013,10 +2226,8 @@ class MethodWriter extends MethodVisitor {
if (handlerCount > 0) {
Handler h = firstHandler;
while (h != null) {
- out.putShort(h.start.position)
- .putShort(h.end.position)
- .putShort(h.handler.position)
- .putShort(h.type);
+ out.putShort(h.start.position).putShort(h.end.position)
+ .putShort(h.handler.position).putShort(h.type);
h = h.next;
}
}
@@ -2033,6 +2244,12 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ ++attributeCount;
+ }
if (cattrs != null) {
attributeCount += cattrs.getCount();
}
@@ -2058,31 +2275,45 @@ class MethodWriter extends MethodVisitor {
out.putInt(stackMap.length + 2).putShort(frameCount);
out.putByteArray(stackMap.data, 0, stackMap.length);
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ ctanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ ictanns.put(out);
+ }
if (cattrs != null) {
cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
}
}
if (exceptionCount > 0) {
- out.putShort(cw.newUTF8("Exceptions"))
- .putInt(2 * exceptionCount + 2);
+ out.putShort(cw.newUTF8("Exceptions")).putInt(
+ 2 * exceptionCount + 2);
out.putShort(exceptionCount);
for (int i = 0; i < exceptionCount; ++i) {
out.putShort(exceptions[i]);
}
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
}
if (ClassReader.SIGNATURES && signature != null) {
- out.putShort(cw.newUTF8("Signature"))
- .putInt(2)
+ out.putShort(cw.newUTF8("Signature")).putInt(2)
.putShort(cw.newUTF8(signature));
}
+ if (methodParameters != null) {
+ out.putShort(cw.newUTF8("MethodParameters"));
+ out.putInt(methodParameters.length + 1).putByte(
+ methodParametersCount);
+ out.putByteArray(methodParameters.data, 0, methodParameters.length);
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
out.putShort(cw.newUTF8("AnnotationDefault"));
out.putInt(annd.length);
@@ -2096,6 +2327,14 @@ class MethodWriter extends MethodVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
AnnotationWriter.put(panns, synthetics, out);
@@ -2123,10 +2362,12 @@ class MethodWriter extends MethodVisitor {
* 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
* 32765. This, in turn, may require to increase the size of another jump
* instruction, and so on... All these operations are handled automatically
- * by this method. <p> <i>This method must be called after all the method
- * that is being built has been visited</i>. In particular, the
- * {@link Label Label} objects used to construct the method are no longer
- * valid after this method has been called.
+ * by this method.
+ * <p>
+ * <i>This method must be called after all the method that is being built
+ * has been visited</i>. In particular, the {@link Label Label} objects used
+ * to construct the method are no longer valid after this method has been
+ * called.
*/
private void resizeInstructions() {
byte[] b = code.data; // bytecode of the method
@@ -2138,17 +2379,17 @@ class MethodWriter extends MethodVisitor {
* so on. The first step of the algorithm consists in finding all the
* instructions that need to be resized, without modifying the code.
* This is done by the following "fix point" algorithm:
- *
+ *
* Parse the code to find the jump instructions whose offset will need
* more than 2 bytes to be stored (the future offset is computed from
* the current offset and from the number of bytes that will be inserted
* or removed between the source and target instructions). For each such
* instruction, adds an entry in (a copy of) the indexes and sizes
* arrays (if this has not already been done in a previous iteration!).
- *
+ *
* If at least one entry has been added during the previous step, go
* back to the beginning, otherwise stop.
- *
+ *
* In fact the real algorithm is complicated by the fact that the size
* of TABLESWITCH and LOOKUPSWITCH instructions depends on their
* position in the bytecode (because of padding). In order to ensure the
@@ -2176,158 +2417,14 @@ class MethodWriter extends MethodVisitor {
int insert = 0; // bytes to be added after this instruction
switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // converts temporary opcodes 202 to 217, 218 and
- // 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (newOffset < Short.MIN_VALUE
- || newOffset > Short.MAX_VALUE)
- {
- if (!resize[u]) {
- if (opcode == Opcodes.GOTO
- || opcode == Opcodes.JSR)
- {
- // two additional bytes will be required to
- // replace this GOTO or JSR instruction with
- // a GOTO_W or a JSR_W
- insert = 2;
- } else {
- // five additional bytes will be required to
- // replace this IFxxx <l> instruction with
- // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
- // is the "opposite" opcode of IFxxx (i.e.,
- // IFNE for IFEQ) and where <l'> designates
- // the instruction just after the GOTO_W.
- insert = 5;
- }
- resize[u] = true;
- }
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- if (state == 1) {
- // true number of bytes to be added (or removed)
- // from this instruction = (future number of padding
- // bytes - current number of padding byte) -
- // previously over estimated variation =
- // = ((3 - newOffset%4) - (3 - u%4)) - u%4
- // = (-newOffset%4 + u%4) - u%4
- // = -(newOffset & 3)
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // over estimation of the number of bytes to be
- // added to this instruction = 3 - current number
- // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
- break;
- case ClassWriter.LOOK_INSN:
- if (state == 1) {
- // like TABL_INSN
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // like TABL_INSN
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 8 * readInt(b, u + 4) + 8;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- u += 5;
- break;
- // case ClassWriter.MANA_INSN:
- default:
- u += 4;
- break;
- }
- if (insert != 0) {
- // adds a new (u, insert) entry in the allIndexes and
- // allSizes arrays
- int[] newIndexes = new int[allIndexes.length + 1];
- int[] newSizes = new int[allSizes.length + 1];
- System.arraycopy(allIndexes,
- 0,
- newIndexes,
- 0,
- allIndexes.length);
- System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
- newIndexes[allIndexes.length] = u;
- newSizes[allSizes.length] = insert;
- allIndexes = newIndexes;
- allSizes = newSizes;
- if (insert > 0) {
- state = 3;
- }
- }
- }
- if (state < 3) {
- --state;
- }
- } while (state != 0);
-
- // 2nd step:
- // copies the bytecode of the method into a new bytevector, updates the
- // offsets, and inserts (or removes) bytes as requested.
-
- ByteVector newCode = new ByteVector(code.length);
-
- u = 0;
- while (u < code.length) {
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
case ClassWriter.NOARG_INSN:
case ClassWriter.IMPLVAR_INSN:
- newCode.putByte(opcode);
u += 1;
break;
case ClassWriter.LABEL_INSN:
if (opcode > 201) {
- // changes temporary opcodes 202 to 217 (inclusive), 218
- // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // converts temporary opcodes 202 to 217, 218 and
+ // 219 to IFEQ ... JSR (inclusive), IFNULL and
// IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
label = u + readUnsignedShort(b, u + 1);
@@ -2335,100 +2432,78 @@ class MethodWriter extends MethodVisitor {
label = u + readShort(b, u + 1);
}
newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (resize[u]) {
- // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
- // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
- // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
- // and where <l'> designates the instruction just after
- // the GOTO_W.
- if (opcode == Opcodes.GOTO) {
- newCode.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- newCode.putByte(201); // JSR_W
- } else {
- newCode.putByte(opcode <= 166
- ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- newCode.putShort(8); // jump offset
- newCode.putByte(200); // GOTO_W
- // newOffset now computed from start of GOTO_W
- newOffset -= 3;
+ if (newOffset < Short.MIN_VALUE
+ || newOffset > Short.MAX_VALUE) {
+ if (!resize[u]) {
+ if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+ // two additional bytes will be required to
+ // replace this GOTO or JSR instruction with
+ // a GOTO_W or a JSR_W
+ insert = 2;
+ } else {
+ // five additional bytes will be required to
+ // replace this IFxxx <l> instruction with
+ // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+ // is the "opposite" opcode of IFxxx (i.e.,
+ // IFNE for IFEQ) and where <l'> designates
+ // the instruction just after the GOTO_W.
+ insert = 5;
+ }
+ resize[u] = true;
}
- newCode.putInt(newOffset);
- } else {
- newCode.putByte(opcode);
- newCode.putShort(newOffset);
}
u += 3;
break;
case ClassWriter.LABELW_INSN:
- label = u + readInt(b, u + 1);
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- newCode.putByte(opcode);
- newCode.putInt(newOffset);
u += 5;
break;
case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.TABLESWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- j = readInt(b, u) - j + 1;
- u += 4;
- newCode.putInt(readInt(b, u - 4));
- for (; j > 0; --j) {
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
+ if (state == 1) {
+ // true number of bytes to be added (or removed)
+ // from this instruction = (future number of padding
+ // bytes - current number of padding byte) -
+ // previously over estimated variation =
+ // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+ // = (-newOffset%4 + u%4) - u%4
+ // = -(newOffset & 3)
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // over estimation of the number of bytes to be
+ // added to this instruction = 3 - current number
+ // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+ insert = u & 3;
+ resize[u] = true;
}
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
break;
case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.LOOKUPSWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- for (; j > 0; --j) {
- newCode.putInt(readInt(b, u));
- u += 4;
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
+ if (state == 1) {
+ // like TABL_INSN
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // like TABL_INSN
+ insert = u & 3;
+ resize[u] = true;
}
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 8 * readInt(b, u + 4) + 8;
break;
case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) {
- newCode.putByteArray(b, u, 6);
u += 6;
} else {
- newCode.putByteArray(b, u, 4);
u += 4;
}
break;
case ClassWriter.VAR_INSN:
case ClassWriter.SBYTE_INSN:
case ClassWriter.LDC_INSN:
- newCode.putByteArray(b, u, 2);
u += 2;
break;
case ClassWriter.SHORT_INSN:
@@ -2436,66 +2511,225 @@ class MethodWriter extends MethodVisitor {
case ClassWriter.FIELDORMETH_INSN:
case ClassWriter.TYPE_INSN:
case ClassWriter.IINC_INSN:
- newCode.putByteArray(b, u, 3);
u += 3;
break;
case ClassWriter.ITFMETH_INSN:
case ClassWriter.INDYMETH_INSN:
- newCode.putByteArray(b, u, 5);
u += 5;
break;
- // case MANA_INSN:
+ // case ClassWriter.MANA_INSN:
default:
- newCode.putByteArray(b, u, 4);
u += 4;
break;
+ }
+ if (insert != 0) {
+ // adds a new (u, insert) entry in the allIndexes and
+ // allSizes arrays
+ int[] newIndexes = new int[allIndexes.length + 1];
+ int[] newSizes = new int[allSizes.length + 1];
+ System.arraycopy(allIndexes, 0, newIndexes, 0,
+ allIndexes.length);
+ System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+ newIndexes[allIndexes.length] = u;
+ newSizes[allSizes.length] = insert;
+ allIndexes = newIndexes;
+ allSizes = newSizes;
+ if (insert > 0) {
+ state = 3;
+ }
+ }
}
- }
+ if (state < 3) {
+ --state;
+ }
+ } while (state != 0);
- // recomputes the stack map frames
- if (frameCount > 0) {
- if (compute == FRAMES) {
- frameCount = 0;
- stackMap = null;
- previousFrame = null;
- frame = null;
- Frame f = new Frame();
- f.owner = labels;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, maxLocals);
- visitFrame(f);
- Label l = labels;
- while (l != null) {
- /*
- * here we need the original label position. getNewOffset
- * must therefore never have been called for this label.
- */
- u = l.position - 3;
- if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
- {
- getNewOffset(allIndexes, allSizes, l);
- // TODO update offsets in UNINITIALIZED values
- visitFrame(l.frame);
+ // 2nd step:
+ // copies the bytecode of the method into a new bytevector, updates the
+ // offsets, and inserts (or removes) bytes as requested.
+
+ ByteVector newCode = new ByteVector(code.length);
+
+ u = 0;
+ while (u < code.length) {
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ newCode.putByte(opcode);
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (resize[u]) {
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where <l'> designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO) {
+ newCode.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ newCode.putByte(201); // JSR_W
+ } else {
+ newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ newCode.putShort(8); // jump offset
+ newCode.putByte(200); // GOTO_W
+ // newOffset now computed from start of GOTO_W
+ newOffset -= 3;
}
- l = l.successor;
+ newCode.putInt(newOffset);
+ } else {
+ newCode.putByte(opcode);
+ newCode.putShort(newOffset);
}
- } else {
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ label = u + readInt(b, u + 1);
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ newCode.putByte(opcode);
+ newCode.putInt(newOffset);
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.TABLESWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ j = readInt(b, u) - j + 1;
+ u += 4;
+ newCode.putInt(readInt(b, u - 4));
+ for (; j > 0; --j) {
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.LOOKUPSWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ for (; j > 0; --j) {
+ newCode.putInt(readInt(b, u));
+ u += 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ newCode.putByteArray(b, u, 6);
+ u += 6;
+ } else {
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ newCode.putByteArray(b, u, 2);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ newCode.putByteArray(b, u, 3);
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ newCode.putByteArray(b, u, 5);
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ break;
+ }
+ }
+
+ // updates the stack map frame labels
+ if (compute == FRAMES) {
+ Label l = labels;
+ while (l != null) {
/*
- * Resizing an existing stack map frame table is really hard.
- * Not only the table must be parsed to update the offets, but
- * new frames may be needed for jump instructions that were
- * inserted by this method. And updating the offsets or
- * inserting frames can change the format of the following
- * frames, in case of packed frames. In practice the whole table
- * must be recomputed. For this the frames are marked as
- * potentially invalid. This will cause the whole class to be
- * reread and rewritten with the COMPUTE_FRAMES option (see the
- * ClassWriter.toByteArray method). This is not very efficient
- * but is much easier and requires much less code than any other
- * method I can think of.
+ * Detects the labels that are just after an IF instruction that
+ * has been resized with the IFNOT GOTO_W pattern. These labels
+ * are now the target of a jump instruction (the IFNOT
+ * instruction). Note that we need the original label position
+ * here. getNewOffset must therefore never have been called for
+ * this label.
*/
- cw.invalidFrames = true;
+ u = l.position - 3;
+ if (u >= 0 && resize[u]) {
+ l.status |= Label.TARGET;
+ }
+ getNewOffset(allIndexes, allSizes, l);
+ l = l.successor;
+ }
+ // Update the offsets in the uninitialized types
+ for (i = 0; i < cw.typeTable.length; ++i) {
+ Item item = cw.typeTable[i];
+ if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+ item.intVal = getNewOffset(allIndexes, allSizes, 0,
+ item.intVal);
+ }
}
+ // The stack map frames are not serialized yet, so we don't need
+ // to update them. They will be serialized in visitMaxs.
+ } else if (frameCount > 0) {
+ /*
+ * Resizing an existing stack map frame table is really hard. Not
+ * only the table must be parsed to update the offets, but new
+ * frames may be needed for jump instructions that were inserted by
+ * this method. And updating the offsets or inserting frames can
+ * change the format of the following frames, in case of packed
+ * frames. In practice the whole table must be recomputed. For this
+ * the frames are marked as potentially invalid. This will cause the
+ * whole class to be reread and rewritten with the COMPUTE_FRAMES
+ * option (see the ClassWriter.toByteArray method). This is not very
+ * efficient but is much easier and requires much less code than any
+ * other method I can think of.
+ */
+ cw.invalidFrames = true;
}
// updates the exception handler block labels
Handler h = firstHandler;
@@ -2528,10 +2762,11 @@ class MethodWriter extends MethodVisitor {
b = lineNumber.data;
u = 0;
while (u < lineNumber.length) {
- writeShort(b, u, getNewOffset(allIndexes,
- allSizes,
- 0,
- readUnsignedShort(b, u)));
+ writeShort(
+ b,
+ u,
+ getNewOffset(allIndexes, allSizes, 0,
+ readUnsignedShort(b, u)));
u += 4;
}
}
@@ -2553,9 +2788,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads an unsigned short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static int readUnsignedShort(final byte[] b, final int index) {
@@ -2564,9 +2801,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads a signed short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static short readShort(final byte[] b, final int index) {
@@ -2575,9 +2814,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads a signed int value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static int readInt(final byte[] b, final int index) {
@@ -2587,10 +2828,13 @@ class MethodWriter extends MethodVisitor {
/**
* Writes a short value in the given byte array.
- *
- * @param b a byte array.
- * @param index where the first byte of the short value must be written.
- * @param s the value to be written in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * where the first byte of the short value must be written.
+ * @param s
+ * the value to be written in the given byte array.
*/
static void writeShort(final byte[] b, final int index, final int s) {
b[index] = (byte) (s >>> 8);
@@ -2598,32 +2842,34 @@ class MethodWriter extends MethodVisitor {
}
/**
- * Computes the future value of a bytecode offset. <p> Note: it is possible
- * to have several entries for the same instruction in the <tt>indexes</tt>
- * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
- * are equivalent to a single entry (index=a,size=b+b').
- *
<TRUNCATED>
[06/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..294fd46
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
@@ -0,0 +1,1009 @@
+/***
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link ClassVisitor} 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 ClassVisitor {
+
+ /**
+ * 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<Label, Integer> labels;
+
+ /**
+ * <tt>true</tt> if the method code must be checked with a BasicVerifier.
+ */
+ private boolean checkDataFlow;
+
+ /**
+ * Checks a given class.
+ * <p>
+ * Usage: CheckClassAdapter <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ if (args.length != 1) {
+ System.err.println("Verifies the given class.");
+ System.err.println("Usage: CheckClassAdapter "
+ + "<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<MethodNode> methods = cn.methods;
+
+ List<Type> interfaces = new ArrayList<Type>();
+ for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
+ interfaces.add(Type.getObjectType(i.next()));
+ }
+
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = methods.get(i);
+ SimpleVerifier verifier = new SimpleVerifier(
+ Type.getObjectType(cn.name), syperType, interfaces,
+ (cn.access & Opcodes.ACC_INTERFACE) != 0);
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(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<BasicValue> a,
+ final PrintWriter pw) {
+ Frame<BasicValue>[] frames = a.getFrames();
+ Textifier t = new Textifier();
+ TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+ pw.println(method.name + method.desc);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ method.instructions.get(j).accept(mv);
+
+ StringBuffer s = new StringBuffer();
+ Frame<BasicValue> f = frames[j];
+ if (f == null) {
+ s.append('?');
+ } else {
+ for (int k = 0; k < f.getLocals(); ++k) {
+ s.append(getShortName(f.getLocal(k).toString()))
+ .append(' ');
+ }
+ s.append(" : ");
+ for (int k = 0; k < f.getStackSize(); ++k) {
+ s.append(getShortName(f.getStack(k).toString()))
+ .append(' ');
+ }
+ }
+ while (s.length() < method.maxStack + method.maxLocals + 1) {
+ s.append(' ');
+ }
+ pw.print(Integer.toString(j + 100000).substring(1));
+ pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+ }
+ for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+ method.tryCatchBlocks.get(j).accept(mv);
+ pw.print(" " + t.text.get(t.text.size() - 1));
+ }
+ pw.println();
+ }
+
+ private static String getShortName(final String name) {
+ int n = name.lastIndexOf('/');
+ int k = name.length();
+ if (name.charAt(k - 1) == ';') {
+ k--;
+ }
+ return n == -1 ? name : name.substring(n + 1, k);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param cv
+ * the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor cv) {
+ this(cv, true);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @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.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
+ this(Opcodes.ASM5, cv, checkDataFlow);
+ if (getClass() != CheckClassAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @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.
+ */
+ protected CheckClassAdapter(final int api, final ClassVisitor cv,
+ final boolean checkDataFlow) {
+ super(api, cv);
+ this.labels = new HashMap<Label, Integer>();
+ this.checkDataFlow = checkDataFlow;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ if (start) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ start = true;
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+ + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (name == null || !name.endsWith("package-info")) {
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException(
+ "The super class name of the Object class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(superName, "super class name");
+ }
+ if (signature != null) {
+ checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException(
+ "The super class name of interfaces must be 'java/lang/Object'");
+ }
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(interfaces[i],
+ "interface name at index " + i);
+ }
+ }
+ this.version = version;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (source) {
+ throw new IllegalStateException(
+ "visitSource can be called only once.");
+ }
+ source = true;
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ checkState();
+ if (outer) {
+ throw new IllegalStateException(
+ "visitOuterClass can be called only once.");
+ }
+ outer = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
+ }
+ if (desc != null) {
+ CheckMethodAdapter.checkMethodDesc(desc);
+ }
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+ }
+ if (innerName != null) {
+ int start = 0;
+ while (start < innerName.length()
+ && Character.isDigit(innerName.charAt(start))) {
+ start++;
+ }
+ if (start == 0 || start < innerName.length()) {
+ CheckMethodAdapter.checkIdentifier(innerName, start, -1,
+ "inner class name");
+ }
+ }
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+ + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (signature != null) {
+ checkFieldSignature(signature);
+ }
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ FieldVisitor av = super
+ .visitField(access, name, desc, signature, value);
+ return new CheckFieldAdapter(av);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+ + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+ + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
+ CheckMethodAdapter.checkMethodIdentifier(version, name,
+ "method name");
+ }
+ CheckMethodAdapter.checkMethodDesc(desc);
+ if (signature != null) {
+ checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(exceptions[i],
+ "exception name at index " + i);
+ }
+ }
+ CheckMethodAdapter cma;
+ if (checkDataFlow) {
+ cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
+ access, name, desc, signature, exceptions), labels);
+ } else {
+ cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
+ signature, exceptions), labels);
+ }
+ cma.version = version;
+ return cma;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkState();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkState();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.CLASS_TYPE_PARAMETER
+ && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.CLASS_EXTENDS) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkState();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkState();
+ end = true;
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that the visit method has been called and that visitEnd has not
+ * been called.
+ */
+ private void checkState() {
+ if (!start) {
+ throw new IllegalStateException(
+ "Cannot visit member before visit has been called.");
+ }
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot visit member after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This
+ * method also checks that mutually incompatible flags are not set
+ * simultaneously.
+ *
+ * @param access
+ * the access flags to be checked
+ * @param possibleAccess
+ * the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: "
+ + access);
+ }
+ int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+ int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+ int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+ if (pub + pri + pro > 1) {
+ throw new IllegalArgumentException(
+ "public private and protected are mutually exclusive: "
+ + access);
+ }
+ int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+ int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+ if (fin + abs > 1) {
+ throw new IllegalArgumentException(
+ "final and abstract are mutually exclusive: " + access);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkClassSignature(final String signature) {
+ // ClassSignature:
+ // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkMethodSignature(final String signature) {
+ // MethodTypeSignature:
+ // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+ // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkFieldSignature(final String signature) {
+ int pos = checkFieldTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks the reference to a type in a type annotation.
+ *
+ * @param typeRef
+ * a reference to an annotated type.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ */
+ static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
+ int mask = 0;
+ switch (typeRef >>> 24) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ mask = 0xFFFF0000;
+ break;
+ case TypeReference.FIELD:
+ case TypeReference.METHOD_RETURN:
+ case TypeReference.METHOD_RECEIVER:
+ case TypeReference.LOCAL_VARIABLE:
+ case TypeReference.RESOURCE_VARIABLE:
+ case TypeReference.INSTANCEOF:
+ case TypeReference.NEW:
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ case TypeReference.METHOD_REFERENCE:
+ mask = 0xFF000000;
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ case TypeReference.THROWS:
+ case TypeReference.EXCEPTION_PARAMETER:
+ mask = 0xFFFFFF00;
+ break;
+ case TypeReference.CAST:
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ mask = 0xFF0000FF;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(typeRef >>> 24));
+ }
+ if ((typeRef & ~mask) != 0) {
+ throw new IllegalArgumentException("Invalid type reference 0x"
+ + Integer.toHexString(typeRef));
+ }
+ if (typePath != null) {
+ for (int i = 0; i < typePath.getLength(); ++i) {
+ int step = typePath.getStep(i);
+ if (step != TypePath.ARRAY_ELEMENT
+ && step != TypePath.INNER_TYPE
+ && step != TypePath.TYPE_ARGUMENT
+ && step != TypePath.WILDCARD_BOUND) {
+ throw new IllegalArgumentException(
+ "Invalid type path step " + i + " in " + typePath);
+ }
+ if (step != TypePath.TYPE_ARGUMENT
+ && typePath.getStepArgument(i) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid type path step argument for step " + i
+ + " in " + typePath);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks the formal type parameters of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameters(final String signature, int pos) {
+ // FormalTypeParameters:
+ // < FormalTypeParameter+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkFormalTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkFormalTypeParameter(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a formal type parameter of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameter(final String signature, int pos) {
+ // FormalTypeParameter:
+ // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+ pos = checkIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkFieldTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkFieldTypeSignature(signature, pos + 1);
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a field type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFieldTypeSignature(final String signature, int pos) {
+ // FieldTypeSignature:
+ // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+ //
+ // ArrayTypeSignature:
+ // [ TypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, int pos) {
+ // ClassTypeSignature:
+ // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+ // TypeArguments? )* ;
+
+ pos = checkChar('L', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkIdentifier(signature, pos + 1);
+ }
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, int pos) {
+ // TypeArguments:
+ // < TypeArgument+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, int pos) {
+ // TypeArgument:
+ // * | ( ( + | - )? FieldTypeSignature )
+
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkFieldTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(final String signature,
+ int pos) {
+ // TypeVariableSignature:
+ // T Identifier ;
+
+ pos = checkChar('T', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks a type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeSignature(final String signature, int pos) {
+ // TypeSignature:
+ // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return pos + 1;
+ default:
+ return checkFieldTypeSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks an identifier.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkIdentifier(final String signature, int pos) {
+ if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+ throw new IllegalArgumentException(signature
+ + ": identifier expected at index " + pos);
+ }
+ ++pos;
+ while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+ ++pos;
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a single character.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, int pos) {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c
+ + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the signature car at the given index.
+ *
+ * @param signature
+ * a signature.
+ * @param pos
+ * an index in signature.
+ * @return the character at the given index, or 0 if there is no such
+ * character.
+ */
+ private static char getChar(final String signature, int pos) {
+ return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..753025b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,122 @@
+/***
+ * 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.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+ private boolean end;
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+ *
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckFieldAdapter(final FieldVisitor fv) {
+ this(Opcodes.ASM5, fv);
+ if (getClass() != CheckFieldAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ */
+ protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+ super(api, fv);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEnd();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkEnd();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.FIELD) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEnd();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ super.visitEnd();
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot call a visit method after visitEnd has been called");
+ }
+ }
+}
[02/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
new file mode 100644
index 0000000..6d5715c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
@@ -0,0 +1,1044 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Processor is a command line tool that can be used for bytecode waving
+ * directed by XSL transformation.
+ * <p>
+ * In order to use a concrete XSLT engine, system property
+ * <tt>javax.xml.transform.TransformerFactory</tt> must be set to one of the
+ * following values.
+ *
+ * <blockquote>
+ * <table border="1" cellspacing="0" cellpadding="3">
+ * <tr>
+ * <td>jd.xslt</td>
+ * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Saxon</td>
+ * <td>net.sf.saxon.TransformerFactoryImpl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Caucho</td>
+ * <td>com.caucho.xsl.Xsl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Xalan interpeter</td>
+ * <td>org.apache.xalan.processor.TransformerFactory</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Xalan xsltc</td>
+ * <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * @author Eugene Kuleshov
+ */
+public class Processor {
+
+ public static final int BYTECODE = 1;
+
+ public static final int MULTI_XML = 2;
+
+ public static final int SINGLE_XML = 3;
+
+ private static final String SINGLE_XML_NAME = "classes.xml";
+
+ private final int inRepresentation;
+
+ private final int outRepresentation;
+
+ private final InputStream input;
+
+ private final OutputStream output;
+
+ private final Source xslt;
+
+ private int n = 0;
+
+ public Processor(final int inRepresenation, final int outRepresentation,
+ final InputStream input, final OutputStream output,
+ final Source xslt) {
+ this.inRepresentation = inRepresenation;
+ this.outRepresentation = outRepresentation;
+ this.input = input;
+ this.output = output;
+ this.xslt = xslt;
+ }
+
+ public int process() throws TransformerException, IOException, SAXException {
+ ZipInputStream zis = new ZipInputStream(input);
+ final ZipOutputStream zos = new ZipOutputStream(output);
+ final OutputStreamWriter osw = new OutputStreamWriter(zos);
+
+ Thread.currentThread().setContextClassLoader(
+ getClass().getClassLoader());
+
+ TransformerFactory tf = TransformerFactory.newInstance();
+ if (!tf.getFeature(SAXSource.FEATURE)
+ || !tf.getFeature(SAXResult.FEATURE)) {
+ return 0;
+ }
+
+ SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
+ Templates templates = null;
+ if (xslt != null) {
+ templates = saxtf.newTemplates(xslt);
+ }
+
+ // configuring outHandlerFactory
+ // ///////////////////////////////////////////////////////
+
+ EntryElement entryElement = getEntryElement(zos);
+
+ ContentHandler outDocHandler = null;
+ switch (outRepresentation) {
+ case BYTECODE:
+ outDocHandler = new OutputSlicingHandler(
+ new ASMContentHandlerFactory(zos), entryElement, false);
+ break;
+
+ case MULTI_XML:
+ outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
+ true), entryElement, true);
+ break;
+
+ case SINGLE_XML:
+ ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
+ zos.putNextEntry(outputEntry);
+ outDocHandler = new SAXWriter(osw, false);
+ break;
+
+ }
+
+ // configuring inputDocHandlerFactory
+ // /////////////////////////////////////////////////
+ ContentHandler inDocHandler;
+ if (templates == null) {
+ inDocHandler = outDocHandler;
+ } else {
+ inDocHandler = new InputSlicingHandler("class", outDocHandler,
+ new TransformerHandlerFactory(saxtf, templates,
+ outDocHandler));
+ }
+ ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
+ inDocHandler);
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.startDocument();
+ inDocHandler.startElement("", "classes", "classes",
+ new AttributesImpl());
+ }
+
+ int i = 0;
+ ZipEntry ze;
+ while ((ze = zis.getNextEntry()) != null) {
+ update(ze.getName(), n++);
+ if (isClassEntry(ze)) {
+ processEntry(zis, ze, inDocHandlerFactory);
+ } else {
+ OutputStream os = entryElement.openEntry(getName(ze));
+ copyEntry(zis, os);
+ entryElement.closeEntry();
+ }
+
+ i++;
+ }
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.endElement("", "classes", "classes");
+ inDocHandler.endDocument();
+ }
+
+ if (outRepresentation == SINGLE_XML) {
+ zos.closeEntry();
+ }
+ zos.flush();
+ zos.close();
+
+ return i;
+ }
+
+ private void copyEntry(final InputStream is, final OutputStream os)
+ throws IOException {
+ if (outRepresentation == SINGLE_XML) {
+ return;
+ }
+
+ byte[] buff = new byte[2048];
+ int i;
+ while ((i = is.read(buff)) != -1) {
+ os.write(buff, 0, i);
+ }
+ }
+
+ private boolean isClassEntry(final ZipEntry ze) {
+ String name = ze.getName();
+ return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
+ || name.endsWith(".class") || name.endsWith(".class.xml");
+ }
+
+ private void processEntry(final ZipInputStream zis, final ZipEntry ze,
+ final ContentHandlerFactory handlerFactory) {
+ ContentHandler handler = handlerFactory.createContentHandler();
+ try {
+
+ // if (CODE2ASM.equals(command)) { // read bytecode and process it
+ // // with TraceClassVisitor
+ // ClassReader cr = new ClassReader(readEntry(zis, ze));
+ // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
+ // false);
+ // }
+
+ boolean singleInputDocument = inRepresentation == SINGLE_XML;
+ if (inRepresentation == BYTECODE) { // read bytecode and process it
+ // with handler
+ ClassReader cr = new ClassReader(readEntry(zis, ze));
+ cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
+
+ } else { // read XML and process it with handler
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(
+ singleInputDocument ? (InputStream) new ProtectedInputStream(
+ zis) : new ByteArrayInputStream(readEntry(zis,
+ ze))));
+
+ }
+ } catch (Exception ex) {
+ update(ze.getName(), 0);
+ update(ex, 0);
+ }
+ }
+
+ private EntryElement getEntryElement(final ZipOutputStream zos) {
+ if (outRepresentation == SINGLE_XML) {
+ return new SingleDocElement(zos);
+ }
+ return new ZipEntryElement(zos);
+ }
+
+ // private ContentHandlerFactory getHandlerFactory(
+ // OutputStream os,
+ // SAXTransformerFactory saxtf,
+ // Templates templates)
+ // {
+ // ContentHandlerFactory factory = null;
+ // if (templates == null) {
+ // if (outputRepresentation == BYTECODE) { // factory used to write
+ // // bytecode
+ // factory = new ASMContentHandlerFactory(os, computeMax);
+ // } else { // factory used to write XML
+ // factory = new SAXWriterFactory(os, true);
+ // }
+ // } else {
+ // if (outputRepresentation == BYTECODE) { // factory used to transform
+ // // and then write bytecode
+ // factory = new ASMTransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // computeMax);
+ // } else { // factory used to transformand then write XML
+ // factory = new TransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // outputRepresentation == SINGLE_XML);
+ // }
+ // }
+ // return factory;
+ // }
+
+ private String getName(final ZipEntry ze) {
+ String name = ze.getName();
+ if (isClassEntry(ze)) {
+ if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
+ name = name.substring(0, name.length() - 4); // .class.xml to
+ // .class
+ } else if (inRepresentation == BYTECODE
+ && outRepresentation != BYTECODE) {
+ name += ".xml"; // .class to .class.xml
+ }
+ // } else if( CODE2ASM.equals( command)) {
+ // name = name.substring( 0, name.length()-6).concat( ".asm");
+ }
+ return name;
+ }
+
+ private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
+ throws IOException {
+ long size = ze.getSize();
+ if (size > -1) {
+ byte[] buff = new byte[(int) size];
+ int k = 0;
+ int n;
+ while ((n = zis.read(buff, k, buff.length - k)) > 0) {
+ k += n;
+ }
+ return buff;
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buff = new byte[4096];
+ int i;
+ while ((i = zis.read(buff)) != -1) {
+ bos.write(buff, 0, i);
+ }
+ return bos.toByteArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+ */
+ protected void update(final Object arg, final int n) {
+ if (arg instanceof Throwable) {
+ ((Throwable) arg).printStackTrace();
+ } else {
+ if (n % 100 == 0) {
+ System.err.println(n + " " + arg);
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ if (args.length < 2) {
+ showUsage();
+ return;
+ }
+
+ int inRepresentation = getRepresentation(args[0]);
+ int outRepresentation = getRepresentation(args[1]);
+
+ InputStream is = System.in;
+ OutputStream os = new BufferedOutputStream(System.out);
+
+ Source xslt = null;
+ // boolean computeMax = true;
+
+ for (int i = 2; i < args.length; i++) {
+ if ("-in".equals(args[i])) {
+ is = new FileInputStream(args[++i]);
+
+ } else if ("-out".equals(args[i])) {
+ os = new BufferedOutputStream(new FileOutputStream(args[++i]));
+
+ } else if ("-xslt".equals(args[i])) {
+ xslt = new StreamSource(new FileInputStream(args[++i]));
+
+ // } else if( "-computemax".equals( args[ i].toLowerCase())) {
+ // computeMax = true;
+
+ } else {
+ showUsage();
+ return;
+
+ }
+ }
+
+ if (inRepresentation == 0 || outRepresentation == 0) {
+ showUsage();
+ return;
+ }
+
+ Processor m = new Processor(inRepresentation, outRepresentation, is,
+ os, xslt);
+
+ long l1 = System.currentTimeMillis();
+ int n = m.process();
+ long l2 = System.currentTimeMillis();
+ System.err.println(n);
+ System.err.println((l2 - l1) + "ms " + 1000f * n / (l2 - l1)
+ + " resources/sec");
+ }
+
+ private static int getRepresentation(final String s) {
+ if ("code".equals(s)) {
+ return BYTECODE;
+ } else if ("xml".equals(s)) {
+ return MULTI_XML;
+ } else if ("singlexml".equals(s)) {
+ return SINGLE_XML;
+ }
+ return 0;
+ }
+
+ private static void showUsage() {
+ System.err
+ .println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt fiel>]");
+ System.err
+ .println(" when -in or -out is omitted sysin and sysout would be used");
+ System.err
+ .println(" <in format> and <out format> - code | xml | singlexml");
+ }
+
+ /**
+ * IputStream wrapper class used to protect input streams from being closed
+ * by some stupid XML parsers.
+ */
+ private static final class ProtectedInputStream extends InputStream {
+ private final InputStream is;
+
+ ProtectedInputStream(final InputStream is) {
+ this.is = is;
+ }
+
+ @Override
+ public final void close() throws IOException {
+ }
+
+ @Override
+ public final int read() throws IOException {
+ return is.read();
+ }
+
+ @Override
+ public final int read(final byte[] b, final int off, final int len)
+ throws IOException {
+ return is.read(b, off, len);
+ }
+
+ @Override
+ public final int available() throws IOException {
+ return is.available();
+ }
+ }
+
+ /**
+ * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
+ * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
+ * context.
+ */
+ private static interface ContentHandlerFactory {
+
+ /**
+ * Creates an instance of the content handler.
+ *
+ * @return content handler
+ */
+ ContentHandler createContentHandler();
+
+ }
+
+ /**
+ * SAXWriterFactory
+ */
+ private static final class SAXWriterFactory implements
+ ContentHandlerFactory {
+ private final Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return new SAXWriter(w, optimizeEmptyElements);
+ }
+
+ }
+
+ /**
+ * ASMContentHandlerFactory
+ */
+ private static final class ASMContentHandlerFactory implements
+ ContentHandlerFactory {
+ final OutputStream os;
+
+ ASMContentHandlerFactory(final OutputStream os) {
+ this.os = os;
+ }
+
+ public final ContentHandler createContentHandler() {
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ return new ASMContentHandler(cw) {
+ @Override
+ public void endDocument() throws SAXException {
+ try {
+ os.write(cw.toByteArray());
+ } catch (IOException e) {
+ throw new SAXException(e);
+ }
+ }
+ };
+ }
+
+ }
+
+ /**
+ * TransformerHandlerFactory
+ */
+ private static final class TransformerHandlerFactory implements
+ ContentHandlerFactory {
+ private SAXTransformerFactory saxtf;
+
+ private final Templates templates;
+
+ private ContentHandler outputHandler;
+
+ TransformerHandlerFactory(final SAXTransformerFactory saxtf,
+ final Templates templates, final ContentHandler outputHandler) {
+ this.saxtf = saxtf;
+ this.templates = templates;
+ this.outputHandler = outputHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ try {
+ TransformerHandler handler = saxtf
+ .newTransformerHandler(templates);
+ handler.setResult(new SAXResult(outputHandler));
+ return handler;
+ } catch (TransformerConfigurationException ex) {
+ throw new RuntimeException(ex.toString());
+ }
+ }
+ }
+
+ /**
+ * SubdocumentHandlerFactory
+ */
+ private static final class SubdocumentHandlerFactory implements
+ ContentHandlerFactory {
+ private final ContentHandler subdocumentHandler;
+
+ SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
+ this.subdocumentHandler = subdocumentHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return subdocumentHandler;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} and
+ * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
+ * from SAX 2.0 events into {@link java.io.Writer Writer}.
+ *
+ * <i><blockquote> This implementation does not support namespaces, entity
+ * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
+ */
+ private static final class SAXWriter extends DefaultHandler implements
+ LexicalHandler {
+ private static final char[] OFF = " "
+ .toCharArray();
+
+ private Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ private boolean openElement = false;
+
+ private int ident = 0;
+
+ /**
+ * Creates <code>SAXWriter</code>.
+ *
+ * @param w
+ * writer
+ * @param optimizeEmptyElements
+ * if set to <code>true</code>, short XML syntax will be used
+ * for empty elements
+ */
+ SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ @Override
+ public final void startElement(final String ns, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write('<' + qName);
+ if (atts != null && atts.getLength() > 0) {
+ writeAttributes(atts);
+ }
+
+ if (optimizeEmptyElements) {
+ openElement = true;
+ } else {
+ w.write(">\n");
+ }
+ ident += 2;
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endElement(final String ns, final String localName,
+ final String qName) throws SAXException {
+ ident -= 2;
+ try {
+ if (openElement) {
+ w.write("/>\n");
+ openElement = false;
+ } else {
+ writeIdent();
+ w.write("</" + qName + ">\n");
+ }
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ try {
+ w.flush();
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void comment(final char[] ch, final int off, final int len)
+ throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write("<!-- ");
+ w.write(ch, off, len);
+ w.write(" -->\n");
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void startDTD(final String arg0, final String arg1,
+ final String arg2) throws SAXException {
+ }
+
+ public final void endDTD() throws SAXException {
+ }
+
+ public final void startEntity(final String arg0) throws SAXException {
+ }
+
+ public final void endEntity(final String arg0) throws SAXException {
+ }
+
+ public final void startCDATA() throws SAXException {
+ }
+
+ public final void endCDATA() throws SAXException {
+ }
+
+ private final void writeAttributes(final Attributes atts)
+ throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int len = atts.getLength();
+ for (int i = 0; i < len; i++) {
+ sb.append(' ').append(atts.getLocalName(i)).append("=\"")
+ .append(esc(atts.getValue(i))).append('\"');
+ }
+ w.write(sb.toString());
+ }
+
+ /**
+ * Encode string with escaping.
+ *
+ * @param str
+ * string to encode.
+ * @return encoded string
+ */
+ private static final String esc(final String str) {
+ StringBuffer sb = new StringBuffer(str.length());
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '&':
+ sb.append("&");
+ break;
+
+ case '<':
+ sb.append("<");
+ break;
+
+ case '>':
+ sb.append(">");
+ break;
+
+ case '\"':
+ sb.append(""");
+ break;
+
+ default:
+ if (ch > 0x7f) {
+ sb.append("&#").append(Integer.toString(ch))
+ .append(';');
+ } else {
+ sb.append(ch);
+ }
+
+ }
+ }
+ return sb.toString();
+ }
+
+ private final void writeIdent() throws IOException {
+ int n = ident;
+ while (n > 0) {
+ if (n > OFF.length) {
+ w.write(OFF);
+ n -= OFF.length;
+ } else {
+ w.write(OFF, 0, n);
+ n = 0;
+ }
+ }
+ }
+
+ private final void closeElement() throws IOException {
+ if (openElement) {
+ w.write(">\n");
+ }
+ openElement = false;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ * <p>
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class InputSlicingHandler extends DefaultHandler {
+ private String subdocumentRoot;
+
+ private final ContentHandler rootHandler;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentRoot
+ * name/path to the root element of the subdocument
+ * @param rootHandler
+ * content handler for the entire document (subdocument
+ * envelope).
+ * @param subdocumentHandlerFactory
+ * a {@link ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link ContentHandler ContentHandler} instances
+ * for subdocuments.
+ */
+ InputSlicingHandler(final String subdocumentRoot,
+ final ContentHandler rootHandler,
+ final ContentHandlerFactory subdocumentHandlerFactory) {
+ this.subdocumentRoot = subdocumentRoot;
+ this.rootHandler = rootHandler;
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ } else if (rootHandler != null) {
+ rootHandler.startElement(namespaceURI, localName, qName, list);
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ }
+ } else if (rootHandler != null) {
+ rootHandler.endElement(namespaceURI, localName, qName);
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.startDocument();
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.endDocument();
+
+ }
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ } else if (rootHandler != null) {
+ rootHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ *
+ * <p>
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class OutputSlicingHandler extends DefaultHandler {
+ private final String subdocumentRoot;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private final EntryElement entryElement;
+
+ private boolean isXml;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentHandlerFactory
+ * a {@link ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link ContentHandler ContentHandler} instances
+ * for subdocuments.
+ * @param entryElement
+ * TODO.
+ * @param isXml
+ * TODO.
+ */
+ OutputSlicingHandler(
+ final ContentHandlerFactory subdocumentHandlerFactory,
+ final EntryElement entryElement, final boolean isXml) {
+ this.subdocumentRoot = "class";
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ this.entryElement = entryElement;
+ this.isXml = isXml;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ String name = list.getValue("name");
+ if (name == null || name.length() == 0) {
+ throw new SAXException(
+ "Class element without name attribute.");
+ }
+ try {
+ entryElement.openEntry(isXml ? name + ".class.xml" : name
+ + ".class");
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ try {
+ entryElement.closeEntry();
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ }
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ private static interface EntryElement {
+
+ OutputStream openEntry(String name) throws IOException;
+
+ void closeEntry() throws IOException;
+
+ }
+
+ private static final class SingleDocElement implements EntryElement {
+ private final OutputStream os;
+
+ SingleDocElement(final OutputStream os) {
+ this.os = os;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ return os;
+ }
+
+ public void closeEntry() throws IOException {
+ os.flush();
+ }
+
+ }
+
+ private static final class ZipEntryElement implements EntryElement {
+ private ZipOutputStream zos;
+
+ ZipEntryElement(final ZipOutputStream zos) {
+ this.zos = zos;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ ZipEntry entry = new ZipEntry(name);
+ zos.putNextEntry(entry);
+ return zos;
+ }
+
+ public void closeEntry() throws IOException {
+ zos.flush();
+ zos.closeEntry();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
new file mode 100644
index 0000000..2f49c24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
@@ -0,0 +1,89 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * SAXAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public class SAXAdapter {
+
+ private final ContentHandler h;
+
+ protected SAXAdapter(final ContentHandler h) {
+ this.h = h;
+ }
+
+ protected ContentHandler getContentHandler() {
+ return h;
+ }
+
+ protected void addDocumentStart() {
+ try {
+ h.startDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected void addDocumentEnd() {
+ try {
+ h.endDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addStart(final String name, final Attributes attrs) {
+ try {
+ h.startElement("", name, name, attrs);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addEnd(final String name) {
+ try {
+ h.endElement("", name, name);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addElement(final String name, final Attributes attrs) {
+ addStart(name, attrs);
+ addEnd(name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
new file mode 100644
index 0000000..491c57e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
@@ -0,0 +1,242 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * SAXAnnotationAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXAnnotationAdapter extends AnnotationVisitor {
+
+ SAXAdapter sa;
+
+ private final String elementName;
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, -1, null,
+ null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final int parameter, final String desc) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, null, parameter, -1,
+ null, null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc,
+ final int typeRef, final TypePath typePath) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+ typePath, null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc,
+ int typeRef, TypePath typePath, final String[] start,
+ final String[] end, final int[] index) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+ typePath, start, end, index);
+ }
+
+ protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+ final String elementName, final int visible, final String desc,
+ final String name, final int parameter) {
+ this(api, sa, elementName, visible, desc, name, parameter, -1, null,
+ null, null, null);
+ }
+
+ protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+ final String elementName, final int visible, final String desc,
+ final String name, final int parameter, final int typeRef,
+ final TypePath typePath, final String[] start, final String[] end,
+ final int[] index) {
+ super(api);
+ this.sa = sa;
+ this.elementName = elementName;
+
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (visible != 0) {
+ att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
+ : "false");
+ }
+ if (parameter != -1) {
+ att.addAttribute("", "parameter", "parameter", "",
+ Integer.toString(parameter));
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+ if (typeRef != -1) {
+ att.addAttribute("", "typeRef", "typeRef", "",
+ Integer.toString(typeRef));
+ }
+ if (typePath != null) {
+ att.addAttribute("", "typePath", "typePath", "",
+ typePath.toString());
+ }
+ if (start != null) {
+ StringBuffer value = new StringBuffer(start[0]);
+ for (int i = 1; i < start.length; ++i) {
+ value.append(" ").append(start[i]);
+ }
+ att.addAttribute("", "start", "start", "", value.toString());
+ }
+ if (end != null) {
+ StringBuffer value = new StringBuffer(end[0]);
+ for (int i = 1; i < end.length; ++i) {
+ value.append(" ").append(end[i]);
+ }
+ att.addAttribute("", "end", "end", "", value.toString());
+ }
+ if (index != null) {
+ StringBuffer value = new StringBuffer();
+ value.append(index[0]);
+ for (int i = 1; i < index.length; ++i) {
+ value.append(" ").append(index[i]);
+ }
+ att.addAttribute("", "index", "index", "", value.toString());
+ }
+
+ sa.addStart(elementName, att);
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ Class<?> c = value.getClass();
+ if (c.isArray()) {
+ AnnotationVisitor av = visitArray(name);
+ if (value instanceof byte[]) {
+ byte[] b = (byte[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Byte(b[i]));
+ }
+
+ } else if (value instanceof char[]) {
+ char[] b = (char[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Character(b[i]));
+ }
+
+ } else if (value instanceof short[]) {
+ short[] b = (short[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Short(b[i]));
+ }
+
+ } else if (value instanceof boolean[]) {
+ boolean[] b = (boolean[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, Boolean.valueOf(b[i]));
+ }
+
+ } else if (value instanceof int[]) {
+ int[] b = (int[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Integer(b[i]));
+ }
+
+ } else if (value instanceof long[]) {
+ long[] b = (long[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Long(b[i]));
+ }
+
+ } else if (value instanceof float[]) {
+ float[] b = (float[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Float(b[i]));
+ }
+
+ } else if (value instanceof double[]) {
+ double[] b = (double[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Double(b[i]));
+ }
+
+ }
+ av.visitEnd();
+ } else {
+ addValueElement("annotationValue", name, Type.getDescriptor(c),
+ value.toString());
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ addValueElement("annotationValueEnum", name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
+ name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
+ null);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd(elementName);
+ }
+
+ private void addValueElement(final String element, final String name,
+ final String desc, final String value) {
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "",
+ SAXClassAdapter.encode(value));
+ }
+
+ sa.addElement(element, att);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
new file mode 100644
index 0000000..dc4cb66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
@@ -0,0 +1,335 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
+ * events from the visited class. It can feed any kind of
+ * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
+ * or XQuery engines.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.ASMContentHandler
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXClassAdapter extends ClassVisitor {
+
+ SAXAdapter sa;
+
+ private final boolean singleDocument;
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
+ *
+ * @param h
+ * content handler that will be used to send SAX 2.0 events.
+ * @param singleDocument
+ * if <tt>true</tt> adapter will not produce
+ * {@link ContentHandler#startDocument() startDocument()} and
+ * {@link ContentHandler#endDocument() endDocument()} events.
+ */
+ public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
+ super(Opcodes.ASM5);
+ this.sa = new SAXAdapter(h);
+ this.singleDocument = singleDocument;
+ if (!singleDocument) {
+ sa.addDocumentStart();
+ }
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ AttributesImpl att = new AttributesImpl();
+ if (source != null) {
+ att.addAttribute("", "file", "file", "", encode(source));
+ }
+ if (debug != null) {
+ att.addAttribute("", "debug", "debug", "", encode(debug));
+ }
+
+ sa.addElement("source", att);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "owner", "owner", "", owner);
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+
+ sa.addElement("outerclass", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_CLASS, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (superName != null) {
+ att.addAttribute("", "parent", "parent", "", superName);
+ }
+ att.addAttribute("", "major", "major", "",
+ Integer.toString(version & 0xFFFF));
+ att.addAttribute("", "minor", "minor", "",
+ Integer.toString(version >>> 16));
+ sa.addStart("class", att);
+
+ sa.addStart("interfaces", new AttributesImpl());
+ if (interfaces != null && interfaces.length > 0) {
+ for (int i = 0; i < interfaces.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", interfaces[i]);
+ sa.addElement("interface", att2);
+ }
+ }
+ sa.addEnd("interfaces");
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_FIELD, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "", encode(value.toString()));
+ }
+
+ return new SAXFieldAdapter(sa, att);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "", signature);
+ }
+ sa.addStart("method", att);
+
+ sa.addStart("exceptions", new AttributesImpl());
+ if (exceptions != null && exceptions.length > 0) {
+ for (int i = 0; i < exceptions.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", exceptions[i]);
+ sa.addElement("exception", att2);
+ }
+ }
+ sa.addEnd("exceptions");
+
+ return new SAXCodeAdapter(sa, access);
+ }
+
+ @Override
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_INNER, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (outerName != null) {
+ att.addAttribute("", "outerName", "outerName", "", outerName);
+ }
+ if (innerName != null) {
+ att.addAttribute("", "innerName", "innerName", "", innerName);
+ }
+ sa.addElement("innerclass", att);
+ }
+
+ @Override
+ public final void visitEnd() {
+ sa.addEnd("class");
+ if (!singleDocument) {
+ sa.addDocumentEnd();
+ }
+ }
+
+ static final String encode(final String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ sb.append("\\\\");
+ } else if (c < 0x20 || c > 0x7f) {
+ sb.append("\\u");
+ if (c < 0x10) {
+ sb.append("000");
+ } else if (c < 0x100) {
+ sb.append("00");
+ } else if (c < 0x1000) {
+ sb.append('0');
+ }
+ sb.append(Integer.toString(c, 16));
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static void appendAccess(final int access, final StringBuffer sb) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ sb.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ sb.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ sb.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ sb.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ sb.append("static ");
+ }
+ if ((access & Opcodes.ACC_SUPER) != 0) {
+ if ((access & ACCESS_CLASS) == 0) {
+ sb.append("synchronized ");
+ } else {
+ sb.append("super ");
+ }
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("bridge ");
+ } else {
+ sb.append("volatile ");
+ }
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("varargs ");
+ } else {
+ sb.append("transient ");
+ }
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ sb.append("native ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ sb.append("strict ");
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ sb.append("interface ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ sb.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ sb.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ sb.append("annotation ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ sb.append("enum ");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append("deprecated ");
+ }
+ if ((access & Opcodes.ACC_MANDATED) != 0) {
+ sb.append("mandated ");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
new file mode 100644
index 0000000..3ed0a49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
@@ -0,0 +1,415 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.util.Printer;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
+ * method.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXCodeAdapter extends MethodVisitor {
+
+ static final String[] TYPES = { "top", "int", "float", "double", "long",
+ "null", "uninitializedThis" };
+
+ SAXAdapter sa;
+
+ int access;
+
+ private final Map<Label, String> labelNames;
+
+ /**
+ * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
+ *
+ * @param sa
+ * content handler that will be used to send SAX 2.0 events.
+ */
+ public SAXCodeAdapter(final SAXAdapter sa, final int access) {
+ super(Opcodes.ASM5);
+ this.sa = sa;
+ this.access = access;
+ this.labelNames = new HashMap<Label, String>();
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ AttributesImpl attrs = new AttributesImpl();
+ if (name != null) {
+ attrs.addAttribute("", "name", "name", "", name);
+ }
+ StringBuffer sb = new StringBuffer();
+ SAXClassAdapter.appendAccess(access, sb);
+ attrs.addAttribute("", "access", "access", "", sb.toString());
+ sa.addElement("parameter", attrs);
+ }
+
+ @Override
+ public final void visitCode() {
+ if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
+ sa.addStart("code", new AttributesImpl());
+ }
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ AttributesImpl attrs = new AttributesImpl();
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ if (type == Opcodes.F_NEW) {
+ attrs.addAttribute("", "type", "type", "", "NEW");
+ } else {
+ attrs.addAttribute("", "type", "type", "", "FULL");
+ }
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ appendFrameTypes(false, nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ attrs.addAttribute("", "type", "type", "", "APPEND");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ attrs.addAttribute("", "type", "type", "", "CHOP");
+ attrs.addAttribute("", "count", "count", "",
+ Integer.toString(nLocal));
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME:
+ attrs.addAttribute("", "type", "type", "", "SAME");
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME1:
+ attrs.addAttribute("", "type", "type", "", "SAME1");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(false, 1, stack);
+ break;
+ }
+ sa.addEnd("frame");
+ }
+
+ private void appendFrameTypes(final boolean local, final int n,
+ final Object[] types) {
+ for (int i = 0; i < n; ++i) {
+ Object type = types[i];
+ AttributesImpl attrs = new AttributesImpl();
+ if (type instanceof String) {
+ attrs.addAttribute("", "type", "type", "", (String) type);
+ } else if (type instanceof Integer) {
+ attrs.addAttribute("", "type", "type", "",
+ TYPES[((Integer) type).intValue()]);
+ } else {
+ attrs.addAttribute("", "type", "type", "", "uninitialized");
+ attrs.addAttribute("", "label", "label", "",
+ getLabel((Label) type));
+ }
+ sa.addElement(local ? "local" : "stack", attrs);
+ }
+ }
+
+ @Override
+ public final void visitInsn(final int opcode) {
+ sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
+ }
+
+ @Override
+ public final void visitIntInsn(final int opcode, final int operand) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitVarInsn(final int opcode, final int var) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitTypeInsn(final int opcode, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", type);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "itf", "itf", "", itf ? "true" : "false");
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "bsm", "bsm", "",
+ SAXClassAdapter.encode(bsm.toString()));
+ sa.addStart("INVOKEDYNAMIC", attrs);
+ for (int i = 0; i < bsmArgs.length; i++) {
+ sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
+ }
+ sa.addEnd("INVOKEDYNAMIC");
+ }
+
+ @Override
+ public final void visitJumpInsn(final int opcode, final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "label", "label", "", getLabel(label));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitLabel(final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", getLabel(label));
+ sa.addElement("Label", attrs);
+ }
+
+ @Override
+ public final void visitLdcInsn(final Object cst) {
+ sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
+ }
+
+ private static AttributesImpl getConstantAttribute(final Object cst) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "cst", "cst", "",
+ SAXClassAdapter.encode(cst.toString()));
+ attrs.addAttribute("", "desc", "desc", "",
+ Type.getDescriptor(cst.getClass()));
+ return attrs;
+ }
+
+ @Override
+ public final void visitIincInsn(final int var, final int increment) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
+ sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
+ }
+
+ @Override
+ public final void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "min", "min", "", Integer.toString(min));
+ attrs.addAttribute("", "max", "max", "", Integer.toString(max));
+ attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.TABLESWITCH];
+ sa.addStart(o, attrs);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
+ sa.addStart(o, att);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitMultiANewArrayInsn(final String desc, final int dims) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
+ sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
+ }
+
+ @Override
+ public final void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
+ if (type != null) {
+ attrs.addAttribute("", "type", "type", "", type);
+ }
+ sa.addElement("TryCatch", attrs);
+ }
+
+ @Override
+ public final void visitMaxs(final int maxStack, final int maxLocals) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "maxStack", "maxStack", "",
+ Integer.toString(maxStack));
+ attrs.addAttribute("", "maxLocals", "maxLocals", "",
+ Integer.toString(maxLocals));
+ sa.addElement("Max", attrs);
+
+ sa.addEnd("code");
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ attrs.addAttribute("", "signature", "signature", "",
+ SAXClassAdapter.encode(signature));
+ }
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "var", "var", "", Integer.toString(index));
+ sa.addElement("LocalVar", attrs);
+ }
+
+ @Override
+ public final void visitLineNumber(final int line, final Label start) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "line", "line", "", Integer.toString(line));
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ sa.addElement("LineNumber", attrs);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
+ : -1, parameter, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "insnAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "tryCatchAnnotation", visible ? 1
+ : -1, null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ String[] s = new String[start.length];
+ String[] e = new String[end.length];
+ for (int i = 0; i < s.length; ++i) {
+ s[i] = getLabel(start[i]);
+ }
+ for (int i = 0; i < e.length; ++i) {
+ e[i] = getLabel(end[i]);
+ }
+ return new SAXAnnotationAdapter(sa, "localVariableAnnotation",
+ visible ? 1 : -1, null, desc, typeRef, typePath, s, e, index);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("method");
+ }
+
+ private final String getLabel(final Label label) {
+ String name = labelNames.get(label);
+ if (name == null) {
+ name = Integer.toString(labelNames.size());
+ labelNames.put(label, name);
+ }
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
new file mode 100644
index 0000000..4fbc2a5
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+
+/**
+ * SAXFieldAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXFieldAdapter extends FieldVisitor {
+
+ SAXAdapter sa;
+
+ public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
+ super(Opcodes.ASM5);
+ this.sa = sa;
+ sa.addStart("field", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("field");
+ }
+}
[04/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
index c74a17f..a849298 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
@@ -29,18 +29,19 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.Attribute;
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 java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* An abstract converter from visit events to text.
- *
+ *
* @author Eric Bruneton
*/
public abstract class Printer {
@@ -103,8 +104,8 @@ public abstract class Printer {
}
s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
- + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
- + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+ + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+ + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
HANDLE_TAG = new String[10];
j = 0;
i = 1;
@@ -116,7 +117,7 @@ public abstract class Printer {
/**
* The ASM API version implemented by this class. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -149,81 +150,67 @@ public abstract class Printer {
}
/**
- * Class header.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
+ * Class header. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
*/
- public abstract void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces);
+ public abstract void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces);
/**
- * Class source.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
+ * Class source. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
*/
public abstract void visitSource(final String file, final String debug);
/**
- * Class outer class.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
+ * Class outer class. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
*/
- public abstract void visitOuterClass(
- final String owner,
- final String name,
- final String desc);
+ public abstract void visitOuterClass(final String owner, final String name,
+ final String desc);
/**
- * Class annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
+ * Class annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
*/
- public abstract Printer visitClassAnnotation(
- final String desc,
- final boolean visible);
+ public abstract Printer visitClassAnnotation(final String desc,
+ final boolean visible);
/**
- * Class attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
+ * Class type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitTypeAnnotation}.
+ */
+ public Printer visitClassTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Class attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
*/
public abstract void visitClassAttribute(final Attribute attr);
/**
- * Class inner name.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
+ * Class inner name. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
*/
- public abstract void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access);
+ public abstract void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access);
/**
- * Class field.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
+ * Class field. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
*/
- public abstract Printer visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value);
+ public abstract Printer visitField(final int access, final String name,
+ final String desc, final String signature, final Object value);
/**
- * Class method.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
+ * Class method. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
*/
- public abstract Printer visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions);
+ public abstract Printer visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions);
/**
- * Class end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
+ * Class end. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
*/
public abstract void visitClassEnd();
@@ -232,37 +219,31 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Annotation value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
+ * Annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
*/
public abstract void visit(final String name, final Object value);
/**
- * Annotation enum value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
+ * Annotation enum value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
*/
- public abstract void visitEnum(
- final String name,
- final String desc,
- final String value);
+ public abstract void visitEnum(final String name, final String desc,
+ final String value);
/**
- * Nested annotation value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
+ * Nested annotation value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
*/
- public abstract Printer visitAnnotation(
- final String name,
- final String desc);
+ public abstract Printer visitAnnotation(final String name, final String desc);
/**
- * Annotation array value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
+ * Annotation array value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
*/
public abstract Printer visitArray(final String name);
/**
- * Annotation end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
+ * Annotation end. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
*/
public abstract void visitAnnotationEnd();
@@ -271,22 +252,29 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Field annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+ * Field annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitFieldAnnotation(final String desc,
+ final boolean visible);
+
+ /**
+ * Field type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitTypeAnnotation}.
*/
- public abstract Printer visitFieldAnnotation(
- final String desc,
- final boolean visible);
+ public Printer visitFieldTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Field attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
+ * Field attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
*/
public abstract void visitFieldAttribute(final Attribute attr);
/**
- * Field end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
+ * Field end. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
*/
public abstract void visitFieldEnd();
@@ -295,199 +283,237 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Method default annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
+ * Method parameter. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameter(String, int)}.
+ */
+ public void visitParameter(String name, int access) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Method default annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
*/
public abstract Printer visitAnnotationDefault();
/**
- * Method annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
+ * Method annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
*/
- public abstract Printer visitMethodAnnotation(
- final String desc,
- final boolean visible);
+ public abstract Printer visitMethodAnnotation(final String desc,
+ final boolean visible);
/**
- * Method parameter annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+ * Method type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeAnnotation}.
*/
- public abstract Printer visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible);
+ public Printer visitMethodTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
+ * Method parameter annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+ */
+ public abstract Printer visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible);
+
+ /**
+ * Method attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
*/
public abstract void visitMethodAttribute(final Attribute attr);
/**
- * Method start.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
+ * Method start. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
*/
public abstract void visitCode();
/**
- * Method stack frame.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ * Method stack frame. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
*/
- public abstract void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack);
+ public abstract void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}.
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}
+ * .
*/
public abstract void visitInsn(final int opcode);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
*/
public abstract void visitIntInsn(final int opcode, final int operand);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
*/
public abstract void visitVarInsn(final int opcode, final int var);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
*/
public abstract void visitTypeInsn(final int opcode, final String type);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
*/
- public abstract void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc);
+ public abstract void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
*/
- public abstract void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc);
+ @Deprecated
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
*/
- public abstract void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs);
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ */
+ public abstract void visitInvokeDynamicInsn(String name, String desc,
+ Handle bsm, Object... bsmArgs);
+
+ /**
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
*/
public abstract void visitJumpInsn(final int opcode, final Label label);
/**
- * Method label.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
+ * Method label. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
*/
public abstract void visitLabel(final Label label);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
*/
public abstract void visitLdcInsn(final Object cst);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
*/
public abstract void visitIincInsn(final int var, final int increment);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+ */
+ public abstract void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels);
+
+ /**
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
*/
- public abstract void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels);
+ public abstract void visitLookupSwitchInsn(final Label dflt,
+ final int[] keys, final Label[] labels);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
*/
- public abstract void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels);
+ public abstract void visitMultiANewArrayInsn(final String desc,
+ final int dims);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
+ * Instruction type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsnAnnotation}.
*/
- public abstract void visitMultiANewArrayInsn(
- final String desc,
- final int dims);
+ public Printer visitInsnAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method exception handler.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
+ * Method exception handler. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
*/
- public abstract void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type);
+ public abstract void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type);
/**
- * Method debug info.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+ * Try catch block type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
*/
- public abstract void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index);
+ public Printer visitTryCatchAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Method debug info. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+ */
+ public abstract void visitLocalVariable(final String name,
+ final String desc, final String signature, final Label start,
+ final Label end, final int index);
+
+ /**
+ * Local variable type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+ */
+ public Printer visitLocalVariableAnnotation(final int typeRef,
+ final TypePath typePath, final Label[] start, final Label[] end,
+ final int[] index, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method debug info.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
+ * Method debug info. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
*/
public abstract void visitLineNumber(final int line, final Label start);
/**
- * Method max stack and max locals.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
+ * Method max stack and max locals. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
*/
public abstract void visitMaxs(final int maxStack, final int maxLocals);
/**
- * Method end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
+ * Method end. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
*/
public abstract void visitMethodEnd();
/**
* Returns the text constructed by this visitor.
- *
+ *
* @return the text constructed by this visitor.
*/
public List<Object> getText() {
@@ -496,8 +522,9 @@ public abstract class Printer {
/**
* Prints the text constructed by this visitor.
- *
- * @param pw the print writer to be used.
+ *
+ * @param pw
+ * the print writer to be used.
*/
public void print(final PrintWriter pw) {
printList(pw, text);
@@ -505,9 +532,11 @@ public abstract class Printer {
/**
* 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.
+ *
+ * @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('\"');
@@ -540,10 +569,12 @@ public abstract class Printer {
/**
* 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.
+ *
+ * @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) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
index 81156fc..dfa5e41 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
@@ -29,26 +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 a readable
* representation of itself.
- *
+ *
* Implementations should construct readable output from an attribute data
* structure. Such representation could be used in unit test assertions.
- *
+ *
* @author Eugene Kuleshov
*/
public interface Textifiable {
/**
* Build a human readable representation of this attribute.
- *
- * @param buf a buffer used for printing Java code.
- * @param labelNames map of label instances to their names.
+ *
+ * @param buf
+ * a buffer used for printing Java code.
+ * @param labelNames
+ * map of label instances to their names.
*/
void textify(StringBuffer buf, 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/Textifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
index 3598080..854fe7c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
@@ -29,14 +29,21 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
-import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
-
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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+
/**
* A {@link Printer} that prints a disassembled view of the classes it visits.
*
@@ -130,36 +137,49 @@ public class Textifier extends Printer {
*/
protected Map<Label, String> labelNames;
+ /**
+ * Class access flags
+ */
+ private int access;
+
private int valueNumber = 0;
/**
* Constructs a new {@link Textifier}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #Textifier(int)}
* version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public Textifier() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != Textifier.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link Textifier}.
*
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected Textifier(final int api) {
super(api);
}
/**
- * Prints a disassembled view of the given class to the standard output. <p>
- * Usage: Textifier [-debug] <binary class name or class
- * file name >
+ * Prints a disassembled view of the given class to the standard output.
+ * <p>
+ * Usage: Textifier [-debug] <binary class name or class file name >
*
- * @param args the command line arguments.
+ * @param args
+ * the command line arguments.
*
- * @throws Exception if the class cannot be found, or if an IO exception
- * occurs.
+ * @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;
@@ -177,21 +197,20 @@ public class Textifier extends Printer {
}
}
if (!ok) {
- System.err.println("Prints a disassembled view of the given class.");
+ System.err
+ .println("Prints a disassembled view of the given class.");
System.err.println("Usage: Textifier [-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)
- {
+ || args[i].indexOf('/') > -1) {
cr = new ClassReader(new FileInputStream(args[i]));
} else {
cr = new ClassReader(args[i]);
}
- cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
- flags);
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
}
// ------------------------------------------------------------------------
@@ -199,38 +218,28 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ this.access = access;
int major = version & 0xFFFF;
int minor = version >>> 16;
buf.setLength(0);
- buf.append("// class version ")
- .append(major)
- .append('.')
- .append(minor)
- .append(" (")
- .append(version)
- .append(")\n");
+ buf.append("// class version ").append(major).append('.').append(minor)
+ .append(" (").append(version).append(")\n");
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append("// DEPRECATED\n");
}
- buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
appendDescriptor(CLASS_SIGNATURE, signature);
if (signature != null) {
TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
SignatureReader r = new SignatureReader(signature);
r.accept(sv);
- buf.append("// declaration: ")
- .append(name)
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append("// declaration: ").append(name)
+ .append(sv.getDeclaration()).append('\n');
}
appendAccess(access & ~Opcodes.ACC_SUPER);
@@ -264,15 +273,11 @@ public class Textifier extends Printer {
public void visitSource(final String file, final String debug) {
buf.setLength(0);
if (file != null) {
- buf.append(tab)
- .append("// compiled from: ")
- .append(file)
+ buf.append(tab).append("// compiled from: ").append(file)
.append('\n');
}
if (debug != null) {
- buf.append(tab)
- .append("// debug info: ")
- .append(debug)
+ buf.append(tab).append("// debug info: ").append(debug)
.append('\n');
}
if (buf.length() > 0) {
@@ -281,11 +286,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
buf.setLength(0);
buf.append(tab).append("OUTERCLASS ");
appendDescriptor(INTERNAL_NAME, owner);
@@ -299,30 +301,33 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitClassAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitClassAnnotation(final String desc,
+ final boolean visible) {
text.add("\n");
return visitAnnotation(desc, visible);
}
@Override
+ public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ text.add("\n");
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
public void visitClassAttribute(final Attribute attr) {
text.add("\n");
visitAttribute(attr);
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
buf.setLength(0);
buf.append(tab).append("// access flags 0x");
- buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n');
+ buf.append(
+ Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
+ .append('\n');
buf.append(tab);
appendAccess(access);
buf.append("INNERCLASS ");
@@ -336,19 +341,15 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public Textifier visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
buf.setLength(0);
buf.append('\n');
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append(tab).append("// DEPRECATED\n");
}
- buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
if (signature != null) {
buf.append(tab);
appendDescriptor(FIELD_SIGNATURE, signature);
@@ -356,10 +357,8 @@ public class Textifier extends Printer {
TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
SignatureReader r = new SignatureReader(signature);
r.acceptType(sv);
- buf.append(tab)
- .append("// declaration: ")
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append(tab).append("// declaration: ")
+ .append(sv.getDeclaration()).append('\n');
}
buf.append(tab);
@@ -385,19 +384,15 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ public Textifier visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
buf.setLength(0);
buf.append('\n');
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append(tab).append("// DEPRECATED\n");
}
- buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
if (signature != null) {
buf.append(tab);
@@ -410,12 +405,8 @@ public class Textifier extends Printer {
String genericReturn = v.getReturnType();
String genericExceptions = v.getExceptions();
- buf.append(tab)
- .append("// declaration: ")
- .append(genericReturn)
- .append(' ')
- .append(name)
- .append(genericDecl);
+ buf.append(tab).append("// declaration: ").append(genericReturn)
+ .append(' ').append(name).append(genericDecl);
if (genericExceptions != null) {
buf.append(" throws ").append(genericExceptions);
}
@@ -433,6 +424,11 @@ public class Textifier extends Printer {
if ((access & Opcodes.ACC_BRIDGE) != 0) {
buf.append("bridge ");
}
+ if ((this.access & Opcodes.ACC_INTERFACE) != 0
+ && (access & Opcodes.ACC_ABSTRACT) == 0
+ && (access & Opcodes.ACC_STATIC) == 0) {
+ buf.append("default ");
+ }
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
@@ -588,11 +584,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -604,10 +597,7 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitAnnotation(
- final String name,
- final String desc)
- {
+ public Textifier visitAnnotation(final String name, final String desc) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -624,9 +614,7 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitArray(
- final String name)
- {
+ public Textifier visitArray(final String name) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -649,14 +637,18 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
- public Textifier visitFieldAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitFieldAnnotation(final String desc,
+ final boolean visible) {
return visitAnnotation(desc, visible);
}
@Override
+ public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
public void visitFieldAttribute(final Attribute attr) {
visitAttribute(attr);
}
@@ -670,6 +662,16 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(final String name, final int access) {
+ buf.setLength(0);
+ buf.append(tab2).append("// parameter ");
+ appendAccess(access);
+ buf.append(' ').append((name == null) ? "<no name>" : name)
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
public Textifier visitAnnotationDefault() {
text.add(tab2 + "default=");
Textifier t = createTextifier();
@@ -679,19 +681,20 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitMethodAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitMethodAnnotation(final String desc,
+ final boolean visible) {
return visitAnnotation(desc, visible);
}
@Override
- public Textifier visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
+ public Textifier visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
buf.setLength(0);
buf.append(tab2).append('@');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -725,40 +728,35 @@ public class Textifier extends Printer {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
buf.setLength(0);
buf.append(ltab);
buf.append("FRAME ");
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- buf.append("FULL [");
- appendFrameTypes(nLocal, local);
- buf.append("] [");
- appendFrameTypes(nStack, stack);
- buf.append(']');
- break;
- case Opcodes.F_APPEND:
- buf.append("APPEND [");
- appendFrameTypes(nLocal, local);
- buf.append(']');
- break;
- case Opcodes.F_CHOP:
- buf.append("CHOP ").append(nLocal);
- break;
- case Opcodes.F_SAME:
- buf.append("SAME");
- break;
- case Opcodes.F_SAME1:
- buf.append("SAME1 ");
- appendFrameTypes(1, stack);
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ buf.append("FULL [");
+ appendFrameTypes(nLocal, local);
+ buf.append("] [");
+ appendFrameTypes(nStack, stack);
+ buf.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ buf.append("APPEND [");
+ appendFrameTypes(nLocal, local);
+ buf.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("CHOP ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ buf.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ buf.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
}
buf.append('\n');
text.add(buf.toString());
@@ -777,20 +775,15 @@ public class Textifier extends Printer {
buf.append(tab2)
.append(OPCODES[opcode])
.append(' ')
- .append(opcode == Opcodes.NEWARRAY
- ? TYPES[operand]
- : Integer.toString(operand))
- .append('\n');
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+ .toString(operand)).append('\n');
text.add(buf.toString());
}
@Override
public void visitVarInsn(final int opcode, final int var) {
buf.setLength(0);
- buf.append(tab2)
- .append(OPCODES[opcode])
- .append(' ')
- .append(var)
+ buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
.append('\n');
text.add(buf.toString());
}
@@ -805,12 +798,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
buf.setLength(0);
buf.append(tab2).append(OPCODES[opcode]).append(' ');
appendDescriptor(INTERNAL_NAME, owner);
@@ -820,13 +809,30 @@ public class Textifier extends Printer {
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)
- {
+ 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(tab2).append(OPCODES[opcode]).append(' ');
appendDescriptor(INTERNAL_NAME, owner);
@@ -837,37 +843,42 @@ public class Textifier extends Printer {
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
buf.setLength(0);
buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
buf.append(" [");
+ buf.append('\n');
+ buf.append(tab3);
appendHandle(bsm);
+ buf.append('\n');
buf.append(tab3).append("// arguments:");
- if(bsmArgs.length == 0) {
+ if (bsmArgs.length == 0) {
buf.append(" none");
} else {
- buf.append('\n').append(tab3);
- for(int i = 0; i < bsmArgs.length; i++) {
+ buf.append('\n');
+ for (int i = 0; i < bsmArgs.length; i++) {
+ buf.append(tab3);
Object cst = bsmArgs[i];
if (cst instanceof String) {
Printer.appendString(buf, (String) cst);
} else if (cst instanceof Type) {
- buf.append(((Type) cst).getDescriptor()).append(".class");
+ Type type = (Type) cst;
+ if(type.getSort() == Type.METHOD){
+ appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+ } else {
+ buf.append(type.getDescriptor()).append(".class");
+ }
} else if (cst instanceof Handle) {
appendHandle((Handle) cst);
} else {
buf.append(cst);
}
- buf.append(", ");
+ buf.append(", \n");
}
- buf.setLength(buf.length() - 2);
+ buf.setLength(buf.length() - 3);
}
buf.append('\n');
buf.append(tab2).append("]\n");
@@ -910,22 +921,14 @@ public class Textifier extends Printer {
@Override
public void visitIincInsn(final int var, final int increment) {
buf.setLength(0);
- buf.append(tab2)
- .append("IINC ")
- .append(var)
- .append(' ')
- .append(increment)
- .append('\n');
+ buf.append(tab2).append("IINC ").append(var).append(' ')
+ .append(increment).append('\n');
text.add(buf.toString());
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
buf.setLength(0);
buf.append(tab2).append("TABLESWITCH\n");
for (int i = 0; i < labels.length; ++i) {
@@ -940,11 +943,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
buf.setLength(0);
buf.append(tab2).append("LOOKUPSWITCH\n");
for (int i = 0; i < labels.length; ++i) {
@@ -968,12 +968,14 @@ public class Textifier extends Printer {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public Printer visitInsnAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
buf.setLength(0);
buf.append(tab2).append("TRYCATCHBLOCK ");
appendLabel(start);
@@ -988,14 +990,28 @@ public class Textifier extends Printer {
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ buf.setLength(0);
+ buf.append(tab2).append("TRYCATCHBLOCK @");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ buf.append(visible ? "\n" : " // invisible\n");
+ text.add(buf.toString());
+ return t;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
buf.setLength(0);
buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1012,12 +1028,37 @@ public class Textifier extends Printer {
TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
SignatureReader r = new SignatureReader(signature);
r.acceptType(sv);
- buf.append(tab2)
- .append("// declaration: ")
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append(tab2).append("// declaration: ")
+ .append(sv.getDeclaration()).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(tab2).append("LOCALVARIABLE @");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ for (int i = 0; i < start.length; ++i) {
+ buf.append(" [ ");
+ appendLabel(start[i]);
+ buf.append(" - ");
+ appendLabel(end[i]);
+ buf.append(" - ").append(index[i]).append(" ]");
}
+ buf.append(visible ? "\n" : " // invisible\n");
text.add(buf.toString());
+ return t;
}
@Override
@@ -1051,14 +1092,13 @@ public class Textifier extends Printer {
/**
* Prints a disassembled view of the given annotation.
*
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values.
*/
- public Textifier visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitAnnotation(final String desc, final boolean visible) {
buf.setLength(0);
buf.append(tab).append('@');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1071,9 +1111,43 @@ public class Textifier extends Printer {
}
/**
+ * Prints a disassembled view of the given type annotation.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public Textifier visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ buf.append(visible ? "\n" : " // invisible\n");
+ text.add(buf.toString());
+ return t;
+ }
+
+ /**
* Prints a disassembled view of the given attribute.
*
- * @param attr an attribute.
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(final Attribute attr) {
buf.setLength(0);
@@ -1106,15 +1180,16 @@ public class Textifier extends Printer {
* Appends an internal name, a type descriptor or a type signature to
* {@link #buf buf}.
*
- * @param type indicates if desc is an internal name, a field descriptor, a
- * method descriptor, a class signature, ...
- * @param desc an internal name, type descriptor, or type signature. May be
- * <tt>null</tt>.
+ * @param type
+ * indicates if desc is an internal name, a field descriptor, a
+ * method descriptor, a class signature, ...
+ * @param desc
+ * an internal name, type descriptor, or type signature. May be
+ * <tt>null</tt>.
*/
protected void appendDescriptor(final int type, final String desc) {
if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
- || type == METHOD_SIGNATURE)
- {
+ || type == METHOD_SIGNATURE) {
if (desc != null) {
buf.append("// signature ").append(desc).append('\n');
}
@@ -1127,7 +1202,8 @@ public class Textifier extends Printer {
* Appends the name of the given label to {@link #buf buf}. Creates a new
* label name if the given label does not yet have one.
*
- * @param l a label.
+ * @param l
+ * a label.
*/
protected void appendLabel(final Label l) {
if (labelNames == null) {
@@ -1144,56 +1220,68 @@ public class Textifier extends Printer {
/**
* Appends the information about the given handle to {@link #buf buf}.
*
- * @param h a handle, non null.
+ * @param h
+ * a handle, non null.
*/
protected void appendHandle(final Handle h) {
- buf.append('\n').append(tab3);
int tag = h.getTag();
- buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+ buf.append("// handle kind 0x").append(Integer.toHexString(tag))
+ .append(" : ");
+ boolean isMethodHandle = false;
switch (tag) {
- case Opcodes.H_GETFIELD:
- buf.append("GETFIELD");
- break;
- case Opcodes.H_GETSTATIC:
- buf.append("GETSTATIC");
- break;
- case Opcodes.H_PUTFIELD:
- buf.append("PUTFIELD");
- break;
- case Opcodes.H_PUTSTATIC:
- buf.append("PUTSTATIC");
- break;
- case Opcodes.H_INVOKEINTERFACE:
- buf.append("INVOKEINTERFACE");
- break;
- case Opcodes.H_INVOKESPECIAL:
- buf.append("INVOKESPECIAL");
- break;
- case Opcodes.H_INVOKESTATIC:
- buf.append("INVOKESTATIC");
- break;
- case Opcodes.H_INVOKEVIRTUAL:
- buf.append("INVOKEVIRTUAL");
- break;
- case Opcodes.H_NEWINVOKESPECIAL:
- buf.append("NEWINVOKESPECIAL");
- break;
+ case Opcodes.H_GETFIELD:
+ buf.append("GETFIELD");
+ break;
+ case Opcodes.H_GETSTATIC:
+ buf.append("GETSTATIC");
+ break;
+ case Opcodes.H_PUTFIELD:
+ buf.append("PUTFIELD");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ buf.append("PUTSTATIC");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ buf.append("INVOKEINTERFACE");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ buf.append("INVOKESPECIAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ buf.append("INVOKESTATIC");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ buf.append("INVOKEVIRTUAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ buf.append("NEWINVOKESPECIAL");
+ isMethodHandle = true;
+ break;
}
buf.append('\n');
buf.append(tab3);
appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.');
buf.append(h.getName());
- buf.append('(');
+ if(!isMethodHandle){
+ buf.append('(');
+ }
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
- buf.append(')').append('\n');
+ if(!isMethodHandle){
+ buf.append(')');
+ }
}
/**
- * Appends a string representation of the given access modifiers to {@link
- * #buf buf}.
+ * Appends a string representation of the given access modifiers to
+ * {@link #buf buf}.
*
- * @param access some access modifiers.
+ * @param access
+ * some access modifiers.
*/
private void appendAccess(final int access) {
if ((access & Opcodes.ACC_PUBLIC) != 0) {
@@ -1226,6 +1314,12 @@ public class Textifier extends Printer {
if ((access & Opcodes.ACC_STRICT) != 0) {
buf.append("strictfp ");
}
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ buf.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_MANDATED) != 0) {
+ buf.append("mandated ");
+ }
if ((access & Opcodes.ACC_ENUM) != 0) {
buf.append("enum ");
}
@@ -1237,6 +1331,90 @@ public class Textifier extends Printer {
}
}
+ private void appendTypeReference(final int typeRef) {
+ TypeReference ref = new TypeReference(typeRef);
+ switch (ref.getSort()) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ buf.append("CLASS_TYPE_PARAMETER ").append(
+ ref.getTypeParameterIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ buf.append("METHOD_TYPE_PARAMETER ").append(
+ ref.getTypeParameterIndex());
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex());
+ break;
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ buf.append("CLASS_TYPE_PARAMETER_BOUND ")
+ .append(ref.getTypeParameterIndex()).append(", ")
+ .append(ref.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ buf.append("METHOD_TYPE_PARAMETER_BOUND ")
+ .append(ref.getTypeParameterIndex()).append(", ")
+ .append(ref.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.FIELD:
+ buf.append("FIELD");
+ break;
+ case TypeReference.METHOD_RETURN:
+ buf.append("METHOD_RETURN");
+ break;
+ case TypeReference.METHOD_RECEIVER:
+ buf.append("METHOD_RECEIVER");
+ break;
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ buf.append("METHOD_FORMAL_PARAMETER ").append(
+ ref.getFormalParameterIndex());
+ break;
+ case TypeReference.THROWS:
+ buf.append("THROWS ").append(ref.getExceptionIndex());
+ break;
+ case TypeReference.LOCAL_VARIABLE:
+ buf.append("LOCAL_VARIABLE");
+ break;
+ case TypeReference.RESOURCE_VARIABLE:
+ buf.append("RESOURCE_VARIABLE");
+ break;
+ case TypeReference.EXCEPTION_PARAMETER:
+ buf.append("EXCEPTION_PARAMETER ").append(
+ ref.getTryCatchBlockIndex());
+ break;
+ case TypeReference.INSTANCEOF:
+ buf.append("INSTANCEOF");
+ break;
+ case TypeReference.NEW:
+ buf.append("NEW");
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ buf.append("CONSTRUCTOR_REFERENCE");
+ break;
+ case TypeReference.METHOD_REFERENCE:
+ buf.append("METHOD_REFERENCE");
+ break;
+ case TypeReference.CAST:
+ buf.append("CAST ").append(ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ }
+ }
+
private void appendFrameTypes(final int n, final Object[] o) {
for (int i = 0; i < n; ++i) {
if (i > 0) {
@@ -1251,27 +1429,27 @@ public class Textifier extends Printer {
}
} else if (o[i] instanceof Integer) {
switch (((Integer) o[i]).intValue()) {
- case 0:
- appendDescriptor(FIELD_DESCRIPTOR, "T");
- break;
- case 1:
- appendDescriptor(FIELD_DESCRIPTOR, "I");
- break;
- case 2:
- appendDescriptor(FIELD_DESCRIPTOR, "F");
- break;
- case 3:
- appendDescriptor(FIELD_DESCRIPTOR, "D");
- break;
- case 4:
- appendDescriptor(FIELD_DESCRIPTOR, "J");
- break;
- case 5:
- appendDescriptor(FIELD_DESCRIPTOR, "N");
- break;
- case 6:
- appendDescriptor(FIELD_DESCRIPTOR, "U");
- break;
+ case 0:
+ appendDescriptor(FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(FIELD_DESCRIPTOR, "U");
+ break;
}
} else {
appendLabel((Label) o[i]);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
index 84b9750..3af500a 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
@@ -33,13 +33,12 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * An {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor} that prints the annotations it visits with a
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a
* {@link Printer}.
- *
+ *
* @author Eric Bruneton
*/
-public final class TraceAnnotationVisitor extends AnnotationVisitor
-{
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
private final Printer p;
@@ -48,7 +47,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
}
public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
- super(Opcodes.ASM4, av);
+ super(Opcodes.ASM5, av);
this.p = p;
}
@@ -59,33 +58,26 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
p.visitEnum(name, desc, value);
super.visitEnum(name, desc, value);
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
Printer p = this.p.visitAnnotation(name, desc);
- AnnotationVisitor av = this.av == null
- ? null
- : this.av.visitAnnotation(name, desc);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitAnnotation(name, desc);
return new TraceAnnotationVisitor(av, p);
}
@Override
public AnnotationVisitor visitArray(final String name) {
Printer p = this.p.visitArray(name);
- AnnotationVisitor av = this.av == null
- ? null
- : this.av.visitArray(name);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitArray(name);
return new TraceAnnotationVisitor(av, p);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
index ae06852..7c6a775 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,18 +29,28 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.io.PrintWriter;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A {@link ClassVisitor} that prints the classes it visits with a
* {@link Printer}. This class visitor can be used in the middle of a class
* visitor chain to trace the class that is visited at a given point in this
- * chain. This may be useful for debugging purposes. <p> The trace printed when
- * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ * chain. This may be useful for debugging purposes.
+ * <p>
+ * The trace printed when visiting the <tt>Hello</tt> class is the following:
+ * <p>
+ * <blockquote>
*
- * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello {
+ * <pre>
+ * // class version 49.0 (49) // access flags 0x21 public class Hello {
*
* // compiled from: Hello.java
*
@@ -51,14 +60,21 @@ import java.io.PrintWriter;
* // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
* java/lang/System out Ljava/io/PrintStream; LDC "hello"
* INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
- * MAXSTACK = 2 MAXLOCALS = 1 } </pre>
+ * MAXSTACK = 2 MAXLOCALS = 1 }
+ * </pre>
*
- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * </blockquote> where <tt>Hello</tt> is defined by:
+ * <p>
+ * <blockquote>
*
- * <pre> public class Hello {
+ * <pre>
+ * public class Hello {
*
- * public static void main(String[] args) {
- * System.out.println("hello"); } } </pre>
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
+ * }
+ * </pre>
*
* </blockquote>
*
@@ -80,7 +96,8 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param pw the print writer to be used to print the class.
+ * @param pw
+ * the print writer to be used to print the class.
*/
public TraceClassVisitor(final PrintWriter pw) {
this(null, pw);
@@ -89,9 +106,11 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
- * May be <tt>null</tt>.
- * @param pw the print writer to be used to print the class.
+ * @param cv
+ * the {@link ClassVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ * @param pw
+ * the print writer to be used to print the class.
*/
public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
this(cv, new Textifier(), pw);
@@ -100,32 +119,27 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
- * May be <tt>null</tt>.
- * @param p the object that actually converts visit events into text.
- * @param pw the print writer to be used to print the class. May be null if
- * you simply want to use the result via
- * {@link Printer#getText()}, instead of printing it.
+ * @param cv
+ * the {@link ClassVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ * @param p
+ * the object that actually converts visit events into text.
+ * @param pw
+ * the print writer to be used to print the class. May be null if
+ * you simply want to use the result via
+ * {@link Printer#getText()}, instead of printing it.
*/
- public TraceClassVisitor(
- final ClassVisitor cv,
- final Printer p,
- final PrintWriter pw)
- {
- super(Opcodes.ASM4, cv);
+ public TraceClassVisitor(final ClassVisitor cv, final Printer p,
+ final PrintWriter pw) {
+ super(Opcodes.ASM5, cv);
this.pw = pw;
this.p = p;
}
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
p.visit(version, access, name, signature, superName, interfaces);
super.visit(version, access, name, signature, superName, interfaces);
}
@@ -137,20 +151,15 @@ public final class TraceClassVisitor extends ClassVisitor {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
p.visitOuterClass(owner, name, desc);
super.visitOuterClass(owner, name, desc);
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitClassAnnotation(desc, visible);
AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
visible);
@@ -158,61 +167,44 @@ public final class TraceClassVisitor extends ClassVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitClassAttribute(attr);
super.visitAttribute(attr);
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
p.visitInnerClass(name, outerName, innerName, access);
super.visitInnerClass(name, outerName, innerName, access);
}
@Override
- public FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- Printer p = this.p.visitField(access,
- name,
- desc,
- signature,
- value);
- FieldVisitor fv = cv == null ? null : cv.visitField(access,
- name,
- desc,
- signature,
- value);
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ Printer p = this.p.visitField(access, name, desc, signature, value);
+ FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
+ signature, value);
return new TraceFieldVisitor(fv, p);
}
@Override
- public MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- Printer p = this.p.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
- MethodVisitor mv = cv == null ? null : cv.visitMethod(access,
- name,
- desc,
- signature,
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ Printer p = this.p.visitMethod(access, name, desc, signature,
exceptions);
+ MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
+ desc, signature, exceptions);
return new TraceMethodVisitor(mv, p);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
index d75b04b..3fed39e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,15 +33,15 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor} that prints the fields it visits with a
+ * A {@link FieldVisitor} that prints the fields it visits with a
* {@link Printer}.
*
* @author Eric Bruneton
*/
-public final class TraceFieldVisitor extends FieldVisitor
-{
+public final class TraceFieldVisitor extends FieldVisitor {
public final Printer p;
@@ -51,15 +50,13 @@ public final class TraceFieldVisitor extends FieldVisitor
}
public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
- super(Opcodes.ASM4, fv);
+ super(Opcodes.ASM5, fv);
this.p = p;
}
-
+
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitFieldAnnotation(desc, visible);
AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
visible);
@@ -67,6 +64,16 @@ public final class TraceFieldVisitor extends FieldVisitor
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitFieldAttribute(attr);
super.visitAttribute(attr);
[03/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
index 0d7fe3f..859a8d1 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,12 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link MethodVisitor} that prints the methods it visits with a
* {@link Printer}.
- *
+ *
* @author Eric Bruneton
*/
public final class TraceMethodVisitor extends MethodVisitor {
@@ -47,15 +52,19 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
- super(Opcodes.ASM4, mv);
+ super(Opcodes.ASM5, mv);
this.p = p;
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public void visitParameter(String name, int access) {
+ p.visitParameter(name, access);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitMethodAnnotation(desc, visible);
AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
visible);
@@ -63,6 +72,16 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitMethodAttribute(attr);
super.visitAttribute(attr);
@@ -76,17 +95,11 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
- Printer p = this.p.visitParameterAnnotation(parameter,
- desc,
- visible);
- AnnotationVisitor av = mv == null
- ? null
- : mv.visitParameterAnnotation(parameter, desc, visible);
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
+ parameter, desc, visible);
return new TraceAnnotationVisitor(av, p);
}
@@ -97,13 +110,8 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
p.visitFrame(type, nLocal, local, nStack, stack);
super.visitFrame(type, nLocal, local, nStack, stack);
}
@@ -133,34 +141,42 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
p.visitFieldInsn(opcode, owner, name, desc);
super.visitFieldInsn(opcode, owner, name, desc);
}
+ @Deprecated
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
p.visitMethodInsn(opcode, owner, name, desc);
- super.visitMethodInsn(opcode, owner, name, desc);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ p.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
@@ -190,22 +206,15 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
p.visitTableSwitchInsn(min, max, dflt, labels);
super.visitTableSwitchInsn(min, max, dflt, labels);
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
p.visitLookupSwitchInsn(dflt, keys, labels);
super.visitLookupSwitchInsn(dflt, keys, labels);
}
@@ -217,30 +226,53 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p
+ .visitInsnAnnotation(typeRef, typePath, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
p.visitTryCatchBlock(start, end, handler, type);
super.visitTryCatchBlock(start, end, handler, type);
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
p.visitLocalVariable(name, desc, signature, start, end, index);
super.visitLocalVariable(name, desc, signature, start, end, index);
}
@Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath,
+ start, end, index, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv
+ .visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitLineNumber(final int line, final Label start) {
p.visitLineNumber(line, start);
super.visitLineNumber(line, start);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
index 3b0a178..1e2c9a3 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
@@ -33,14 +33,13 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
- * A {@link org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor} that prints a disassembled view of the signature
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
* it visits.
- *
+ *
* @author Eugene Kuleshov
* @author Eric Bruneton
*/
-public final class TraceSignatureVisitor extends SignatureVisitor
-{
+public final class TraceSignatureVisitor extends SignatureVisitor {
private final StringBuffer declaration;
@@ -76,13 +75,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor
private String separator = "";
public TraceSignatureVisitor(final int access) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
this.declaration = new StringBuffer();
}
private TraceSignatureVisitor(final StringBuffer buf) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
this.declaration = buf;
}
@@ -118,8 +117,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor
@Override
public SignatureVisitor visitInterface() {
- separator = seenInterface ? ", " : isInterface
- ? " extends "
+ separator = seenInterface ? ", " : isInterface ? " extends "
: " implements ";
seenInterface = true;
startType();
@@ -166,34 +164,34 @@ public final class TraceSignatureVisitor extends SignatureVisitor
@Override
public void visitBaseType(final char descriptor) {
switch (descriptor) {
- case 'V':
- declaration.append("void");
- break;
- case 'B':
- declaration.append("byte");
- break;
- case 'J':
- declaration.append("long");
- break;
- case 'Z':
- declaration.append("boolean");
- break;
- case 'I':
- declaration.append("int");
- break;
- case 'S':
- declaration.append("short");
- break;
- case 'C':
- declaration.append("char");
- break;
- case 'F':
- declaration.append("float");
- break;
- // case 'D':
- default:
- declaration.append("double");
- break;
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ // case 'D':
+ default:
+ declaration.append("double");
+ break;
}
endType();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
new file mode 100644
index 0000000..88dab5e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
@@ -0,0 +1,1453 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
+ * document into Java class file. This class can be feeded by any kind of SAX
+ * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ *
+ * @author Eugene Kuleshov
+ */
+public class ASMContentHandler extends DefaultHandler implements Opcodes {
+
+ /**
+ * Stack of the intermediate processing contexts.
+ */
+ private final ArrayList<Object> stack = new ArrayList<Object>();
+
+ /**
+ * Complete name of the current element.
+ */
+ String match = "";
+
+ /**
+ * Current instance of the {@link ClassVisitor ClassVisitor} used to visit
+ * classfile bytecode.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Map of the active {@link Label Label} instances for current method.
+ */
+ protected Map<Object, Label> labels;
+
+ private static final String BASE = "class";
+
+ private final RuleSet RULES = new RuleSet();
+ {
+ RULES.add(BASE, new ClassRule());
+ RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
+ RULES.add(BASE + "/interfaces", new InterfacesRule());
+ RULES.add(BASE + "/outerclass", new OuterClassRule());
+ RULES.add(BASE + "/innerclass", new InnerClassRule());
+ RULES.add(BASE + "/source", new SourceRule());
+ RULES.add(BASE + "/field", new FieldRule());
+
+ RULES.add(BASE + "/method", new MethodRule());
+ RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
+ RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
+
+ RULES.add(BASE + "/method/parameter", new MethodParameterRule());
+ RULES.add(BASE + "/method/annotationDefault",
+ new AnnotationDefaultRule());
+
+ RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
+
+ RULES.add(BASE + "/method/code/frame", new FrameRule());
+ RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
+ RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
+
+ RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
+ RULES.add(BASE + "/method/code/TABLESWITCH/label",
+ new TableSwitchLabelRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
+ new LookupSwitchLabelRule());
+
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
+ new InvokeDynamicBsmArgumentsRule());
+
+ RULES.add(BASE + "/method/code/Label", new LabelRule());
+ RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
+ RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
+ RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
+ RULES.add(BASE + "/method/code/Max", new MaxRule());
+
+ RULES.add("*/annotation", new AnnotationRule());
+ RULES.add("*/typeAnnotation", new TypeAnnotationRule());
+ RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
+ RULES.add("*/insnAnnotation", new InsnAnnotationRule());
+ RULES.add("*/tryCatchAnnotation", new TryCatchAnnotationRule());
+ RULES.add("*/localVariableAnnotation",
+ new LocalVariableAnnotationRule());
+ RULES.add("*/annotationValue", new AnnotationValueRule());
+ RULES.add("*/annotationValueAnnotation",
+ new AnnotationValueAnnotationRule());
+ RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
+ RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
+ }
+
+ private static interface OpcodeGroup {
+ public static final int INSN = 0;
+ public static final int INSN_INT = 1;
+ public static final int INSN_VAR = 2;
+ public static final int INSN_TYPE = 3;
+ public static final int INSN_FIELD = 4;
+ public static final int INSN_METHOD = 5;
+ public static final int INSN_JUMP = 6;
+ public static final int INSN_LDC = 7;
+ public static final int INSN_IINC = 8;
+ public static final int INSN_MULTIANEWARRAY = 9;
+ }
+
+ /**
+ * Map of the opcode names to opcode and opcode group
+ */
+ static final HashMap<String, Opcode> OPCODES = new HashMap<String, Opcode>();
+ static {
+ addOpcode("NOP", NOP, OpcodeGroup.INSN);
+ addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
+ addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
+ addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
+ addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
+ addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
+ addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
+ addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
+ addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
+ addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
+ addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
+ addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
+ addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
+ addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
+ addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
+ addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
+ addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
+ addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
+ addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
+ addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
+ addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
+ addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
+ addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
+ addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
+ addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
+ addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
+ addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
+ addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
+ addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
+ addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
+ addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
+ addOpcode("POP", POP, OpcodeGroup.INSN);
+ addOpcode("POP2", POP2, OpcodeGroup.INSN);
+ addOpcode("DUP", DUP, OpcodeGroup.INSN);
+ addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
+ addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
+ addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
+ addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
+ addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
+ addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
+ addOpcode("IADD", IADD, OpcodeGroup.INSN);
+ addOpcode("LADD", LADD, OpcodeGroup.INSN);
+ addOpcode("FADD", FADD, OpcodeGroup.INSN);
+ addOpcode("DADD", DADD, OpcodeGroup.INSN);
+ addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
+ addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
+ addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
+ addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
+ addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
+ addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
+ addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
+ addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
+ addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
+ addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
+ addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
+ addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
+ addOpcode("IREM", IREM, OpcodeGroup.INSN);
+ addOpcode("LREM", LREM, OpcodeGroup.INSN);
+ addOpcode("FREM", FREM, OpcodeGroup.INSN);
+ addOpcode("DREM", DREM, OpcodeGroup.INSN);
+ addOpcode("INEG", INEG, OpcodeGroup.INSN);
+ addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
+ addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
+ addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
+ addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
+ addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
+ addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
+ addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
+ addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
+ addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
+ addOpcode("IAND", IAND, OpcodeGroup.INSN);
+ addOpcode("LAND", LAND, OpcodeGroup.INSN);
+ addOpcode("IOR", IOR, OpcodeGroup.INSN);
+ addOpcode("LOR", LOR, OpcodeGroup.INSN);
+ addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
+ addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
+ addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
+ addOpcode("I2L", I2L, OpcodeGroup.INSN);
+ addOpcode("I2F", I2F, OpcodeGroup.INSN);
+ addOpcode("I2D", I2D, OpcodeGroup.INSN);
+ addOpcode("L2I", L2I, OpcodeGroup.INSN);
+ addOpcode("L2F", L2F, OpcodeGroup.INSN);
+ addOpcode("L2D", L2D, OpcodeGroup.INSN);
+ addOpcode("F2I", F2I, OpcodeGroup.INSN);
+ addOpcode("F2L", F2L, OpcodeGroup.INSN);
+ addOpcode("F2D", F2D, OpcodeGroup.INSN);
+ addOpcode("D2I", D2I, OpcodeGroup.INSN);
+ addOpcode("D2L", D2L, OpcodeGroup.INSN);
+ addOpcode("D2F", D2F, OpcodeGroup.INSN);
+ addOpcode("I2B", I2B, OpcodeGroup.INSN);
+ addOpcode("I2C", I2C, OpcodeGroup.INSN);
+ addOpcode("I2S", I2S, OpcodeGroup.INSN);
+ addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
+ addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
+ addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
+ addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
+ addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
+ addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
+ addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
+ addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
+ addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
+ addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
+ addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
+ addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
+ addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
+ addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
+ addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
+ addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
+ addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
+ addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
+ addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
+ addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
+ addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
+ addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
+ addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
+ addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
+ addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
+ OpcodeGroup.INSN_MULTIANEWARRAY);
+ addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
+ }
+
+ private static void addOpcode(String operStr, int oper, int group) {
+ OPCODES.put(operStr, new Opcode(oper, group));
+ }
+
+ static final HashMap<String, Integer> TYPES = new HashMap<String, Integer>();
+ static {
+ String[] types = SAXCodeAdapter.TYPES;
+ for (int i = 0; i < types.length; i++) {
+ TYPES.put(types[i], new Integer(i));
+ }
+ }
+
+ /**
+ * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
+ *
+ * @param cv
+ * class visitor that will be called to reconstruct the classfile
+ * using the XML stream.
+ */
+ public ASMContentHandler(final ClassVisitor cv) {
+ this.cv = cv;
+ }
+
+ /**
+ * Process notification of the start of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified name (with prefix), or the empty string if
+ * qualified names are not available.
+ * @param list
+ * - The attributes attached to the element. If there are no
+ * attributes, it shall be an empty Attributes object.
+ * @exception SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void startElement(final String ns, final String lName,
+ final String qName, final Attributes list) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Compute the current matching rule
+ StringBuffer sb = new StringBuffer(match);
+ if (match.length() > 0) {
+ sb.append('/');
+ }
+ sb.append(name);
+ match = sb.toString();
+
+ // Fire "begin" events for all relevant rules
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.begin(name, list);
+ }
+ }
+
+ /**
+ * Process notification of the end of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified XML 1.0 name (with prefix), or the empty
+ * string if qualified names are not available.
+ *
+ * @exception SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void endElement(final String ns, final String lName,
+ final String qName) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Fire "end" events for all relevant rules in reverse order
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.end(name);
+ }
+
+ // Recover the previous match expression
+ int slash = match.lastIndexOf('/');
+ if (slash >= 0) {
+ match = match.substring(0, slash);
+ } else {
+ match = "";
+ }
+ }
+
+ /**
+ * Return the top object on the stack without removing it. If there are no
+ * objects on the stack, return <code>null</code>.
+ *
+ * @return the top object on the stack without removing it.
+ */
+ final Object peek() {
+ int size = stack.size();
+ return size == 0 ? null : stack.get(size - 1);
+ }
+
+ /**
+ * Pop the top object off of the stack, and return it. If there are no
+ * objects on the stack, return <code>null</code>.
+ *
+ * @return the top object off of the stack.
+ */
+ final Object pop() {
+ int size = stack.size();
+ return size == 0 ? null : stack.remove(size - 1);
+ }
+
+ /**
+ * Push a new object onto the top of the object stack.
+ *
+ * @param object
+ * The new object
+ */
+ final void push(final Object object) {
+ stack.add(object);
+ }
+
+ static final class RuleSet {
+
+ private final HashMap<String, Object> rules = new HashMap<String, Object>();
+
+ private final ArrayList<String> lpatterns = new ArrayList<String>();
+
+ private final ArrayList<String> rpatterns = new ArrayList<String>();
+
+ public void add(final String path, final Object rule) {
+ String pattern = path;
+ if (path.startsWith("*/")) {
+ pattern = path.substring(1);
+ lpatterns.add(pattern);
+ } else if (path.endsWith("/*")) {
+ pattern = path.substring(0, path.length() - 1);
+ rpatterns.add(pattern);
+ }
+ rules.put(pattern, rule);
+ }
+
+ public Object match(final String path) {
+ if (rules.containsKey(path)) {
+ return rules.get(path);
+ }
+
+ int n = path.lastIndexOf('/');
+ for (Iterator<String> it = lpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.substring(n).endsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ for (Iterator<String> it = rpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.startsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Rule
+ */
+ protected abstract class Rule {
+
+ public void begin(final String name, final Attributes attrs)
+ throws SAXException {
+ }
+
+ public void end(final String name) {
+ }
+
+ protected final Object getValue(final String desc, final String val)
+ throws SAXException {
+ Object value = null;
+ if (val != null) {
+ if ("Ljava/lang/String;".equals(desc)) {
+ value = decode(val);
+ } else if ("Ljava/lang/Integer;".equals(desc)
+ || "I".equals(desc) || "S".equals(desc)
+ || "B".equals(desc) || "C".equals(desc)
+ || "Z".equals(desc)) {
+ value = new Integer(val);
+
+ } else if ("Ljava/lang/Short;".equals(desc)) {
+ value = new Short(val);
+
+ } else if ("Ljava/lang/Byte;".equals(desc)) {
+ value = new Byte(val);
+
+ } else if ("Ljava/lang/Character;".equals(desc)) {
+ value = new Character(decode(val).charAt(0));
+
+ } else if ("Ljava/lang/Boolean;".equals(desc)) {
+ value = Boolean.valueOf(val);
+
+ } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
+ value = new Long(val);
+ } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
+ value = new Float(val);
+ } else if ("Ljava/lang/Double;".equals(desc)
+ || "D".equals(desc)) {
+ value = new Double(val);
+ } else if (Type.getDescriptor(Type.class).equals(desc)) {
+ value = Type.getType(val);
+
+ } else if (Type.getDescriptor(Handle.class).equals(desc)) {
+ value = decodeHandle(val);
+
+ } else {
+ // TODO use of default toString().
+ throw new SAXException("Invalid value:" + val + " desc:"
+ + desc + " ctx:" + this);
+ }
+ }
+ return value;
+ }
+
+ Handle decodeHandle(final String val) throws SAXException {
+ try {
+ int dotIndex = val.indexOf('.');
+ int descIndex = val.indexOf('(', dotIndex + 1);
+ int tagIndex = val.lastIndexOf('(');
+
+ int tag = Integer.parseInt(val.substring(tagIndex + 1,
+ val.length() - 1));
+ String owner = val.substring(0, dotIndex);
+ String name = val.substring(dotIndex + 1, descIndex);
+ String desc = val.substring(descIndex, tagIndex - 1);
+ return new Handle(tag, owner, name, desc);
+
+ } catch (RuntimeException e) {
+ throw new SAXException("Malformed handle " + val, e);
+ }
+ }
+
+ private final String decode(final String val) throws SAXException {
+ StringBuffer sb = new StringBuffer(val.length());
+ try {
+ int n = 0;
+ while (n < val.length()) {
+ char c = val.charAt(n);
+ if (c == '\\') {
+ n++;
+ c = val.charAt(n);
+ if (c == '\\') {
+ sb.append('\\');
+ } else {
+ n++; // skip 'u'
+ sb.append((char) Integer.parseInt(
+ val.substring(n, n + 4), 16));
+ n += 3;
+ }
+ } else {
+ sb.append(c);
+ }
+ n++;
+ }
+
+ } catch (RuntimeException ex) {
+ throw new SAXException(ex);
+ }
+ return sb.toString();
+ }
+
+ protected final Label getLabel(final Object label) {
+ Label lbl = labels.get(label);
+ if (lbl == null) {
+ lbl = new Label();
+ labels.put(label, lbl);
+ }
+ return lbl;
+ }
+
+ // TODO verify move to stack
+ protected final MethodVisitor getCodeVisitor() {
+ return (MethodVisitor) peek();
+ }
+
+ protected final int getAccess(final String s) {
+ int access = 0;
+ if (s.indexOf("public") != -1) {
+ access |= ACC_PUBLIC;
+ }
+ if (s.indexOf("private") != -1) {
+ access |= ACC_PRIVATE;
+ }
+ if (s.indexOf("protected") != -1) {
+ access |= ACC_PROTECTED;
+ }
+ if (s.indexOf("static") != -1) {
+ access |= ACC_STATIC;
+ }
+ if (s.indexOf("final") != -1) {
+ access |= ACC_FINAL;
+ }
+ if (s.indexOf("super") != -1) {
+ access |= ACC_SUPER;
+ }
+ if (s.indexOf("synchronized") != -1) {
+ access |= ACC_SYNCHRONIZED;
+ }
+ if (s.indexOf("volatile") != -1) {
+ access |= ACC_VOLATILE;
+ }
+ if (s.indexOf("bridge") != -1) {
+ access |= ACC_BRIDGE;
+ }
+ if (s.indexOf("varargs") != -1) {
+ access |= ACC_VARARGS;
+ }
+ if (s.indexOf("transient") != -1) {
+ access |= ACC_TRANSIENT;
+ }
+ if (s.indexOf("native") != -1) {
+ access |= ACC_NATIVE;
+ }
+ if (s.indexOf("interface") != -1) {
+ access |= ACC_INTERFACE;
+ }
+ if (s.indexOf("abstract") != -1) {
+ access |= ACC_ABSTRACT;
+ }
+ if (s.indexOf("strict") != -1) {
+ access |= ACC_STRICT;
+ }
+ if (s.indexOf("synthetic") != -1) {
+ access |= ACC_SYNTHETIC;
+ }
+ if (s.indexOf("annotation") != -1) {
+ access |= ACC_ANNOTATION;
+ }
+ if (s.indexOf("enum") != -1) {
+ access |= ACC_ENUM;
+ }
+ if (s.indexOf("deprecated") != -1) {
+ access |= ACC_DEPRECATED;
+ }
+ if (s.indexOf("mandated") != -1) {
+ access |= ACC_MANDATED;
+ }
+ return access;
+ }
+ }
+
+ /**
+ * ClassRule
+ */
+ final class ClassRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int major = Integer.parseInt(attrs.getValue("major"));
+ int minor = Integer.parseInt(attrs.getValue("minor"));
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("version", new Integer(minor << 16 | major));
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("parent", attrs.getValue("parent"));
+ vals.put("source", attrs.getValue("source"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("interfaces", new ArrayList<String>());
+ push(vals);
+ // values will be extracted in InterfacesRule.end();
+ }
+ }
+
+ final class SourceRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String file = attrs.getValue("file");
+ String debug = attrs.getValue("debug");
+ cv.visitSource(file, debug);
+ }
+ }
+
+ /**
+ * InterfaceRule
+ */
+ final class InterfaceRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("interfaces"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * InterfacesRule
+ */
+ final class InterfacesRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int version = ((Integer) vals.get("version")).intValue();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String signature = (String) vals.get("signature");
+ String parent = (String) vals.get("parent");
+ ArrayList<?> infs = (ArrayList<?>) vals.get("interfaces");
+ String[] interfaces = infs.toArray(new String[infs.size()]);
+ cv.visit(version, access, name, signature, parent, interfaces);
+ push(cv);
+ }
+ }
+
+ /**
+ * OuterClassRule
+ */
+ final class OuterClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String owner = attrs.getValue("owner");
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ /**
+ * InnerClassRule
+ */
+ final class InnerClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String outerName = attrs.getValue("outerName");
+ String innerName = attrs.getValue("innerName");
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ /**
+ * FieldRule
+ */
+ final class FieldRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String signature = attrs.getValue("signature");
+ String desc = attrs.getValue("desc");
+ Object value = getValue(desc, attrs.getValue("value"));
+ push(cv.visitField(access, name, desc, signature, value));
+ }
+
+ @Override
+ public void end(final String name) {
+ ((FieldVisitor) pop()).visitEnd();
+ }
+ }
+
+ /**
+ * MethodRule
+ */
+ final class MethodRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ labels = new HashMap<Object, Label>();
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("desc", attrs.getValue("desc"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("exceptions", new ArrayList<String>());
+ push(vals);
+ // values will be extracted in ExceptionsRule.end();
+ }
+
+ @Override
+ public final void end(final String name) {
+ ((MethodVisitor) pop()).visitEnd();
+ labels = null;
+ }
+ }
+
+ /**
+ * ExceptionRule
+ */
+ final class ExceptionRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("exceptions"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * ExceptionsRule
+ */
+ final class ExceptionsRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String desc = (String) vals.get("desc");
+ String signature = (String) vals.get("signature");
+ ArrayList<?> excs = (ArrayList<?>) vals.get("exceptions");
+ String[] exceptions = excs.toArray(new String[excs.size()]);
+
+ push(cv.visitMethod(access, name, desc, signature, exceptions));
+ }
+ }
+
+ /**
+ * MethodParameterRule
+ */
+ final class MethodParameterRule extends Rule {
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ String name = attrs.getValue("name");
+ int access = getAccess(attrs.getValue("access"));
+ getCodeVisitor().visitParameter(name, access);
+ }
+ }
+
+ /**
+ * TableSwitchRule
+ */
+ final class TableSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("min", attrs.getValue("min"));
+ vals.put("max", attrs.getValue("max"));
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList<String>());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int min = Integer.parseInt((String) vals.get("min"));
+ int max = Integer.parseInt((String) vals.get("max"));
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * TableSwitchLabelRule
+ */
+ final class TableSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<Label>) ((HashMap<?, ?>) peek()).get("labels"))
+ .add(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * LookupSwitchRule
+ */
+ final class LookupSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList<Label>());
+ vals.put("keys", new ArrayList<String>());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList<String> keyList = (ArrayList<String>) vals.get("keys");
+ ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ int[] keys = new int[keyList.size()];
+ for (int i = 0; i < keys.length; i++) {
+ keys[i] = Integer.parseInt(keyList.get(i));
+ }
+ getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * LookupSwitchLabelRule
+ */
+ final class LookupSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) peek();
+ ((ArrayList<Label>) vals.get("labels")).add(getLabel(attrs
+ .getValue("name")));
+ ((ArrayList<String>) vals.get("keys")).add(attrs.getValue("key"));
+ }
+ }
+
+ /**
+ * FrameRule
+ */
+ final class FrameRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> typeLists = new HashMap<String, Object>();
+ typeLists.put("local", new ArrayList<Object>());
+ typeLists.put("stack", new ArrayList<Object>());
+ push(attrs.getValue("type"));
+ push(attrs.getValue("count") == null ? "0" : attrs
+ .getValue("count"));
+ push(typeLists);
+ }
+
+ @Override
+ public void end(final String name) {
+ HashMap<?, ?> typeLists = (HashMap<?, ?>) pop();
+ ArrayList<?> locals = (ArrayList<?>) typeLists.get("local");
+ int nLocal = locals.size();
+ Object[] local = locals.toArray();
+ ArrayList<?> stacks = (ArrayList<?>) typeLists.get("stack");
+ int nStack = stacks.size();
+ Object[] stack = stacks.toArray();
+ String count = (String) pop();
+ String type = (String) pop();
+ if ("NEW".equals(type)) {
+ getCodeVisitor()
+ .visitFrame(F_NEW, nLocal, local, nStack, stack);
+ } else if ("FULL".equals(type)) {
+ getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
+ stack);
+ } else if ("APPEND".equals(type)) {
+ getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
+ } else if ("CHOP".equals(type)) {
+ getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
+ null, 0, null);
+ } else if ("SAME".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
+ } else if ("SAME1".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
+ }
+ }
+ }
+
+ final class FrameTypeRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ ArrayList<Object> types = (ArrayList<Object>) ((HashMap<?, ?>) peek())
+ .get(name);
+ String type = attrs.getValue("type");
+ if ("uninitialized".equals(type)) {
+ types.add(getLabel(attrs.getValue("label")));
+ } else {
+ Integer t = TYPES.get(type);
+ if (t == null) {
+ types.add(type);
+ } else {
+ types.add(t);
+ }
+ }
+ }
+ }
+
+ /**
+ * LabelRule
+ */
+ final class LabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * TryCatchRule
+ */
+ final class TryCatchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ Label handler = getLabel(attrs.getValue("handler"));
+ String type = attrs.getValue("type");
+ getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * LineNumberRule
+ */
+ final class LineNumberRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int line = Integer.parseInt(attrs.getValue("line"));
+ Label start = getLabel(attrs.getValue("start"));
+ getCodeVisitor().visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * LocalVarRule
+ */
+ final class LocalVarRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ String signature = attrs.getValue("signature");
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ int var = Integer.parseInt(attrs.getValue("var"));
+ getCodeVisitor().visitLocalVariable(name, desc, signature, start,
+ end, var);
+ }
+ }
+
+ /**
+ * InvokeDynamicRule
+ */
+ final class InvokeDynamicRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ push(attrs.getValue("name"));
+ push(attrs.getValue("desc"));
+ push(decodeHandle(attrs.getValue("bsm")));
+ push(new ArrayList<Object>());
+ }
+
+ @Override
+ public final void end(final String element) {
+ ArrayList<?> bsmArgs = (ArrayList<?>) pop();
+ Handle bsm = (Handle) pop();
+ String desc = (String) pop();
+ String name = (String) pop();
+ getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
+ bsmArgs.toArray());
+ }
+ }
+
+ /**
+ * InvokeDynamicBsmArgumentsRule
+ */
+ final class InvokeDynamicBsmArgumentsRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ ArrayList<Object> bsmArgs = (ArrayList<Object>) peek();
+ bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
+ }
+ }
+
+ /**
+ * OpcodesRule
+ */
+ final class OpcodesRule extends Rule {
+
+ // public boolean match( String match, String element) {
+ // return match.startsWith( path) && OPCODES.containsKey( element);
+ // }
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ Opcode o = OPCODES.get(element);
+ if (o == null) {
+ throw new SAXException("Invalid element: " + element + " at "
+ + match);
+ }
+
+ switch (o.type) {
+ case OpcodeGroup.INSN:
+ getCodeVisitor().visitInsn(o.opcode);
+ break;
+
+ case OpcodeGroup.INSN_FIELD:
+ getCodeVisitor().visitFieldInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_INT:
+ getCodeVisitor().visitIntInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("value")));
+ break;
+
+ case OpcodeGroup.INSN_JUMP:
+ getCodeVisitor().visitJumpInsn(o.opcode,
+ getLabel(attrs.getValue("label")));
+ break;
+
+ case OpcodeGroup.INSN_METHOD:
+ getCodeVisitor().visitMethodInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"),
+ attrs.getValue("itf").equals("true"));
+ break;
+
+ case OpcodeGroup.INSN_TYPE:
+ getCodeVisitor()
+ .visitTypeInsn(o.opcode, attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_VAR:
+ getCodeVisitor().visitVarInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("var")));
+ break;
+
+ case OpcodeGroup.INSN_IINC:
+ getCodeVisitor().visitIincInsn(
+ Integer.parseInt(attrs.getValue("var")),
+ Integer.parseInt(attrs.getValue("inc")));
+ break;
+
+ case OpcodeGroup.INSN_LDC:
+ getCodeVisitor()
+ .visitLdcInsn(
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("cst")));
+ break;
+
+ case OpcodeGroup.INSN_MULTIANEWARRAY:
+ getCodeVisitor().visitMultiANewArrayInsn(
+ attrs.getValue("desc"),
+ Integer.parseInt(attrs.getValue("dims")));
+ break;
+
+ default:
+ throw new Error("Internal error");
+
+ }
+ }
+ }
+
+ /**
+ * MaxRule
+ */
+ final class MaxRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
+ int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
+ getCodeVisitor().visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ final class AnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ Object v = peek();
+ if (v instanceof ClassVisitor) {
+ push(((ClassVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof FieldVisitor) {
+ push(((FieldVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof MethodVisitor) {
+ push(((MethodVisitor) v).visitAnnotation(desc, visible));
+ }
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class TypeAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+
+ Object v = peek();
+ if (v instanceof ClassVisitor) {
+ push(((ClassVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ } else if (v instanceof FieldVisitor) {
+ push(((FieldVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ } else if (v instanceof MethodVisitor) {
+ push(((MethodVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ }
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationParameterRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ int parameter = Integer.parseInt(attrs.getValue("parameter"));
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
+ desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class InsnAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ push(((MethodVisitor) peek()).visitInsnAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class TryCatchAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ push(((MethodVisitor) peek()).visitTryCatchAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class LocalVariableAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ String[] s = attrs.getValue("start").split(" ");
+ Label[] start = new Label[s.length];
+ for (int i = 0; i < start.length; ++i) {
+ start[i] = getLabel(s[i]);
+ }
+ String[] e = attrs.getValue("end").split(" ");
+ Label[] end = new Label[e.length];
+ for (int i = 0; i < end.length; ++i) {
+ end[i] = getLabel(e[i]);
+ }
+ String[] v = attrs.getValue("index").split(" ");
+ int[] index = new int[v.length];
+ for (int i = 0; i < index.length; ++i) {
+ index[i] = Integer.parseInt(v[i]);
+ }
+ push(((MethodVisitor) peek()).visitLocalVariableAnnotation(typeRef,
+ typePath, start, end, index, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs)
+ throws SAXException {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visit(
+ attrs.getValue("name"),
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("value")));
+ }
+ }
+ }
+
+ final class AnnotationValueEnumRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
+ attrs.getValue("value"));
+ }
+ }
+ }
+
+ final class AnnotationValueAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
+ attrs.getValue("desc")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueArrayRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitArray(attrs.getValue("name")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationDefaultRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ MethodVisitor av = (MethodVisitor) peek();
+ push(av == null ? null : av.visitAnnotationDefault());
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ /**
+ * Opcode
+ */
+ static final class Opcode {
+
+ public final int opcode;
+
+ public final int type;
+
+ Opcode(final int opcode, final int type) {
+ this.opcode = opcode;
+ this.type = type;
+ }
+ }
+}
[11/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
new file mode 100644
index 0000000..ecf580f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
@@ -0,0 +1,62 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/Frame/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.typeCount=-
+org/objectweb/asm/ClassWriter.typeTable=-
+
+org/objectweb/asm/Label.frame=-
+
+org/objectweb/asm/MethodWriter.frameCount=-
+org/objectweb/asm/MethodWriter.stackMap=-
+org/objectweb/asm/MethodWriter.previousFrameOffset=-
+org/objectweb/asm/MethodWriter.previousFrame=-
+org/objectweb/asm/MethodWriter.frameIndex=-
+org/objectweb/asm/MethodWriter.frame=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=-
+
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=-
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=-
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=-
+org/objectweb/asm/ClassWriter.getMergedType(II)I=-
+
+org/objectweb/asm/MethodWriter.startFrame(III)V=-
+org/objectweb/asm/MethodWriter.endFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=-
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
new file mode 100644
index 0000000..97f7e34
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
@@ -0,0 +1,37 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+# field mappings
+
+# method mappings
+
+org/objectweb/asm/MethodWriter.resizeInstructions()V=-
\ 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/optimizer/shrink-signatures.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
new file mode 100644
index 0000000..6a48623
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
@@ -0,0 +1,43 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/signature/SignatureReader/remove=true
+org/objectweb/asm/signature/SignatureVisitor/remove=true
+org/objectweb/asm/signature/SignatureWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.signature=-
+
+org/objectweb/asm/FieldWriter.signature=-
+
+org/objectweb/asm/MethodWriter.signature=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
new file mode 100644
index 0000000..1c83ca2
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
@@ -0,0 +1,66 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+org/objectweb/asm/ByteVector/remove=true
+org/objectweb/asm/ClassWriter/remove=true
+org/objectweb/asm/Edge/remove=true
+org/objectweb/asm/FieldWriter/remove=true
+org/objectweb/asm/Frame/remove=true
+org/objectweb/asm/Handler/remove=true
+org/objectweb/asm/Item/remove=true
+org/objectweb/asm/MethodWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/Label.position=-
+org/objectweb/asm/Label.referenceCount=-
+org/objectweb/asm/Label.srcAndRefPositions=-
+org/objectweb/asm/Label.inputStackTop=-
+org/objectweb/asm/Label.outputStackMax=-
+org/objectweb/asm/Label.frame=-
+org/objectweb/asm/Label.successor=-
+org/objectweb/asm/Label.successors=-
+org/objectweb/asm/Label.next=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=-
+
+org/objectweb/asm/Label.addReference(II)V=-
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=-
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=-
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=-
+org/objectweb/asm/Label.inSubroutine(J)Z=-
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=-
+org/objectweb/asm/Label.addToSubroutine(JI)V=-
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
new file mode 100644
index 0000000..6b2a41f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
@@ -0,0 +1,380 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+#org/objectweb/asm/Edge=org/objectweb/asm/a
+#org/objectweb/asm/Item=org/objectweb/asm/b
+#org/objectweb/asm/FieldWriter=org/objectweb/asm/c
+#org/objectweb/asm/MethodWriter=org/objectweb/asm/d
+#org/objectweb/asm/AnnotationWriter=org/objectweb/asm/e
+#org/objectweb/asm/Context=org/objectweb/asm/f
+
+java/lang/StringBuilder=java/lang/StringBuffer
+
+
+# field mappings
+
+org/objectweb/asm/AnnotationWriter.cw=a
+org/objectweb/asm/AnnotationWriter.size=b
+org/objectweb/asm/AnnotationWriter.named=c
+org/objectweb/asm/AnnotationWriter.bv=d
+org/objectweb/asm/AnnotationWriter.parent=e
+org/objectweb/asm/AnnotationWriter.offset=f
+org/objectweb/asm/AnnotationWriter.next=g
+org/objectweb/asm/AnnotationWriter.prev=h
+
+org/objectweb/asm/Attribute.next=a
+org/objectweb/asm/Attribute.value=b
+
+org/objectweb/asm/ByteVector.data=a
+org/objectweb/asm/ByteVector.length=b
+
+org/objectweb/asm/ClassReader.items=a
+org/objectweb/asm/ClassReader.strings=c
+org/objectweb/asm/ClassReader.maxStringLength=d
+#org/objectweb/asm/ClassReader.header=e
+
+org/objectweb/asm/Context.attrs=a
+org/objectweb/asm/Context.flags=b
+org/objectweb/asm/Context.buffer=c
+org/objectweb/asm/Context.bootstrapMethods=d
+org/objectweb/asm/Context.access=e
+org/objectweb/asm/Context.name=f
+org/objectweb/asm/Context.desc=g
+org/objectweb/asm/Context.labels=h
+org/objectweb/asm/Context.typeRef=i
+org/objectweb/asm/Context.typePath=j
+org/objectweb/asm/Context.offset=k
+org/objectweb/asm/Context.start=l
+org/objectweb/asm/Context.end=m
+org/objectweb/asm/Context.index=n
+org/objectweb/asm/Context.offset=o
+org/objectweb/asm/Context.mode=p
+org/objectweb/asm/Context.localCount=q
+org/objectweb/asm/Context.localDiff=r
+org/objectweb/asm/Context.local=s
+org/objectweb/asm/Context.stackCount=t
+org/objectweb/asm/Context.stack=u
+
+org/objectweb/asm/ClassWriter.TYPE=a
+org/objectweb/asm/ClassWriter.version=b
+org/objectweb/asm/ClassWriter.index=c
+org/objectweb/asm/ClassWriter.pool=d
+org/objectweb/asm/ClassWriter.items=e
+org/objectweb/asm/ClassWriter.threshold=f
+org/objectweb/asm/ClassWriter.key=g
+org/objectweb/asm/ClassWriter.key2=h
+org/objectweb/asm/ClassWriter.key3=i
+org/objectweb/asm/ClassWriter.key4=j
+org/objectweb/asm/ClassWriter.access=k
+org/objectweb/asm/ClassWriter.name=l
+org/objectweb/asm/ClassWriter.signature=m
+org/objectweb/asm/ClassWriter.superName=n
+org/objectweb/asm/ClassWriter.interfaceCount=o
+org/objectweb/asm/ClassWriter.interfaces=p
+org/objectweb/asm/ClassWriter.sourceFile=q
+org/objectweb/asm/ClassWriter.sourceDebug=r
+org/objectweb/asm/ClassWriter.enclosingMethodOwner=s
+org/objectweb/asm/ClassWriter.enclosingMethod=t
+org/objectweb/asm/ClassWriter.anns=u
+org/objectweb/asm/ClassWriter.ianns=v
+org/objectweb/asm/ClassWriter.tanns=N
+org/objectweb/asm/ClassWriter.itanns=O
+org/objectweb/asm/ClassWriter.attrs=w
+org/objectweb/asm/ClassWriter.innerClassesCount=x
+org/objectweb/asm/ClassWriter.innerClasses=y
+org/objectweb/asm/ClassWriter.bootstrapMethodsCount=z
+org/objectweb/asm/ClassWriter.bootstrapMethods=A
+org/objectweb/asm/ClassWriter.firstField=B
+org/objectweb/asm/ClassWriter.lastField=C
+org/objectweb/asm/ClassWriter.firstMethod=D
+org/objectweb/asm/ClassWriter.lastMethod=E
+org/objectweb/asm/ClassWriter.computeMaxs=F
+org/objectweb/asm/ClassWriter.typeCount=G
+org/objectweb/asm/ClassWriter.typeTable=H
+org/objectweb/asm/ClassWriter.thisName=I
+org/objectweb/asm/ClassWriter.computeFrames=J
+org/objectweb/asm/ClassWriter.computeMaxs=K
+org/objectweb/asm/ClassWriter.invalidFrames=L
+org/objectweb/asm/ClassWriter.cr=M
+
+org/objectweb/asm/Edge.info=a
+org/objectweb/asm/Edge.successor=b
+org/objectweb/asm/Edge.next=c
+
+org/objectweb/asm/Handler.start=a
+org/objectweb/asm/Handler.end=b
+org/objectweb/asm/Handler.handler=c
+org/objectweb/asm/Handler.desc=d
+org/objectweb/asm/Handler.type=e
+org/objectweb/asm/Handler.next=f
+
+org/objectweb/asm/FieldWriter.cw=b
+org/objectweb/asm/FieldWriter.access=c
+org/objectweb/asm/FieldWriter.name=d
+org/objectweb/asm/FieldWriter.desc=e
+org/objectweb/asm/FieldWriter.signature=f
+org/objectweb/asm/FieldWriter.value=g
+org/objectweb/asm/FieldWriter.anns=h
+org/objectweb/asm/FieldWriter.ianns=i
+org/objectweb/asm/FieldWriter.tanns=k
+org/objectweb/asm/FieldWriter.itanns=l
+org/objectweb/asm/FieldWriter.attrs=j
+
+org/objectweb/asm/Item.index=a
+org/objectweb/asm/Item.type=b
+org/objectweb/asm/Item.intVal=c
+org/objectweb/asm/Item.longVal=d
+org/objectweb/asm/Item.strVal1=g
+org/objectweb/asm/Item.strVal2=h
+org/objectweb/asm/Item.strVal3=i
+org/objectweb/asm/Item.hashCode=j
+org/objectweb/asm/Item.next=k
+
+org/objectweb/asm/Label.status=a
+org/objectweb/asm/Label.line=b
+org/objectweb/asm/Label.position=c
+org/objectweb/asm/Label.referenceCount=d
+org/objectweb/asm/Label.srcAndRefPositions=e
+org/objectweb/asm/Label.inputStackTop=f
+org/objectweb/asm/Label.outputStackMax=g
+org/objectweb/asm/Label.frame=h
+org/objectweb/asm/Label.successor=i
+org/objectweb/asm/Label.successors=j
+org/objectweb/asm/Label.next=k
+
+org/objectweb/asm/Frame.SIZE=a
+org/objectweb/asm/Frame.owner=b
+org/objectweb/asm/Frame.inputLocals=c
+org/objectweb/asm/Frame.inputStack=d
+org/objectweb/asm/Frame.outputLocals=e
+org/objectweb/asm/Frame.outputStack=f
+org/objectweb/asm/Frame.outputStackTop=g
+org/objectweb/asm/Frame.initializationCount=h
+org/objectweb/asm/Frame.initializations=i
+
+org/objectweb/asm/MethodWriter.cw=b
+org/objectweb/asm/MethodWriter.access=c
+org/objectweb/asm/MethodWriter.name=d
+org/objectweb/asm/MethodWriter.desc=e
+org/objectweb/asm/MethodWriter.descriptor=f
+org/objectweb/asm/MethodWriter.signature=g
+org/objectweb/asm/MethodWriter.classReaderOffset=h
+org/objectweb/asm/MethodWriter.classReaderLength=i
+org/objectweb/asm/MethodWriter.exceptionCount=j
+org/objectweb/asm/MethodWriter.exceptions=k
+org/objectweb/asm/MethodWriter.annd=l
+org/objectweb/asm/MethodWriter.anns=m
+org/objectweb/asm/MethodWriter.ianns=n
+org/objectweb/asm/MethodWriter.tanns=U
+org/objectweb/asm/MethodWriter.itanns=V
+org/objectweb/asm/MethodWriter.panns=o
+org/objectweb/asm/MethodWriter.ipanns=p
+org/objectweb/asm/MethodWriter.attrs=q
+org/objectweb/asm/MethodWriter.code=r
+org/objectweb/asm/MethodWriter.maxStack=s
+org/objectweb/asm/MethodWriter.maxLocals=t
+org/objectweb/asm/MethodWriter.currentLocals=T
+org/objectweb/asm/MethodWriter.frameCount=u
+org/objectweb/asm/MethodWriter.stackMap=v
+org/objectweb/asm/MethodWriter.previousFrameOffset=w
+org/objectweb/asm/MethodWriter.previousFrame=x
+#org/objectweb/asm/MethodWriter.frameIndex=y
+org/objectweb/asm/MethodWriter.frame=z
+org/objectweb/asm/MethodWriter.handlerCount=A
+org/objectweb/asm/MethodWriter.firstHandler=B
+org/objectweb/asm/MethodWriter.lastHandler=C
+org/objectweb/asm/MethodWriter.methodParametersCount=Z
+org/objectweb/asm/MethodWriter.methodParameters=$
+org/objectweb/asm/MethodWriter.localVarCount=D
+org/objectweb/asm/MethodWriter.localVar=E
+org/objectweb/asm/MethodWriter.localVarTypeCount=F
+org/objectweb/asm/MethodWriter.localVarType=G
+org/objectweb/asm/MethodWriter.lineNumberCount=H
+org/objectweb/asm/MethodWriter.lineNumber=I
+org/objectweb/asm/MethodWriter.lastCodeOffset=Y
+org/objectweb/asm/MethodWriter.ctanns=W
+org/objectweb/asm/MethodWriter.ictanns=X
+org/objectweb/asm/MethodWriter.cattrs=J
+org/objectweb/asm/MethodWriter.resize=K
+org/objectweb/asm/MethodWriter.subroutines=L
+org/objectweb/asm/MethodWriter.compute=M
+org/objectweb/asm/MethodWriter.labels=N
+org/objectweb/asm/MethodWriter.previousBlock=O
+org/objectweb/asm/MethodWriter.currentBlock=P
+org/objectweb/asm/MethodWriter.stackSize=Q
+org/objectweb/asm/MethodWriter.maxStackSize=R
+org/objectweb/asm/MethodWriter.synthetics=S
+
+org/objectweb/asm/Type.sort=a
+org/objectweb/asm/Type.buf=b
+org/objectweb/asm/Type.off=c
+org/objectweb/asm/Type.len=d
+
+org/objectweb/asm/TypeReference.value=a
+
+org/objectweb/asm/TypePath.b=a
+org/objectweb/asm/TypePath.offset=b
+
+org/objectweb/asm/Handle.tag=a
+org/objectweb/asm/Handle.owner=b
+org/objectweb/asm/Handle.name=c
+org/objectweb/asm/Handle.desc=d
+
+org/objectweb/asm/signature/SignatureReader.signature=a
+
+org/objectweb/asm/signature/SignatureWriter.buf=a
+org/objectweb/asm/signature/SignatureWriter.hasFormals=b
+org/objectweb/asm/signature/SignatureWriter.hasParameters=c
+org/objectweb/asm/signature/SignatureWriter.argumentStack=d
+
+# method mappings
+
+org/objectweb/asm/AnnotationWriter.getSize()I=a
+org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;ILorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.putTarget(ILorg/objectweb/asm/TypePath;Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Attribute.getCount()I=a
+org/objectweb/asm/Attribute.getSize(Lorg/objectweb/asm/ClassWriter;[BIII)I=a
+org/objectweb/asm/Attribute.put(Lorg/objectweb/asm/ClassWriter;[BIIILorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/ByteVector.enlarge(I)V=a
+org/objectweb/asm/ByteVector.put11(II)Lorg/objectweb/asm/ByteVector;=a
+org/objectweb/asm/ByteVector.put12(II)Lorg/objectweb/asm/ByteVector;=b
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=a
+org/objectweb/asm/ClassReader.copyBootstrapMethods(Lorg/objectweb/asm/ClassWriter;[Lorg/objectweb/asm/Item;[C)V=a
+org/objectweb/asm/ClassReader.readField(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readMethod(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=b
+org/objectweb/asm/ClassReader.readCode(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;I)V=a
+org/objectweb/asm/ClassReader.readTypeAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)[I=a
+org/objectweb/asm/ClassReader.readAnnotationTarget(Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.getAttributes()I=a
+org/objectweb/asm/ClassReader.readAttribute([Lorg/objectweb/asm/Attribute;Ljava/lang/String;II[CI[Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Attribute;=a
+org/objectweb/asm/ClassReader.readClass(Ljava/io/InputStream;Z)[B=a
+org/objectweb/asm/ClassReader.readParameterAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)V=b
+org/objectweb/asm/ClassReader.readUTF(II[C)Ljava/lang/String;=a
+org/objectweb/asm/ClassReader.getImplicitFrame(Lorg/objectweb/asm/Context;)V=a
+org/objectweb/asm/ClassReader.readFrame(IZZLorg/objectweb/asm/Context;)I=a
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=a
+
+org/objectweb/asm/ClassWriter.get(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newClassItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newConstItem(Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newDouble(D)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newFloat(F)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInteger(I)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newLong(J)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newString(Ljava/lang/String;)Lorg/objectweb/asm/Item;=b
+org/objectweb/asm/ClassWriter.put122(III)V=a
+org/objectweb/asm/ClassWriter.put112(III)V=b
+org/objectweb/asm/ClassWriter.put(Lorg/objectweb/asm/Item;)V=b
+org/objectweb/asm/ClassWriter.newFieldItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=c
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=a
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.getMergedType(II)I=a
+org/objectweb/asm/ClassWriter.newNameTypeItem(Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodTypeItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.newHandleItem(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInvokeDynamicItem(Ljava/lang/String;Ljava/lang/String;Lorg/objectweb/asm/Handle;[Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+
+org/objectweb/asm/FieldWriter.getSize()I=a
+org/objectweb/asm/FieldWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Item.isEqualTo(Lorg/objectweb/asm/Item;)Z=a
+org/objectweb/asm/Item.set(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V=a
+org/objectweb/asm/Item.set(D)V=a
+org/objectweb/asm/Item.set(F)V=a
+org/objectweb/asm/Item.set(I)V=a
+org/objectweb/asm/Item.set(J)V=a
+org/objectweb/asm/Item.set(Ljava/lang/String;Ljava/lang/String;I)V=a
+org/objectweb/asm/Item.set(II)V=a
+
+org/objectweb/asm/Label.addReference(II)V=a
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=a
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=a
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=a
+org/objectweb/asm/Label.inSubroutine(J)Z=a
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=a
+org/objectweb/asm/Label.addToSubroutine(JI)V=a
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=b
+
+org/objectweb/asm/Frame.get(I)I=a
+org/objectweb/asm/Frame.set(II)V=a
+org/objectweb/asm/Frame.push(I)V=b
+org/objectweb/asm/Frame.push(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.type(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)I=b
+org/objectweb/asm/Frame.pop()I=a
+org/objectweb/asm/Frame.pop(Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.pop(I)V=c
+org/objectweb/asm/Frame.init(I)V=d
+org/objectweb/asm/Frame.init(Lorg/objectweb/asm/ClassWriter;I)I=a
+org/objectweb/asm/Frame.initInputFrame(Lorg/objectweb/asm/ClassWriter;I[Lorg/objectweb/asm/Type;I)V=a
+org/objectweb/asm/Frame.execute(IILorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Item;)V=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Frame;I)Z=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;I[II)Z=a
+
+org/objectweb/asm/Handler.remove(Lorg/objectweb/asm/Handler;Lorg/objectweb/asm/Label;Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Handler;=a
+
+org/objectweb/asm/MethodWriter.visitSwitchInsn(Lorg/objectweb/asm/Label;[Lorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.addSuccessor(ILorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[III)I=a
+org/objectweb/asm/MethodWriter.getSize()I=a
+org/objectweb/asm/MethodWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/MethodWriter.readInt([BI)I=a
+org/objectweb/asm/MethodWriter.readShort([BI)S=b
+org/objectweb/asm/MethodWriter.readUnsignedShort([BI)I=c
+org/objectweb/asm/MethodWriter.writeShort([BII)V=a
+org/objectweb/asm/MethodWriter.visitFrame(Lorg/objectweb/asm/Frame;)V=b
+org/objectweb/asm/MethodWriter.visitImplicitFirstFrame()V=f
+org/objectweb/asm/MethodWriter.startFrame(III)I=a
+org/objectweb/asm/MethodWriter.endFrame()V=b
+org/objectweb/asm/MethodWriter.writeFrame()V=c
+org/objectweb/asm/MethodWriter.resizeInstructions()V=d
+org/objectweb/asm/MethodWriter.noSuccessor()V=e
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=a
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[ILorg/objectweb/asm/Label;)V=a
+
+org/objectweb/asm/Type.getType([CI)Lorg/objectweb/asm/Type;=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;)V=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;Ljava/lang/Class;)V=a
+
+org/objectweb/asm/signature/SignatureReader.parseType(Ljava/lang/String;ILorg/objectweb/asm/signature/SignatureVisitor;)I=a
+
+org/objectweb/asm/signature/SignatureWriter.endFormals()V=a
+org/objectweb/asm/signature/SignatureWriter.endArguments()V=b
+
\ 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/signature/SignatureReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
index b72fde6..b5b2c45 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm.signature;
/**
* A type signature parser to make a signature visitor visit an existing
* signature.
- *
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -45,9 +45,10 @@ public class SignatureReader {
/**
* Constructs a {@link SignatureReader} for the given signature.
- *
- * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
- * or <i>FieldTypeSignature</i>.
+ *
+ * @param signature
+ * A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
+ * <i>FieldTypeSignature</i>.
*/
public SignatureReader(final String signature) {
this.signature = signature;
@@ -58,15 +59,15 @@ public class SignatureReader {
* {@link SignatureReader}. This signature is the one specified in the
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
* method is intended to be called on a {@link SignatureReader} that was
- * created using a <i>ClassSignature</i> (such as the
+ * created using a <i>ClassSignature</i> (such as the <code>signature</code>
+ * parameter of the {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit
+ * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
* <code>signature</code> parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit ClassVisitor.visit} method)
- * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
- * parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
- * method).
- *
- * @param v the visitor that must visit this signature.
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod
+ * ClassVisitor.visitMethod} method).
+ *
+ * @param v
+ * the visitor that must visit this signature.
*/
public void accept(final SignatureVisitor v) {
String signature = this.signature;
@@ -118,12 +119,12 @@ public class SignatureReader {
* method is intended to be called on a {@link SignatureReader} that was
* created using a <i>FieldTypeSignature</i>, such as the
* <code>signature</code> parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField
- * ClassVisitor.visitField} or {@link
- * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField ClassVisitor.visitField}
+ * or {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
* MethodVisitor.visitLocalVariable} methods.
- *
- * @param v the visitor that must visit this signature.
+ *
+ * @param v
+ * the visitor that must visit this signature.
*/
public void acceptType(final SignatureVisitor v) {
parseType(this.signature, 0, v);
@@ -131,99 +132,97 @@ public class SignatureReader {
/**
* Parses a field type signature and makes the given visitor visit it.
- *
- * @param signature a string containing the signature that must be parsed.
- * @param pos index of the first character of the signature to parsed.
- * @param v the visitor that must visit this signature.
+ *
+ * @param signature
+ * a string containing the signature that must be parsed.
+ * @param pos
+ * index of the first character of the signature to parsed.
+ * @param v
+ * the visitor that must visit this signature.
* @return the index of the first character after the parsed signature.
*/
- private static int parseType(
- final String signature,
- int pos,
- final SignatureVisitor v)
- {
+ private static int parseType(final String signature, int pos,
+ final SignatureVisitor v) {
char c;
int start, end;
boolean visited, inner;
String name;
switch (c = signature.charAt(pos++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- case 'F':
- case 'J':
- case 'D':
- case 'V':
- v.visitBaseType(c);
- return pos;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'V':
+ v.visitBaseType(c);
+ return pos;
- case '[':
- return parseType(signature, pos, v.visitArrayType());
+ case '[':
+ return parseType(signature, pos, v.visitArrayType());
- case 'T':
- end = signature.indexOf(';', pos);
- v.visitTypeVariable(signature.substring(pos, end));
- return end + 1;
+ case 'T':
+ end = signature.indexOf(';', pos);
+ v.visitTypeVariable(signature.substring(pos, end));
+ return end + 1;
- default: // case 'L':
- start = pos;
- visited = false;
- inner = false;
- for (;;) {
- switch (c = signature.charAt(pos++)) {
- case '.':
- case ';':
- if (!visited) {
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- }
- if (c == ';') {
- v.visitEnd();
- return pos;
- }
- start = pos;
- visited = false;
- inner = true;
- break;
+ default: // case 'L':
+ start = pos;
+ visited = false;
+ inner = false;
+ for (;;) {
+ switch (c = signature.charAt(pos++)) {
+ case '.':
+ case ';':
+ if (!visited) {
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ }
+ if (c == ';') {
+ v.visitEnd();
+ return pos;
+ }
+ start = pos;
+ visited = false;
+ inner = true;
+ break;
- case '<':
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- visited = true;
- top: for (;;) {
- switch (c = signature.charAt(pos)) {
- case '>':
- break top;
- case '*':
- ++pos;
- v.visitTypeArgument();
- break;
- case '+':
- case '-':
- pos = parseType(signature,
- pos + 1,
- v.visitTypeArgument(c));
- break;
- default:
- pos = parseType(signature,
- pos,
- v.visitTypeArgument('='));
- break;
- }
- }
+ case '<':
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ visited = true;
+ top: for (;;) {
+ switch (c = signature.charAt(pos)) {
+ case '>':
+ break top;
+ case '*':
+ ++pos;
+ v.visitTypeArgument();
+ break;
+ case '+':
+ case '-':
+ pos = parseType(signature, pos + 1,
+ v.visitTypeArgument(c));
+ break;
+ default:
+ pos = parseType(signature, pos,
+ v.visitTypeArgument('='));
+ break;
+ }
}
}
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
index 14e9ccb..941980f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
@@ -35,22 +35,22 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
* A visitor to visit a generic signature. The methods of this interface must be
* called in one of the three following orders (the last one is the only valid
* order for a {@link SignatureVisitor} that is returned by a method of this
- * interface): <ul> <li><i>ClassSignature</i> = (
- * <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
- * <tt>visitInterface</tt>* )</li>
+ * interface):
+ * <ul>
+ * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li>
* <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
- * <tt>visitReturnType</tt>
- * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
- * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
- * <tt>visitArrayType</tt> | (
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li>
+ * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
+ * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
* <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
- * <tt>visitEnd</tt> ) )</li> </ul>
- *
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
+ * ) )</li>
+ * </ul>
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -73,31 +73,36 @@ public abstract class SignatureVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
/**
* Constructs a new {@link SignatureVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public SignatureVisitor(final int api) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
this.api = api;
}
/**
* Visits a formal type parameter.
- *
- * @param name the name of the formal parameter.
+ *
+ * @param name
+ * the name of the formal parameter.
*/
public void visitFormalTypeParameter(String name) {
}
/**
* Visits the class bound of the last visited formal type parameter.
- *
+ *
* @return a non null visitor to visit the signature of the class bound.
*/
public SignatureVisitor visitClassBound() {
@@ -106,7 +111,7 @@ public abstract class SignatureVisitor {
/**
* Visits an interface bound of the last visited formal type parameter.
- *
+ *
* @return a non null visitor to visit the signature of the interface bound.
*/
public SignatureVisitor visitInterfaceBound() {
@@ -115,7 +120,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of the super class.
- *
+ *
* @return a non null visitor to visit the signature of the super class
* type.
*/
@@ -125,7 +130,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of an interface implemented by the class.
- *
+ *
* @return a non null visitor to visit the signature of the interface type.
*/
public SignatureVisitor visitInterface() {
@@ -134,7 +139,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of a method parameter.
- *
+ *
* @return a non null visitor to visit the signature of the parameter type.
*/
public SignatureVisitor visitParameterType() {
@@ -143,7 +148,7 @@ public abstract class SignatureVisitor {
/**
* Visits the return type of the method.
- *
+ *
* @return a non null visitor to visit the signature of the return type.
*/
public SignatureVisitor visitReturnType() {
@@ -152,7 +157,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of a method exception.
- *
+ *
* @return a non null visitor to visit the signature of the exception type.
*/
public SignatureVisitor visitExceptionType() {
@@ -161,24 +166,26 @@ public abstract class SignatureVisitor {
/**
* Visits a signature corresponding to a primitive type.
- *
- * @param descriptor the descriptor of the primitive type, or 'V' for
- * <tt>void</tt>.
+ *
+ * @param descriptor
+ * the descriptor of the primitive type, or 'V' for <tt>void</tt>
+ * .
*/
public void visitBaseType(char descriptor) {
}
/**
* Visits a signature corresponding to a type variable.
- *
- * @param name the name of the type variable.
+ *
+ * @param name
+ * the name of the type variable.
*/
public void visitTypeVariable(String name) {
}
/**
* Visits a signature corresponding to an array type.
- *
+ *
* @return a non null visitor to visit the signature of the array element
* type.
*/
@@ -189,16 +196,18 @@ public abstract class SignatureVisitor {
/**
* Starts the visit of a signature corresponding to a class or interface
* type.
- *
- * @param name the internal name of the class or interface.
+ *
+ * @param name
+ * the internal name of the class or interface.
*/
public void visitClassType(String name) {
}
/**
* Visits an inner class.
- *
- * @param name the local name of the inner class in its enclosing class.
+ *
+ * @param name
+ * the local name of the inner class in its enclosing class.
*/
public void visitInnerClassType(String name) {
}
@@ -212,8 +221,9 @@ public abstract class SignatureVisitor {
/**
* Visits a type argument of the last visited class or inner class type.
- *
- * @param wildcard '+', '-' or '='.
+ *
+ * @param wildcard
+ * '+', '-' or '='.
* @return a non null visitor to visit the signature of the type argument.
*/
public SignatureVisitor visitTypeArgument(char wildcard) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
index 841fdad..d1e6bac 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A signature visitor that generates signatures in string format.
- *
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -66,7 +66,7 @@ public class SignatureWriter extends SignatureVisitor {
* Constructs a new {@link SignatureWriter} object.
*/
public SignatureWriter() {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
}
// ------------------------------------------------------------------------
@@ -193,7 +193,7 @@ public class SignatureWriter extends SignatureVisitor {
/**
* Returns the signature that was built by this signature writer.
- *
+ *
* @return the signature that was built by this signature writer.
*/
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
index 32dc008..a6a01d6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
@@ -29,15 +29,16 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a bytecode instruction. <i>An instruction can appear
* at most once in at most one {@link InsnList} at a time</i>.
- *
+ *
* @author Eric Bruneton
*/
public abstract class AbstractInsnNode {
@@ -128,6 +129,28 @@ public abstract class AbstractInsnNode {
protected int opcode;
/**
+ * The runtime visible type annotations of this instruction. This field is
+ * only used for real instructions (i.e. not for labels, frames, or line
+ * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
+ * May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this instruction. This field is
+ * only used for real instructions (i.e. not for labels, frames, or line
+ * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
+ * May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* Previous instruction in the list to which this instruction belongs.
*/
AbstractInsnNode prev;
@@ -147,8 +170,9 @@ public abstract class AbstractInsnNode {
/**
* Constructs a new {@link AbstractInsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed.
*/
protected AbstractInsnNode(final int opcode) {
this.opcode = opcode;
@@ -157,7 +181,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the opcode of this instruction.
- *
+ *
* @return the opcode of this instruction.
*/
public int getOpcode() {
@@ -166,7 +190,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the type of this instruction.
- *
+ *
* @return the type of this instruction, i.e. one the constants defined in
* this class.
*/
@@ -175,7 +199,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the previous instruction in the list to which this instruction
* belongs, if any.
- *
+ *
* @return the previous instruction in the list to which this instruction
* belongs, if any. May be <tt>null</tt>.
*/
@@ -186,7 +210,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the next instruction in the list to which this instruction
* belongs, if any.
- *
+ *
* @return the next instruction in the list to which this instruction
* belongs, if any. May be <tt>null</tt>.
*/
@@ -196,43 +220,107 @@ public abstract class AbstractInsnNode {
/**
* Makes the given code visitor visit this instruction.
- *
- * @param cv a code visitor.
+ *
+ * @param cv
+ * a code visitor.
*/
public abstract void accept(final MethodVisitor cv);
/**
+ * Makes the given visitor visit the annotations of this instruction.
+ *
+ * @param mv
+ * a method visitor.
+ */
+ protected final void acceptAnnotations(final MethodVisitor mv) {
+ int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
+ }
+
+ /**
* Returns a copy of this instruction.
- *
- * @param labels a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param labels
+ * a map from LabelNodes to cloned LabelNodes.
* @return a copy of this instruction. The returned instruction does not
* belong to any {@link InsnList}.
*/
- public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels);
+ public abstract AbstractInsnNode clone(
+ final Map<LabelNode, LabelNode> labels);
/**
* Returns the clone of the given label.
- *
- * @param label a label.
- * @param map a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param label
+ * a label.
+ * @param map
+ * a map from LabelNodes to cloned LabelNodes.
* @return the clone of the given label.
*/
- static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
+ static LabelNode clone(final LabelNode label,
+ final Map<LabelNode, LabelNode> map) {
return map.get(label);
}
/**
* Returns the clones of the given labels.
- *
- * @param labels a list of labels.
- * @param map a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param labels
+ * a list of labels.
+ * @param map
+ * a map from LabelNodes to cloned LabelNodes.
* @return the clones of the given labels.
*/
- static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) {
+ static LabelNode[] clone(final List<LabelNode> labels,
+ final Map<LabelNode, LabelNode> map) {
LabelNode[] clones = new LabelNode[labels.size()];
for (int i = 0; i < clones.length; ++i) {
clones[i] = map.get(labels.get(i));
}
return clones;
}
+
+ /**
+ * Clones the annotations of the given instruction into this instruction.
+ *
+ * @param insn
+ * the source instruction.
+ * @return this instruction.
+ */
+ protected final AbstractInsnNode cloneAnnotations(
+ final AbstractInsnNode insn) {
+ if (insn.visibleTypeAnnotations != null) {
+ this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
+ TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
+ TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+ src.typePath, src.desc);
+ src.accept(ann);
+ this.visibleTypeAnnotations.add(ann);
+ }
+ }
+ if (insn.invisibleTypeAnnotations != null) {
+ this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
+ TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
+ TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+ src.typePath, src.desc);
+ src.accept(ann);
+ this.invisibleTypeAnnotations.add(ann);
+ }
+ }
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
index 2fe5b77..9d07669 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
@@ -29,19 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents an annotationn.
*
* @author Eric Bruneton
*/
-public class AnnotationNode extends AnnotationVisitor
-{
+public class AnnotationNode extends AnnotationVisitor {
/**
* The class descriptor of the annotation class.
@@ -56,8 +55,8 @@ public class AnnotationNode extends AnnotationVisitor
* {@link Double}, {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an
* two elements String array (for enumeration values), a
* {@link AnnotationNode}, or a {@link List} of values of one of the
- * preceding types. The list may be <tt>null</tt> if there is no name
- * value pair.
+ * preceding types. The list may be <tt>null</tt> if there is no name value
+ * pair.
*/
public List<Object> values;
@@ -66,18 +65,26 @@ public class AnnotationNode extends AnnotationVisitor
* constructor</i>. Instead, they must use the
* {@link #AnnotationNode(int, String)} version.
*
- * @param desc the class descriptor of the annotation class.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public AnnotationNode(final String desc) {
- this(Opcodes.ASM4, desc);
+ this(Opcodes.ASM5, desc);
+ if (getClass() != AnnotationNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link AnnotationNode}.
*
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param desc the class descriptor of the annotation class.
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param desc
+ * the class descriptor of the annotation class.
*/
public AnnotationNode(final int api, final String desc) {
super(api);
@@ -87,10 +94,11 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Constructs a new {@link AnnotationNode} to visit an array value.
*
- * @param values where the visited values must be stored.
+ * @param values
+ * where the visited values must be stored.
*/
AnnotationNode(final List<Object> values) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
this.values = values;
}
@@ -110,11 +118,8 @@ public class AnnotationNode extends AnnotationVisitor
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
if (values == null) {
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
@@ -125,10 +130,8 @@ public class AnnotationNode extends AnnotationVisitor
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
if (values == null) {
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
@@ -167,7 +170,9 @@ public class AnnotationNode extends AnnotationVisitor
* recursively, do not contain elements that were introduced in more recent
* versions of the ASM API than the given version.
*
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
@@ -176,7 +181,8 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Makes the given visitor visit this annotation.
*
- * @param av an annotation visitor. Maybe <tt>null</tt>.
+ * @param av
+ * an annotation visitor. Maybe <tt>null</tt>.
*/
public void accept(final AnnotationVisitor av) {
if (av != null) {
@@ -194,15 +200,15 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Makes the given visitor visit a given annotation value.
*
- * @param av an annotation visitor. Maybe <tt>null</tt>.
- * @param name the value name.
- * @param value the actual value.
+ * @param av
+ * an annotation visitor. Maybe <tt>null</tt>.
+ * @param name
+ * the value name.
+ * @param value
+ * the actual value.
*/
- static void accept(
- final AnnotationVisitor av,
- final String name,
- final Object value)
- {
+ public static void accept(final AnnotationVisitor av, final String name,
+ final Object value) {
if (av != null) {
if (value instanceof String[]) {
String[] typeconst = (String[]) value;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
index 7bda1ab..0bdcc54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
@@ -29,15 +29,21 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A node that represents a class.
- *
+ *
* @author Eric Bruneton
*/
public class ClassNode extends ClassVisitor {
@@ -60,15 +66,15 @@ public class ClassNode extends ClassVisitor {
public String name;
/**
- * The signature of the class. Mayt be <tt>null</tt>.
+ * The signature of the class. May be <tt>null</tt>.
*/
public String signature;
/**
* The internal of name of the super class (see
* {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). For
- * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
- * but only for the {@link Object} class.
+ * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
+ * only for the {@link Object} class.
*/
public String superName;
@@ -86,7 +92,7 @@ public class ClassNode extends ClassVisitor {
public String sourceFile;
/**
- * Debug information to compute the correspondance between source and
+ * Debug information to compute the correspondence between source and
* compiled elements of the class. May be <tt>null</tt>.
*/
public String sourceDebug;
@@ -104,16 +110,16 @@ public class ClassNode extends ClassVisitor {
public String outerMethod;
/**
- * The descriptor of the method that contains the class, or <tt>null</tt>
- * if the class is not enclosed in a method.
+ * The descriptor of the method that contains the class, or <tt>null</tt> if
+ * the class is not enclosed in a method.
*/
public String outerMethodDesc;
/**
* The runtime visible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -121,41 +127,59 @@ public class ClassNode extends ClassVisitor {
/**
* The runtime invisible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this class. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this class. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this class. This list is a list of
* {@link Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
/**
* Informations about the inner classes of this class. This list is a list
* of {@link InnerClassNode} objects.
- *
- * @associates InnerClassNode
+ *
+ * @associates org.objectweb.asm.tree.InnerClassNode
*/
public List<InnerClassNode> innerClasses;
/**
* The fields of this class. This list is a list of {@link FieldNode}
* objects.
- *
- * @associates FieldNode
+ *
+ * @associates org.objectweb.asm.tree.FieldNode
*/
public List<FieldNode> fields;
/**
* The methods of this class. This list is a list of {@link MethodNode}
* objects.
- *
- * @associates MethodNode
+ *
+ * @associates org.objectweb.asm.tree.MethodNode
*/
public List<MethodNode> methods;
@@ -163,16 +187,23 @@ public class ClassNode extends ClassVisitor {
* Constructs a new {@link ClassNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #ClassNode(int)}
* version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public ClassNode() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != ClassNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link ClassNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassNode(final int api) {
super(api);
@@ -187,14 +218,9 @@ public class ClassNode extends ClassVisitor {
// ------------------------------------------------------------------------
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
this.version = version;
this.access = access;
this.name = name;
@@ -212,21 +238,16 @@ public class ClassNode extends ClassVisitor {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
outerClass = owner;
outerMethod = name;
outerMethodDesc = desc;
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -243,6 +264,24 @@ public class ClassNode extends ClassVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
attrs = new ArrayList<Attribute>(1);
@@ -251,44 +290,25 @@ public class ClassNode extends ClassVisitor {
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
- InnerClassNode icn = new InnerClassNode(name,
- outerName,
- innerName,
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
access);
innerClasses.add(icn);
}
@Override
- public FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
FieldNode fn = new FieldNode(access, name, desc, signature, value);
fields.add(fn);
return fn;
}
@Override
- public MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- MethodNode mn = new MethodNode(access,
- name,
- desc,
- signature,
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodNode mn = new MethodNode(access, name, desc, signature,
exceptions);
methods.add(mn);
return mn;
@@ -307,17 +327,35 @@ public class ClassNode extends ClassVisitor {
* This methods checks that this node, and all its nodes recursively, do not
* contain elements that were introduced in more recent versions of the ASM
* API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ for (FieldNode f : fields) {
+ f.check(api);
+ }
+ for (MethodNode m : methods) {
+ m.check(api);
+ }
+ }
}
/**
* Makes the given class visitor visit this class.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
// visits header
@@ -344,6 +382,19 @@ public class ClassNode extends ClassVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(cv.visitAnnotation(an.desc, false));
}
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
cv.visitAttribute(attrs.get(i));
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
index 265fb1e..848d05d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a field instruction. A field instruction is an
* instruction that loads or stores the value of a field of an object.
- *
+ *
* @author Eric Bruneton
*/
public class FieldInsnNode extends AbstractInsnNode {
@@ -59,20 +59,21 @@ public class FieldInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link FieldInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner the internal name of the field's owner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner
+ * the internal name of the field's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
*/
- public FieldInsnNode(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public FieldInsnNode(final int opcode, final String owner,
+ final String name, final String desc) {
super(opcode);
this.owner = owner;
this.name = name;
@@ -81,9 +82,10 @@ public class FieldInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
- * PUTSTATIC, GETFIELD or PUTFIELD.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be GETSTATIC,
+ * PUTSTATIC, GETFIELD or PUTFIELD.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -95,12 +97,14 @@ public class FieldInsnNode extends AbstractInsnNode {
}
@Override
- public void accept(final MethodVisitor cv) {
- cv.visitFieldInsn(opcode, owner, name, desc);
+ public void accept(final MethodVisitor mv) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new FieldInsnNode(opcode, owner, name, desc);
+ return new FieldInsnNode(opcode, owner, name, desc)
+ .cloneAnnotations(this);
}
}
[13/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
new file mode 100644
index 0000000..bffd20e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
@@ -0,0 +1,223 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.apache.tapestry5.internal.plastic.asm.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names. Subclasses can override
+ * the following methods:
+ *
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ *
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+ public String mapDesc(String desc) {
+ Type t = Type.getType(desc);
+ switch (t.getSort()) {
+ case Type.ARRAY:
+ String s = mapDesc(t.getElementType().getDescriptor());
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return s;
+ case Type.OBJECT:
+ String newType = map(t.getInternalName());
+ if (newType != null) {
+ return 'L' + newType + ';';
+ }
+ }
+ return desc;
+ }
+
+ private Type mapType(Type t) {
+ switch (t.getSort()) {
+ case Type.ARRAY:
+ String s = mapDesc(t.getElementType().getDescriptor());
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return Type.getType(s);
+ case Type.OBJECT:
+ s = map(t.getInternalName());
+ return s != null ? Type.getObjectType(s) : t;
+ case Type.METHOD:
+ return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+ }
+ return t;
+ }
+
+ public String mapType(String type) {
+ if (type == null) {
+ return null;
+ }
+ return mapType(Type.getObjectType(type)).getInternalName();
+ }
+
+ public String[] mapTypes(String[] types) {
+ String[] newTypes = null;
+ boolean needMapping = false;
+ for (int i = 0; i < types.length; i++) {
+ String type = types[i];
+ String newType = map(type);
+ if (newType != null && newTypes == null) {
+ newTypes = new String[types.length];
+ if (i > 0) {
+ System.arraycopy(types, 0, newTypes, 0, i);
+ }
+ needMapping = true;
+ }
+ if (needMapping) {
+ newTypes[i] = newType == null ? type : newType;
+ }
+ }
+ return needMapping ? newTypes : types;
+ }
+
+ public String mapMethodDesc(String desc) {
+ if ("()V".equals(desc)) {
+ return desc;
+ }
+
+ Type[] args = Type.getArgumentTypes(desc);
+ StringBuffer s = new StringBuffer("(");
+ for (int i = 0; i < args.length; i++) {
+ s.append(mapDesc(args[i].getDescriptor()));
+ }
+ Type returnType = Type.getReturnType(desc);
+ if (returnType == Type.VOID_TYPE) {
+ s.append(")V");
+ return s.toString();
+ }
+ s.append(')').append(mapDesc(returnType.getDescriptor()));
+ return s.toString();
+ }
+
+ public Object mapValue(Object value) {
+ if (value instanceof Type) {
+ return mapType((Type) value);
+ }
+ if (value instanceof Handle) {
+ Handle h = (Handle) value;
+ return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
+ h.getOwner(), h.getName(), h.getDesc()),
+ mapMethodDesc(h.getDesc()));
+ }
+ return value;
+ }
+
+ /**
+ *
+ * @param typeSignature
+ * true if signature is a FieldTypeSignature, such as the
+ * signature parameter of the ClassVisitor.visitField or
+ * MethodVisitor.visitLocalVariable methods
+ */
+ public String mapSignature(String signature, boolean typeSignature) {
+ if (signature == null) {
+ return null;
+ }
+ SignatureReader r = new SignatureReader(signature);
+ SignatureWriter w = new SignatureWriter();
+ SignatureVisitor a = createRemappingSignatureAdapter(w);
+ if (typeSignature) {
+ r.acceptType(a);
+ } else {
+ r.accept(a);
+ }
+ return w.toString();
+ }
+
+ protected SignatureVisitor createRemappingSignatureAdapter(
+ SignatureVisitor v) {
+ return new RemappingSignatureAdapter(v, this);
+ }
+
+ /**
+ * Map method name to the new name. Subclasses can override.
+ *
+ * @param owner
+ * owner of the method.
+ * @param name
+ * name of the method.
+ * @param desc
+ * descriptor of the method.
+ * @return new name of the method
+ */
+ public String mapMethodName(String owner, String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map invokedynamic method name to the new name. Subclasses can override.
+ *
+ * @param name
+ * name of the invokedynamic.
+ * @param desc
+ * descriptor of the invokedynamic.
+ * @return new invokdynamic name.
+ */
+ public String mapInvokeDynamicMethodName(String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map field name to the new name. Subclasses can override.
+ *
+ * @param owner
+ * owner of the field.
+ * @param name
+ * name of the field
+ * @param desc
+ * descriptor of the field
+ * @return new name of the field.
+ */
+ public String mapFieldName(String owner, String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map type name to the new name. Subclasses can override.
+ */
+ public String map(String typeName) {
+ return typeName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
new file mode 100644
index 0000000..2f253dd
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
@@ -0,0 +1,79 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} adapter for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter extends AnnotationVisitor {
+
+ protected final Remapper remapper;
+
+ public RemappingAnnotationAdapter(final AnnotationVisitor av,
+ final Remapper remapper) {
+ this(Opcodes.ASM5, av, remapper);
+ }
+
+ protected RemappingAnnotationAdapter(final int api,
+ final AnnotationVisitor av, final Remapper remapper) {
+ super(api, av);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ av.visit(name, remapper.mapValue(value));
+ }
+
+ @Override
+ public void visitEnum(String name, String desc, String value) {
+ av.visitEnum(name, remapper.mapDesc(desc), value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
+ return v == null ? null : (v == av ? this
+ : new RemappingAnnotationAdapter(v, remapper));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor v = av.visitArray(name);
+ return v == null ? null : (v == av ? this
+ : new RemappingAnnotationAdapter(v, remapper));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
new file mode 100644
index 0000000..7dbae24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
@@ -0,0 +1,135 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassVisitor {
+
+ protected final Remapper remapper;
+
+ protected String className;
+
+ public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
+ this(Opcodes.ASM5, cv, remapper);
+ }
+
+ protected RemappingClassAdapter(final int api, final ClassVisitor cv,
+ final Remapper remapper) {
+ super(api, cv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces) {
+ this.className = name;
+ super.visit(version, access, remapper.mapType(name), remapper
+ .mapSignature(signature, false), remapper.mapType(superName),
+ interfaces == null ? null : remapper.mapTypes(interfaces));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? null : createRemappingAnnotationAdapter(av);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? null : createRemappingAnnotationAdapter(av);
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc,
+ String signature, Object value) {
+ FieldVisitor fv = super.visitField(access,
+ remapper.mapFieldName(className, name, desc),
+ remapper.mapDesc(desc), remapper.mapSignature(signature, true),
+ remapper.mapValue(value));
+ return fv == null ? null : createRemappingFieldAdapter(fv);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
+ String newDesc = remapper.mapMethodDesc(desc);
+ MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
+ className, name, desc), newDesc, remapper.mapSignature(
+ signature, false),
+ exceptions == null ? null : remapper.mapTypes(exceptions));
+ return mv == null ? null : createRemappingMethodAdapter(access,
+ newDesc, mv);
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName,
+ String innerName, int access) {
+ // TODO should innerName be changed?
+ super.visitInnerClass(remapper.mapType(name), outerName == null ? null
+ : remapper.mapType(outerName), innerName, access);
+ }
+
+ @Override
+ public void visitOuterClass(String owner, String name, String desc) {
+ super.visitOuterClass(remapper.mapType(owner), name == null ? null
+ : remapper.mapMethodName(owner, name, desc),
+ desc == null ? null : remapper.mapMethodDesc(desc));
+ }
+
+ protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+ return new RemappingFieldAdapter(fv, remapper);
+ }
+
+ protected MethodVisitor createRemappingMethodAdapter(int access,
+ String newDesc, MethodVisitor mv) {
+ return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+ }
+
+ protected AnnotationVisitor createRemappingAnnotationAdapter(
+ AnnotationVisitor av) {
+ return new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
new file mode 100644
index 0000000..8a8420d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} adapter for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter extends FieldVisitor {
+
+ private final Remapper remapper;
+
+ public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
+ this(Opcodes.ASM5, fv, remapper);
+ }
+
+ protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
+ final Remapper remapper) {
+ super(api, fv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
new file mode 100644
index 0000000..1dec924
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
@@ -0,0 +1,224 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link LocalVariablesSorter} for type mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+ protected final Remapper remapper;
+
+ public RemappingMethodAdapter(final int access, final String desc,
+ final MethodVisitor mv, final Remapper remapper) {
+ this(Opcodes.ASM5, access, desc, mv, remapper);
+ }
+
+ protected RemappingMethodAdapter(final int api, final int access,
+ final String desc, final MethodVisitor mv, final Remapper remapper) {
+ super(api, access, desc, mv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ AnnotationVisitor av = super.visitAnnotationDefault();
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
+ AnnotationVisitor av = super.visitParameterAnnotation(parameter,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+ Object[] stack) {
+ super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
+ remapEntries(nStack, stack));
+ }
+
+ private Object[] remapEntries(int n, Object[] entries) {
+ for (int i = 0; i < n; i++) {
+ if (entries[i] instanceof String) {
+ Object[] newEntries = new Object[n];
+ if (i > 0) {
+ System.arraycopy(entries, 0, newEntries, 0, i);
+ }
+ do {
+ Object t = entries[i];
+ newEntries[i++] = t instanceof String ? remapper
+ .mapType((String) t) : t;
+ } while (i < n);
+ return newEntries;
+ }
+ }
+ return entries;
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner, String name,
+ String desc) {
+ super.visitFieldInsn(opcode, remapper.mapType(owner),
+ remapper.mapFieldName(owner, name, desc),
+ remapper.mapDesc(desc));
+ }
+
+ @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(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ // Calling super.visitMethodInsn requires to call the correct version
+ // depending on this.api (otherwise infinite loops can occur). To
+ // simplify and to make it easier to automatically remove the backward
+ // compatibility code, we inline the code of the overridden method here.
+ // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+ // LocalVariableSorter.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, remapper.mapType(owner),
+ remapper.mapMethodName(owner, name, desc),
+ remapper.mapMethodDesc(desc), itf);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ for (int i = 0; i < bsmArgs.length; i++) {
+ bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(
+ remapper.mapInvokeDynamicMethodName(name, desc),
+ remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
+ bsmArgs);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ super.visitTypeInsn(opcode, remapper.mapType(type));
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ super.visitLdcInsn(remapper.mapValue(cst));
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
+ super.visitTryCatchBlock(start, end, handler, type == null ? null
+ : remapper.mapType(type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
+ super.visitLocalVariable(name, remapper.mapDesc(desc),
+ remapper.mapSignature(signature, true), start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
+ typePath, start, end, index, remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
new file mode 100644
index 0000000..ff608a4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
@@ -0,0 +1,155 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} adapter for type mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter extends SignatureVisitor {
+
+ private final SignatureVisitor v;
+
+ private final Remapper remapper;
+
+ private String className;
+
+ public RemappingSignatureAdapter(final SignatureVisitor v,
+ final Remapper remapper) {
+ this(Opcodes.ASM5, v, remapper);
+ }
+
+ protected RemappingSignatureAdapter(final int api,
+ final SignatureVisitor v, final Remapper remapper) {
+ super(api);
+ this.v = v;
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitClassType(String name) {
+ className = name;
+ v.visitClassType(remapper.mapType(name));
+ }
+
+ @Override
+ public void visitInnerClassType(String name) {
+ String remappedOuter = remapper.mapType(className) + '$';
+ className = className + '$' + name;
+ String remappedName = remapper.mapType(className);
+ int index = remappedName.startsWith(remappedOuter) ? remappedOuter
+ .length() : remappedName.lastIndexOf('$') + 1;
+ v.visitInnerClassType(remappedName.substring(index));
+ }
+
+ @Override
+ public void visitFormalTypeParameter(String name) {
+ v.visitFormalTypeParameter(name);
+ }
+
+ @Override
+ public void visitTypeVariable(String name) {
+ v.visitTypeVariable(name);
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ v.visitArrayType();
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(char descriptor) {
+ v.visitBaseType(descriptor);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ v.visitClassBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ v.visitExceptionType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ v.visitInterface();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ v.visitInterfaceBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ v.visitParameterType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ v.visitReturnType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ v.visitSuperclass();
+ return this;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ v.visitTypeArgument();
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(char wildcard) {
+ v.visitTypeArgument(wildcard);
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ v.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
new file mode 100644
index 0000000..04dcc9b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -0,0 +1,540 @@
+/***
+ * 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.commons;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that adds a serial version unique identifier to a
+ * class if missing. Here is typical usage of this class:
+ *
+ * <pre>
+ * ClassWriter cw = new ClassWriter(...);
+ * ClassVisitor sv = new SerialVersionUIDAdder(cw);
+ * ClassVisitor ca = new MyClassAdapter(sv);
+ * new ClassReader(orginalClass).accept(ca, false);
+ * </pre>
+ *
+ * The SVUID algorithm can be found <a href=
+ * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
+ * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
+ *
+ * <pre>
+ * The serialVersionUID is computed using the signature of a stream of bytes
+ * that reflect the class definition. The National Institute of Standards and
+ * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
+ * signature for the stream. The first two 32-bit quantities are used to form a
+ * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
+ * types to a sequence of bytes. The values input to the stream are defined by
+ * the Java Virtual Machine (VM) specification for classes.
+ *
+ * The sequence of items in the stream is as follows:
+ *
+ * 1. The class name written using UTF encoding.
+ * 2. The class modifiers written as a 32-bit integer.
+ * 3. The name of each interface sorted by name written using UTF encoding.
+ * 4. For each field of the class sorted by field name (except private static
+ * and private transient fields):
+ * 1. The name of the field in UTF encoding.
+ * 2. The modifiers of the field written as a 32-bit integer.
+ * 3. The descriptor of the field in UTF encoding
+ * 5. If a class initializer exists, write out the following:
+ * 1. The name of the method, <clinit>, in UTF encoding.
+ * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
+ * written as a 32-bit integer.
+ * 3. The descriptor of the method, ()V, in UTF encoding.
+ * 6. For each non-private constructor sorted by method name and signature:
+ * 1. The name of the method, <init>, in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 7. For each non-private method sorted by method name and signature:
+ * 1. The name of the method in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
+ * DataOutputStream and produces five 32-bit values sha[0..4].
+ *
+ * 9. The hash value is assembled from the first and second 32-bit values of
+ * the SHA-1 message digest. If the result of the message digest, the five
+ * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
+ * sha, the hash value would be computed as follows:
+ *
+ * long hash = ((sha[0] >>> 24) & 0xFF) |
+ * ((sha[0] >>> 16) & 0xFF) << 8 |
+ * ((sha[0] >>> 8) & 0xFF) << 16 |
+ * ((sha[0] >>> 0) & 0xFF) << 24 |
+ * ((sha[1] >>> 24) & 0xFF) << 32 |
+ * ((sha[1] >>> 16) & 0xFF) << 40 |
+ * ((sha[1] >>> 8) & 0xFF) << 48 |
+ * ((sha[1] >>> 0) & 0xFF) << 56;
+ * </pre>
+ *
+ * @author Rajendra Inamdar, Vishal Vishnoi
+ */
+public class SerialVersionUIDAdder extends ClassVisitor {
+
+ /**
+ * Flag that indicates if we need to compute SVUID.
+ */
+ private boolean computeSVUID;
+
+ /**
+ * Set to true if the class already has SVUID.
+ */
+ private boolean hasSVUID;
+
+ /**
+ * Classes access flags.
+ */
+ private int access;
+
+ /**
+ * Internal name of the class
+ */
+ private String name;
+
+ /**
+ * Interfaces implemented by the class.
+ */
+ private String[] interfaces;
+
+ /**
+ * Collection of fields. (except private static and private transient
+ * fields)
+ */
+ private Collection<Item> svuidFields;
+
+ /**
+ * Set to true if the class has static initializer.
+ */
+ private boolean hasStaticInitializer;
+
+ /**
+ * Collection of non-private constructors.
+ */
+ private Collection<Item> svuidConstructors;
+
+ /**
+ * Collection of non-private methods.
+ */
+ private Collection<Item> svuidMethods;
+
+ /**
+ * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
+ *
+ * @param cv
+ * a {@link ClassVisitor} to which this visitor will delegate
+ * calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public SerialVersionUIDAdder(final ClassVisitor cv) {
+ this(Opcodes.ASM5, cv);
+ if (getClass() != SerialVersionUIDAdder.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link SerialVersionUIDAdder}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param cv
+ * a {@link ClassVisitor} to which this visitor will delegate
+ * calls.
+ */
+ protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
+ super(api, cv);
+ svuidFields = new ArrayList<Item>();
+ svuidConstructors = new ArrayList<Item>();
+ svuidMethods = new ArrayList<Item>();
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ /*
+ * Visit class header and get class name, access , and interfaces
+ * information (step 1,2, and 3) for SVUID computation.
+ */
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
+
+ if (computeSVUID) {
+ this.name = name;
+ this.access = access;
+ this.interfaces = new String[interfaces.length];
+ System.arraycopy(interfaces, 0, this.interfaces, 0,
+ interfaces.length);
+ }
+
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ /*
+ * Visit the methods and get constructor and method information (step 5 and
+ * 7). Also determine if there is a class initializer (step 6).
+ */
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ if (computeSVUID) {
+ if ("<clinit>".equals(name)) {
+ hasStaticInitializer = true;
+ }
+ /*
+ * Remembers non private constructors and methods for SVUID
+ * computation For constructor and method modifiers, only the
+ * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
+ * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
+ * are used.
+ */
+ int mods = access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
+ | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
+
+ // all non private methods
+ if ((access & Opcodes.ACC_PRIVATE) == 0) {
+ if ("<init>".equals(name)) {
+ svuidConstructors.add(new Item(name, mods, desc));
+ } else if (!"<clinit>".equals(name)) {
+ svuidMethods.add(new Item(name, mods, desc));
+ }
+ }
+ }
+
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ /*
+ * Gets class field information for step 4 of the algorithm. Also determines
+ * if the class already has a SVUID.
+ */
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if (computeSVUID) {
+ if ("serialVersionUID".equals(name)) {
+ // since the class already has SVUID, we won't be computing it.
+ computeSVUID = false;
+ hasSVUID = true;
+ }
+ /*
+ * Remember field for SVUID computation For field modifiers, only
+ * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
+ * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
+ * computing serialVersionUID values.
+ */
+ if ((access & Opcodes.ACC_PRIVATE) == 0
+ || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
+ int mods = access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
+ svuidFields.add(new Item(name, mods, desc));
+ }
+ }
+
+ return super.visitField(access, name, desc, signature, value);
+ }
+
+ /**
+ * Handle a bizarre special case. Nested classes (static classes declared
+ * inside another class) that are protected have their access bit set to
+ * public in their class files to deal with some odd reflection situation.
+ * Our SVUID computation must do as the JVM does and ignore access bits in
+ * the class file in favor of the access bits InnerClass attribute.
+ */
+ @Override
+ public void visitInnerClass(final String aname, final String outerName,
+ final String innerName, final int attr_access) {
+ if ((name != null) && name.equals(aname)) {
+ this.access = attr_access;
+ }
+ super.visitInnerClass(aname, outerName, innerName, attr_access);
+ }
+
+ /*
+ * Add the SVUID if class doesn't have one
+ */
+ @Override
+ public void visitEnd() {
+ // compute SVUID and add it to the class
+ if (computeSVUID && !hasSVUID) {
+ try {
+ addSVUID(computeSVUID());
+ } catch (Throwable e) {
+ throw new RuntimeException("Error while computing SVUID for "
+ + name, e);
+ }
+ }
+
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns true if the class already has a SVUID field. The result of this
+ * method is only valid when visitEnd is or has been called.
+ *
+ * @return true if the class already has a SVUID field.
+ */
+ public boolean hasSVUID() {
+ return hasSVUID;
+ }
+
+ protected void addSVUID(long svuid) {
+ FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
+ + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long(
+ svuid));
+ if (fv != null) {
+ fv.visitEnd();
+ }
+ }
+
+ /**
+ * Computes and returns the value of SVUID.
+ *
+ * @return Returns the serial version UID
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ protected long computeSVUID() throws IOException {
+ ByteArrayOutputStream bos;
+ DataOutputStream dos = null;
+ long svuid = 0;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ dos = new DataOutputStream(bos);
+
+ /*
+ * 1. The class name written using UTF encoding.
+ */
+ dos.writeUTF(name.replace('/', '.'));
+
+ /*
+ * 2. The class modifiers written as a 32-bit integer.
+ */
+ dos.writeInt(access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
+ | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
+
+ /*
+ * 3. The name of each interface sorted by name written using UTF
+ * encoding.
+ */
+ Arrays.sort(interfaces);
+ for (int i = 0; i < interfaces.length; i++) {
+ dos.writeUTF(interfaces[i].replace('/', '.'));
+ }
+
+ /*
+ * 4. For each field of the class sorted by field name (except
+ * private static and private transient fields):
+ *
+ * 1. The name of the field in UTF encoding. 2. The modifiers of the
+ * field written as a 32-bit integer. 3. The descriptor of the field
+ * in UTF encoding
+ *
+ * Note that field signatures are not dot separated. Method and
+ * constructor signatures are dot separated. Go figure...
+ */
+ writeItems(svuidFields, dos, false);
+
+ /*
+ * 5. If a class initializer exists, write out the following: 1. The
+ * name of the method, <clinit>, in UTF encoding. 2. The modifier of
+ * the method, java.lang.reflect.Modifier.STATIC, written as a
+ * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
+ * encoding.
+ */
+ if (hasStaticInitializer) {
+ dos.writeUTF("<clinit>");
+ dos.writeInt(Opcodes.ACC_STATIC);
+ dos.writeUTF("()V");
+ } // if..
+
+ /*
+ * 6. For each non-private constructor sorted by method name and
+ * signature: 1. The name of the method, <init>, in UTF encoding. 2.
+ * The modifiers of the method written as a 32-bit integer. 3. The
+ * descriptor of the method in UTF encoding.
+ */
+ writeItems(svuidConstructors, dos, true);
+
+ /*
+ * 7. For each non-private method sorted by method name and
+ * signature: 1. The name of the method in UTF encoding. 2. The
+ * modifiers of the method written as a 32-bit integer. 3. The
+ * descriptor of the method in UTF encoding.
+ */
+ writeItems(svuidMethods, dos, true);
+
+ dos.flush();
+
+ /*
+ * 8. The SHA-1 algorithm is executed on the stream of bytes
+ * produced by DataOutputStream and produces five 32-bit values
+ * sha[0..4].
+ */
+ byte[] hashBytes = computeSHAdigest(bos.toByteArray());
+
+ /*
+ * 9. The hash value is assembled from the first and second 32-bit
+ * values of the SHA-1 message digest. If the result of the message
+ * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
+ * five int values named sha, the hash value would be computed as
+ * follows:
+ *
+ * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
+ * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
+ * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
+ * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
+ * 56;
+ */
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+ }
+ } finally {
+ // close the stream (if open)
+ if (dos != null) {
+ dos.close();
+ }
+ }
+
+ return svuid;
+ }
+
+ /**
+ * Returns the SHA-1 message digest of the given value.
+ *
+ * @param value
+ * the value whose SHA message digest must be computed.
+ * @return the SHA-1 message digest of the given value.
+ */
+ protected byte[] computeSHAdigest(final byte[] value) {
+ try {
+ return MessageDigest.getInstance("SHA").digest(value);
+ } catch (Exception e) {
+ throw new UnsupportedOperationException(e.toString());
+ }
+ }
+
+ /**
+ * Sorts the items in the collection and writes it to the data output stream
+ *
+ * @param itemCollection
+ * collection of items
+ * @param dos
+ * a <code>DataOutputStream</code> value
+ * @param dotted
+ * a <code>boolean</code> value
+ * @exception IOException
+ * if an error occurs
+ */
+ private static void writeItems(final Collection<Item> itemCollection,
+ final DataOutput dos, final boolean dotted) throws IOException {
+ int size = itemCollection.size();
+ Item[] items = itemCollection.toArray(new Item[size]);
+ Arrays.sort(items);
+ for (int i = 0; i < size; i++) {
+ dos.writeUTF(items[i].name);
+ dos.writeInt(items[i].access);
+ dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
+ : items[i].desc);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Inner classes
+ // ------------------------------------------------------------------------
+
+ private static class Item implements Comparable<Item> {
+
+ final String name;
+
+ final int access;
+
+ final String desc;
+
+ Item(final String name, final int access, final String desc) {
+ this.name = name;
+ this.access = access;
+ this.desc = desc;
+ }
+
+ public int compareTo(final Item other) {
+ int retVal = name.compareTo(other.name);
+ if (retVal == 0) {
+ retVal = desc.compareTo(other.desc);
+ }
+ return retVal;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o instanceof Item) {
+ return compareTo((Item) o) == 0;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (name + desc).hashCode();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
new file mode 100644
index 0000000..25b594d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
@@ -0,0 +1,69 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * A {@link Remapper} using a {@link Map} to define its mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class SimpleRemapper extends Remapper {
+
+ private final Map<String, String> mapping;
+
+ public SimpleRemapper(Map<String, String> mapping) {
+ this.mapping = mapping;
+ }
+
+ public SimpleRemapper(String oldName, String newName) {
+ this.mapping = Collections.singletonMap(oldName, newName);
+ }
+
+ @Override
+ public String mapMethodName(String owner, String name, String desc) {
+ String s = map(owner + '.' + name + desc);
+ return s == null ? name : s;
+ }
+
+ @Override
+ public String mapFieldName(String owner, String name, String desc) {
+ String s = map(owner + '.' + name);
+ return s == null ? name : s;
+ }
+
+ @Override
+ public String map(String key) {
+ return mapping.get(key);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
new file mode 100644
index 0000000..8291c66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that merges clinit methods into a single one.
+ *
+ * @author Eric Bruneton
+ */
+public class StaticInitMerger extends ClassVisitor {
+
+ private String name;
+
+ private MethodVisitor clinit;
+
+ private final String prefix;
+
+ private int counter;
+
+ public StaticInitMerger(final String prefix, final ClassVisitor cv) {
+ this(Opcodes.ASM5, prefix, cv);
+ }
+
+ protected StaticInitMerger(final int api, final String prefix,
+ final ClassVisitor cv) {
+ super(api, cv);
+ this.prefix = prefix;
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ this.name = name;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodVisitor mv;
+ if ("<clinit>".equals(name)) {
+ int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+ String n = prefix + counter++;
+ mv = cv.visitMethod(a, n, desc, signature, exceptions);
+
+ if (clinit == null) {
+ clinit = cv.visitMethod(a, name, desc, null, null);
+ }
+ clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
+ false);
+ } else {
+ mv = cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+ return mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ if (clinit != null) {
+ clinit.visitInsn(Opcodes.RETURN);
+ clinit.visitMaxs(0, 0);
+ }
+ cv.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
new file mode 100644
index 0000000..322d7bb
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
@@ -0,0 +1,57 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
+/**
+ * A code generator for switch statements.
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public interface TableSwitchGenerator {
+
+ /**
+ * Generates the code for a switch case.
+ *
+ * @param key
+ * the switch case key.
+ * @param end
+ * a label that corresponds to the end of the switch statement.
+ */
+ void generateCase(int key, Label end);
+
+ /**
+ * Generates the code for the default switch case.
+ */
+ void generateDefault();
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
new file mode 100644
index 0000000..4b4641a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
@@ -0,0 +1,96 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+
+/**
+ * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
+ * are sorted in a method innermost-to-outermost. This allows the programmer to
+ * add handlers without worrying about ordering them correctly with respect to
+ * existing, in-code handlers.
+ *
+ * Behavior is only defined for properly-nested handlers. If any "try" blocks
+ * overlap (something that isn't possible in Java code) then this may not do
+ * what you want. In fact, this adapter just sorts by the length of the "try"
+ * block, taking advantage of the fact that a given try block must be larger
+ * than any block it contains).
+ *
+ * @author Adrian Sampson
+ */
+public class TryCatchBlockSorter extends MethodNode {
+
+ public TryCatchBlockSorter(final MethodVisitor mv, final int access,
+ final String name, final String desc, final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+ }
+
+ protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ super(api, access, name, desc, signature, exceptions);
+ this.mv = mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ // Compares TryCatchBlockNodes by the length of their "try" block.
+ Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
+
+ public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
+ int len1 = blockLength(t1);
+ int len2 = blockLength(t2);
+ return len1 - len2;
+ }
+
+ private int blockLength(TryCatchBlockNode block) {
+ int startidx = instructions.indexOf(block.start);
+ int endidx = instructions.indexOf(block.end);
+ return endidx - startidx;
+ }
+ };
+ Collections.sort(tryCatchBlocks, comp);
+ // Updates the 'target' of each try catch block annotation.
+ for (int i = 0; i < tryCatchBlocks.size(); ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
+ }
+ if (mv != null) {
+ accept(mv);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
new file mode 100644
index 0000000..4ce0db8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
@@ -0,0 +1,48 @@
+<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>
+Provides some useful class and method adapters. <i>The preferred way of using
+these adapters is by chaining them together and to custom adapters (instead of
+inheriting from them)</i>. Indeed this approach provides more combination
+possibilities than inheritance. For instance, suppose you want to implement an
+adapter MyAdapter than needs sorted local variables and intermediate stack map
+frame values taking into account the local variables sort. By using inheritance,
+this would require MyAdapter to extend AnalyzerAdapter, itself extending
+LocalVariablesSorter. But AnalyzerAdapter is not a subclass of
+LocalVariablesSorter, so this is not possible. On the contrary, by using
+delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter,
+itself delegating to MyAdapter. In this case AnalyzerAdapter computes
+intermediate frames based on the output of LocalVariablesSorter, and MyAdapter
+can add new locals by calling the newLocal method on LocalVariablesSorter, and
+can get the stack map frame state before each instruction by reading the locals
+and stack fields in AnalyzerAdapter (this requires references from MyAdapter
+back to LocalVariablesSorter and AnalyzerAdapter).
+</body>
\ 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/optimizer/AnnotationConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
new file mode 100644
index 0000000..84aff49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
@@ -0,0 +1,147 @@
+/***
+ * 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.optimizer;
+
+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 collects the {@link Constant}s of the
+ * annotations it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class AnnotationConstantsCollector extends AnnotationVisitor {
+
+ private final ConstantPool cp;
+
+ public AnnotationConstantsCollector(final AnnotationVisitor av,
+ final ConstantPool cp) {
+ super(Opcodes.ASM5, av);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ if (value instanceof Byte) {
+ cp.newInteger(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ cp.newInteger(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Character) {
+ cp.newInteger(((Character) value).charValue());
+ } else if (value instanceof Short) {
+ cp.newInteger(((Short) value).shortValue());
+ } else if (value instanceof Type) {
+ cp.newUTF8(((Type) value).getDescriptor());
+ } else if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i] ? 1 : 0);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newLong(v[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newFloat(v[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newDouble(v[i]);
+ }
+ } else {
+ cp.newConst(value);
+ }
+ av.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ cp.newUTF8(desc);
+ cp.newUTF8(value);
+ av.visitEnum(name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ cp.newUTF8(desc);
+ return new AnnotationConstantsCollector(av.visitAnnotation(name, desc),
+ cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ return new AnnotationConstantsCollector(av.visitArray(name), cp);
+ }
+
+ @Override
+ public void visitEnd() {
+ av.visitEnd();
+ }
+}
[12/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
new file mode 100644
index 0000000..b907322
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} that collects the {@link Constant}s of the classes it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassConstantsCollector extends ClassVisitor {
+
+ private final ConstantPool cp;
+
+ public ClassConstantsCollector(final ClassVisitor cv, final ConstantPool cp) {
+ super(Opcodes.ASM5, cv);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ cp.newClass(name);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (superName != null) {
+ cp.newClass(superName);
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ cp.newClass(interfaces[i]);
+ }
+ }
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ if (source != null) {
+ cp.newUTF8("SourceFile");
+ cp.newUTF8(source);
+ }
+ if (debug != null) {
+ cp.newUTF8("SourceDebugExtension");
+ }
+ cv.visitSource(source, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ cp.newUTF8("EnclosingMethod");
+ cp.newClass(owner);
+ if (name != null && desc != null) {
+ cp.newNameType(name, desc);
+ }
+ cv.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // can do nothing
+ cv.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ cp.newUTF8("InnerClasses");
+ if (name != null) {
+ cp.newClass(name);
+ }
+ if (outerName != null) {
+ cp.newClass(outerName);
+ }
+ if (innerName != null) {
+ cp.newUTF8(innerName);
+ }
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (value != null) {
+ cp.newConst(value);
+ }
+ return new FieldConstantsCollector(cv.visitField(access, name, desc,
+ signature, value), cp);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (exceptions != null) {
+ cp.newUTF8("Exceptions");
+ for (int i = 0; i < exceptions.length; ++i) {
+ cp.newClass(exceptions[i]);
+ }
+ }
+ return new MethodConstantsCollector(cv.visitMethod(access, name, desc,
+ signature, exceptions), cp);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
new file mode 100644
index 0000000..f4a7a22
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
@@ -0,0 +1,260 @@
+/***
+ * 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.optimizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingClassAdapter;
+
+/**
+ * A {@link ClassVisitor} that renames fields and methods, and removes debug
+ * info.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassOptimizer extends RemappingClassAdapter {
+
+ private String pkgName;
+ String clsName;
+
+ boolean isInterface = false;
+ boolean hasClinitMethod = false;
+ List<String> syntheticClassFields = new ArrayList<String>();
+
+ public ClassOptimizer(final ClassVisitor cv, final Remapper remapper) {
+ super(Opcodes.ASM5, cv, remapper);
+ }
+
+ FieldVisitor syntheticFieldVisitor(final int access, final String name,
+ final String desc) {
+ return super.visitField(access, name, desc, null, null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ super.visit(Opcodes.V1_2, access, name, null, superName, interfaces);
+ int index = name.lastIndexOf('/');
+ if (index > 0) {
+ pkgName = name.substring(0, index);
+ } else {
+ pkgName = "";
+ }
+ clsName = name;
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ // remove debug info
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // remove non standard attributes
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ // remove debug info
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ String s = remapper.mapFieldName(className, name, desc);
+ if ("-".equals(s)) {
+ return null;
+ }
+ if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+ if ((access & Opcodes.ACC_FINAL) != 0
+ && (access & Opcodes.ACC_STATIC) != 0 && desc.length() == 1) {
+ return null;
+ }
+ if ("org/objectweb/asm".equals(pkgName) && s.equals(name)) {
+ System.out.println("INFO: " + clsName + "." + s
+ + " could be renamed");
+ }
+ super.visitField(access, name, desc, null, value);
+ } else {
+ if (!s.equals(name)) {
+ throw new RuntimeException("The public or protected field "
+ + className + '.' + name + " must not be renamed.");
+ }
+ super.visitField(access, name, desc, null, value);
+ }
+ return null; // remove debug info
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ String s = remapper.mapMethodName(className, name, desc);
+ if ("-".equals(s)) {
+ return null;
+ }
+ if (name.equals("<clinit>") && !isInterface) {
+ hasClinitMethod = true;
+ MethodVisitor mv = super.visitMethod(access, name, desc, null,
+ exceptions);
+ return new MethodVisitor(Opcodes.ASM5, mv) {
+ @Override
+ public void visitCode() {
+ super.visitCode();
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName,
+ "_clinit_", "()V", false);
+ }
+ };
+ }
+
+ if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+ if ("org/objectweb/asm".equals(pkgName) && !name.startsWith("<")
+ && s.equals(name)) {
+ System.out.println("INFO: " + clsName + "." + s
+ + " could be renamed");
+ }
+ return super.visitMethod(access, name, desc, null, exceptions);
+ } else {
+ if (!s.equals(name)) {
+ throw new RuntimeException("The public or protected method "
+ + className + '.' + name + desc
+ + " must not be renamed.");
+ }
+ return super.visitMethod(access, name, desc, null, exceptions);
+ }
+ }
+
+ @Override
+ protected MethodVisitor createRemappingMethodAdapter(int access,
+ String newDesc, MethodVisitor mv) {
+ return new MethodOptimizer(this, access, newDesc, mv, remapper);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (syntheticClassFields.isEmpty()) {
+ if (hasClinitMethod) {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "_clinit_", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ } else {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2,
+ "java/lang/ClassNotFoundException");
+ mv.visitLabel(l0);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class",
+ "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitLabel(l1);
+ mv.visitInsn(Opcodes.ARETURN);
+ mv.visitLabel(l2);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/ClassNotFoundException", "getMessage",
+ "()Ljava/lang/String;", false);
+ mv.visitVarInsn(Opcodes.ASTORE, 1);
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/NoClassDefFoundError");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ALOAD, 1);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "java/lang/NoClassDefFoundError", "<init>",
+ "(Ljava/lang/String;)V", false);
+ mv.visitInsn(Opcodes.ATHROW);
+ mv.visitMaxs(3, 2);
+ mv.visitEnd();
+
+ if (hasClinitMethod) {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+ "_clinit_", "()V", null, null);
+ } else {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V",
+ null, null);
+ }
+ for (String ldcName : syntheticClassFields) {
+ String fieldName = "class$" + ldcName.replace('/', '$');
+ mv.visitLdcInsn(ldcName.replace('/', '.'));
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, clsName, fieldName,
+ "Ljava/lang/Class;");
+ }
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(1, 0);
+ mv.visitEnd();
+ }
+ super.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
new file mode 100644
index 0000000..9c1f306
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
@@ -0,0 +1,323 @@
+/***
+ * 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.optimizer;
+
+import java.util.Arrays;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+
+/**
+ * A constant pool item.
+ *
+ * @author Eric Bruneton
+ */
+class Constant {
+
+ /**
+ * Type of this constant pool item. A single class is used to represent all
+ * constant pool item types, in order to minimize the bytecode size of this
+ * package. The value of this field is I, J, F, D, S, s, C, T, G, M, N, y,
+ * t, [h..p] (for Constant Integer, Long, Float, Double, STR, UTF8, Class,
+ * NameType, Fieldref, Methodref, InterfaceMethodref, InvokeDynamic,
+ * MethodType and MethodHandle constant pool items respectively).
+ *
+ * The 9 variable of MethodHandle constants are stored between h and p.
+ */
+ char type;
+
+ /**
+ * Value of this item, for an integer item.
+ */
+ int intVal;
+
+ /**
+ * Value of this item, for a long item.
+ */
+ long longVal;
+
+ /**
+ * Value of this item, for a float item.
+ */
+ float floatVal;
+
+ /**
+ * Value of this item, for a double item.
+ */
+ double doubleVal;
+
+ /**
+ * First part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal1;
+
+ /**
+ * Second part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal2;
+
+ /**
+ * Third part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ Object objVal3;
+
+ /**
+ * InvokeDynamic's constant values.
+ */
+ Object[] objVals;
+
+ /**
+ * The hash code value of this constant pool item.
+ */
+ int hashCode;
+
+ Constant() {
+ }
+
+ Constant(final Constant i) {
+ type = i.type;
+ intVal = i.intVal;
+ longVal = i.longVal;
+ floatVal = i.floatVal;
+ doubleVal = i.doubleVal;
+ strVal1 = i.strVal1;
+ strVal2 = i.strVal2;
+ objVal3 = i.objVal3;
+ objVals = i.objVals;
+ hashCode = i.hashCode;
+ }
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal
+ * the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = 'I';
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
+
+ /**
+ * Sets this item to a long item.
+ *
+ * @param longVal
+ * the value of this item.
+ */
+ void set(final long longVal) {
+ this.type = 'J';
+ this.longVal = longVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+ }
+
+ /**
+ * Sets this item to a float item.
+ *
+ * @param floatVal
+ * the value of this item.
+ */
+ void set(final float floatVal) {
+ this.type = 'F';
+ this.floatVal = floatVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+ }
+
+ /**
+ * Sets this item to a double item.
+ *
+ * @param doubleVal
+ * the value of this item.
+ */
+ void set(final double doubleVal) {
+ this.type = 'D';
+ this.doubleVal = doubleVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+ }
+
+ /**
+ * Sets this item to an item that do not hold a primitive value.
+ *
+ * @param type
+ * the type of this item.
+ * @param strVal1
+ * first part of the value of this item.
+ * @param strVal2
+ * second part of the value of this item.
+ * @param strVal3
+ * third part of the value of this item.
+ */
+ void set(final char type, final String strVal1, final String strVal2,
+ final String strVal3) {
+ this.type = type;
+ this.strVal1 = strVal1;
+ this.strVal2 = strVal2;
+ this.objVal3 = strVal3;
+ switch (type) {
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case 'T':
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ // case 'G':
+ // case 'M':
+ // case 'N':
+ // case 'h' ... 'p':
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
+ }
+ }
+
+ /**
+ * Set this item to an InvokeDynamic item.
+ *
+ * @param name
+ * invokedynamic's name.
+ * @param desc
+ * invokedynamic's descriptor.
+ * @param bsm
+ * bootstrap method.
+ * @param bsmArgs
+ * bootstrap method constant arguments.
+ */
+ void set(final String name, final String desc, final Handle bsm,
+ final Object[] bsmArgs) {
+ this.type = 'y';
+ this.strVal1 = name;
+ this.strVal2 = desc;
+ this.objVal3 = bsm;
+ this.objVals = bsmArgs;
+
+ int hashCode = 'y' + name.hashCode() * desc.hashCode() * bsm.hashCode();
+ for (int i = 0; i < bsmArgs.length; i++) {
+ hashCode *= bsmArgs[i].hashCode();
+ }
+ this.hashCode = 0x7FFFFFFF & hashCode;
+ }
+
+ void write(final ClassWriter cw) {
+ switch (type) {
+ case 'I':
+ cw.newConst(new Integer(intVal));
+ break;
+ case 'J':
+ cw.newConst(new Long(longVal));
+ break;
+ case 'F':
+ cw.newConst(new Float(floatVal));
+ break;
+ case 'D':
+ cw.newConst(new Double(doubleVal));
+ break;
+ case 'S':
+ cw.newConst(strVal1);
+ break;
+ case 's':
+ cw.newUTF8(strVal1);
+ break;
+ case 'C':
+ cw.newClass(strVal1);
+ break;
+ case 'T':
+ cw.newNameType(strVal1, strVal2);
+ break;
+ case 'G':
+ cw.newField(strVal1, strVal2, (String) objVal3);
+ break;
+ case 'M':
+ cw.newMethod(strVal1, strVal2, (String) objVal3, false);
+ break;
+ case 'N':
+ cw.newMethod(strVal1, strVal2, (String) objVal3, true);
+ break;
+ case 'y':
+ cw.newInvokeDynamic(strVal1, strVal2, (Handle) objVal3, objVals);
+ break;
+ case 't':
+ cw.newMethodType(strVal1);
+ break;
+ default: // 'h' ... 'p': handle
+ cw.newHandle(type - 'h' + 1, strVal1, strVal2, (String) objVal3);
+ }
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Constant)) {
+ return false;
+ }
+ Constant c = (Constant) o;
+ if (c.type == type) {
+ switch (type) {
+ case 'I':
+ return c.intVal == intVal;
+ case 'J':
+ return c.longVal == longVal;
+ case 'F':
+ return Float.compare(c.floatVal, floatVal) == 0;
+ case 'D':
+ return Double.compare(c.doubleVal, doubleVal) == 0;
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ return c.strVal1.equals(strVal1);
+ case 'T':
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2);
+ case 'y':
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+ && c.objVal3.equals(objVal3)
+ && Arrays.equals(c.objVals, objVals);
+ // case 'G':
+ // case 'M':
+ // case 'N':
+ // case 'h' ... 'p':
+ default:
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+ && c.objVal3.equals(objVal3);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
new file mode 100644
index 0000000..1901387
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
@@ -0,0 +1,249 @@
+/***
+ * 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.optimizer;
+
+import java.util.HashMap;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A constant pool.
+ *
+ * @author Eric Bruneton
+ */
+public class ConstantPool extends HashMap<Constant, Constant> {
+
+ private final Constant key1 = new Constant();
+
+ private final Constant key2 = new Constant();
+
+ private final Constant key3 = new Constant();
+
+ private final Constant key4 = new Constant();
+
+ private final Constant key5 = new Constant();
+
+ public Constant newInteger(final int value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newFloat(final float value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newLong(final long value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newDouble(final double value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newUTF8(final String value) {
+ key1.set('s', value, null, null);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ private Constant newString(final String value) {
+ key2.set('S', value, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(value);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newClass(final String value) {
+ key2.set('C', value, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(value);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newMethodType(final String methodDescriptor) {
+ key2.set('t', methodDescriptor, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(methodDescriptor);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newHandle(final int tag, final String owner,
+ final String name, final String desc) {
+ key4.set((char) ('h' - 1 + tag), owner, name, desc);
+ Constant result = get(key4);
+ if (result == null) {
+ if (tag <= Opcodes.H_PUTSTATIC) {
+ newField(owner, name, desc);
+ } else {
+ newMethod(owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
+ }
+ result = new Constant(key4);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newConst(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ return newFloat(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ return newLong(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ return newDouble(val);
+ } else if (cst instanceof String) {
+ return newString((String) cst);
+ } else if (cst instanceof Type) {
+ Type t = (Type) cst;
+ int s = t.getSort();
+ if (s == Type.OBJECT) {
+ return newClass(t.getInternalName());
+ } else if (s == Type.METHOD) {
+ return newMethodType(t.getDescriptor());
+ } else { // s == primitive type or array
+ return newClass(t.getDescriptor());
+ }
+ } else if (cst instanceof Handle) {
+ Handle h = (Handle) cst;
+ return newHandle(h.getTag(), h.getOwner(), h.getName(), h.getDesc());
+ } else {
+ throw new IllegalArgumentException("value " + cst);
+ }
+ }
+
+ public Constant newField(final String owner, final String name,
+ final String desc) {
+ key3.set('G', owner, name, desc);
+ Constant result = get(key3);
+ if (result == null) {
+ newClass(owner);
+ newNameType(name, desc);
+ result = new Constant(key3);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newMethod(final String owner, final String name,
+ final String desc, final boolean itf) {
+ key3.set(itf ? 'N' : 'M', owner, name, desc);
+ Constant result = get(key3);
+ if (result == null) {
+ newClass(owner);
+ newNameType(name, desc);
+ result = new Constant(key3);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newInvokeDynamic(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ key5.set(name, desc, bsm, bsmArgs);
+ Constant result = get(key5);
+ if (result == null) {
+ newNameType(name, desc);
+ newHandle(bsm.getTag(), bsm.getOwner(), bsm.getName(),
+ bsm.getDesc());
+ for (int i = 0; i < bsmArgs.length; i++) {
+ newConst(bsmArgs[i]);
+ }
+ result = new Constant(key5);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newNameType(final String name, final String desc) {
+ key2.set('T', name, desc, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(name);
+ newUTF8(desc);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ private Constant get(final Constant key) {
+ return get((Object) key);
+ }
+
+ private void put(final Constant cst) {
+ put(cst, cst);
+ }
+}
\ 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/optimizer/FieldConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
new file mode 100644
index 0000000..63ca654
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
@@ -0,0 +1,89 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} that collects the {@link Constant}s of the fields it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldConstantsCollector extends FieldVisitor {
+
+ private final ConstantPool cp;
+
+ public FieldConstantsCollector(final FieldVisitor fv, final ConstantPool cp) {
+ super(Opcodes.ASM5, fv);
+ this.cp = cp;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // can do nothing
+ fv.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ fv.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
new file mode 100644
index 0000000..e7d93cf
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
@@ -0,0 +1,235 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A Jar file optimizer.
+ *
+ * @author Eric Bruneton
+ */
+public class JarOptimizer {
+
+ static final Set<String> API = new HashSet<String>();
+ static final Map<String, String> HIERARCHY = new HashMap<String, String>();
+ static boolean nodebug = false;
+
+ public static void main(final String[] args) throws IOException {
+ File f = new File(args[0]);
+ InputStream is = new GZIPInputStream(new FileInputStream(f));
+ BufferedReader lnr = new LineNumberReader(new InputStreamReader(is));
+ while (true) {
+ String line = lnr.readLine();
+ if (line != null) {
+ if (line.startsWith("class")) {
+ String c = line.substring(6, line.lastIndexOf(' '));
+ String sc = line.substring(line.lastIndexOf(' ') + 1);
+ HIERARCHY.put(c, sc);
+ } else {
+ API.add(line);
+ }
+ } else {
+ break;
+ }
+ }
+
+ int argIndex = 1;
+ if (args[argIndex].equals("-nodebug")) {
+ nodebug = true;
+ argIndex++;
+ }
+
+ optimize(new File(args[argIndex]));
+ }
+
+ static void optimize(final File f) throws IOException {
+ if (nodebug && f.getName().contains("debug")) {
+ return;
+ }
+
+ if (f.isDirectory()) {
+ File[] files = f.listFiles();
+ for (int i = 0; i < files.length; ++i) {
+ optimize(files[i]);
+ }
+ } else if (f.getName().endsWith(".jar")) {
+ File g = new File(f.getParentFile(), f.getName() + ".new");
+ ZipFile zf = new ZipFile(f);
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(g));
+ Enumeration<? extends ZipEntry> e = zf.entries();
+ byte[] buf = new byte[10000];
+ while (e.hasMoreElements()) {
+ ZipEntry ze = e.nextElement();
+ if (ze.isDirectory()) {
+ out.putNextEntry(ze);
+ continue;
+ }
+ out.putNextEntry(ze);
+ if (ze.getName().endsWith(".class")) {
+ ClassReader cr = new ClassReader(zf.getInputStream(ze));
+ // cr.accept(new ClassDump(), 0);
+ cr.accept(new ClassVerifier(), 0);
+ }
+ InputStream is = zf.getInputStream(ze);
+ int n;
+ do {
+ n = is.read(buf, 0, buf.length);
+ if (n != -1) {
+ out.write(buf, 0, n);
+ }
+ } while (n != -1);
+ out.closeEntry();
+ }
+ out.close();
+ zf.close();
+ if (!f.delete()) {
+ throw new IOException("Cannot delete file " + f);
+ }
+ if (!g.renameTo(f)) {
+ throw new IOException("Cannot rename file " + g);
+ }
+ }
+ }
+
+ static class ClassDump extends ClassVisitor {
+
+ String owner;
+
+ public ClassDump() {
+ super(Opcodes.ASM5);
+ }
+
+ @Override
+ public void visit(final int version, final int access,
+ final String name, final String signature,
+ final String superName, final String[] interfaces) {
+ owner = name;
+ if (owner.startsWith("java/")) {
+ System.out.println("class " + name + ' ' + superName);
+ }
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if (owner.startsWith("java/")) {
+ System.out.println(owner + ' ' + name);
+ }
+ return null;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions) {
+ if (owner.startsWith("java/")) {
+ System.out.println(owner + ' ' + name + desc);
+ }
+ return null;
+ }
+ }
+
+ static class ClassVerifier extends ClassVisitor {
+
+ String owner;
+
+ String method;
+
+ public ClassVerifier() {
+ super(Opcodes.ASM5);
+ }
+
+ @Override
+ public void visit(final int version, final int access,
+ final String name, final String signature,
+ final String superName, final String[] interfaces) {
+ owner = name;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions) {
+ method = name + desc;
+ return new MethodVisitor(Opcodes.ASM5) {
+ @Override
+ public void visitFieldInsn(final int opcode,
+ final String owner, final String name, final String desc) {
+ check(owner, name);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode,
+ final String owner, final String name,
+ final String desc, final boolean itf) {
+ check(owner, name + desc);
+ }
+ };
+ }
+
+ void check(String owner, String member) {
+ if (owner.startsWith("java/")) {
+ String o = owner;
+ while (o != null) {
+ if (API.contains(o + ' ' + member)) {
+ return;
+ }
+ o = HIERARCHY.get(o);
+ }
+ System.out.println("WARNING: " + owner + ' ' + member
+ + " called in " + this.owner + ' ' + method
+ + " is not defined in JDK 1.3 API");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
new file mode 100644
index 0000000..54b3519
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
@@ -0,0 +1,224 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * An {@link MethodVisitor} that collects the {@link Constant}s of the methods
+ * it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodConstantsCollector extends MethodVisitor {
+
+ private final ConstantPool cp;
+
+ public MethodConstantsCollector(final MethodVisitor mv,
+ final ConstantPool cp) {
+ super(Opcodes.ASM5, mv);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ cp.newUTF8("MethodParameters");
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ mv.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ cp.newUTF8("AnnotationDefault");
+ return new AnnotationConstantsCollector(mv.visitAnnotationDefault(), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleParameterAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleParameterAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitParameterAnnotation(
+ parameter, desc, visible), cp);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ cp.newClass(type);
+ mv.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ cp.newField(owner, name, desc);
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ cp.newMethod(owner, name, desc, itf);
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ cp.newInvokeDynamic(name, desc, bsm, bsmArgs);
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ cp.newConst(cst);
+ mv.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ cp.newClass(desc);
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitInsnAnnotation(typeRef,
+ typePath, desc, visible), cp);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ if (type != null) {
+ cp.newClass(type);
+ }
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitTryCatchAnnotation(
+ typeRef, typePath, desc, visible), cp);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ if (signature != null) {
+ cp.newUTF8("LocalVariableTypeTable");
+ cp.newUTF8(name);
+ cp.newUTF8(signature);
+ }
+ cp.newUTF8("LocalVariableTable");
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(
+ mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, visible), cp);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ cp.newUTF8("LineNumberTable");
+ mv.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ cp.newUTF8("Code");
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
new file mode 100644
index 0000000..adad6b4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingMethodAdapter;
+
+/**
+ * A {@link MethodVisitor} that renames fields and methods, and removes debug
+ * info.
+ *
+ * @author Eugene Kuleshov
+ */
+public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
+
+ private final ClassOptimizer classOptimizer;
+
+ public MethodOptimizer(ClassOptimizer classOptimizer, int access,
+ String desc, MethodVisitor mv, Remapper remapper) {
+ super(Opcodes.ASM5, access, desc, mv, remapper);
+ this.classOptimizer = classOptimizer;
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(String name, int access) {
+ // remove parameter info
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitFrame(int type, int local, Object[] local2, int stack,
+ Object[] stack2) {
+ // remove frame info
+ }
+
+ @Override
+ public void visitAttribute(Attribute attr) {
+ // remove non standard attributes
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ if (!(cst instanceof Type)) {
+ super.visitLdcInsn(cst);
+ return;
+ }
+
+ // transform Foo.class for 1.2 compatibility
+ String ldcName = ((Type) cst).getInternalName();
+ String fieldName = "class$" + ldcName.replace('/', '$');
+ if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
+ classOptimizer.syntheticClassFields.add(ldcName);
+ FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
+ | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
+ fv.visitEnd();
+ }
+
+ String clsName = classOptimizer.clsName;
+ mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
new file mode 100644
index 0000000..70d74f7
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
@@ -0,0 +1,114 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A MAPPING from names to names, used to rename classes, fields and methods.
+ *
+ * @author Eric Bruneton
+ */
+public class NameMapping {
+
+ public final Properties mapping;
+
+ public final Set<Object> unused;
+
+ public NameMapping(final String file) throws IOException {
+ mapping = new Properties();
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ mapping.load(is);
+ unused = new HashSet<Object>(mapping.keySet());
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+
+ public String map(final String name) {
+ String s = (String) mapping.get(name);
+ if (s == null) {
+ int p = name.indexOf('.');
+ if (p == -1) {
+ s = name;
+ } else {
+ int q = name.indexOf('(');
+ if (q == -1) {
+ s = name.substring(p + 1);
+ } else {
+ s = name.substring(p + 1, q);
+ }
+ }
+ } else {
+ unused.remove(name);
+ }
+ return s;
+ }
+
+ public String fix(final String desc) {
+ if (desc.startsWith("(")) {
+ Type[] arguments = Type.getArgumentTypes(desc);
+ Type result = Type.getReturnType(desc);
+ for (int i = 0; i < arguments.length; ++i) {
+ arguments[i] = fix(arguments[i]);
+ }
+ result = fix(result);
+ return Type.getMethodDescriptor(result, arguments);
+ } else {
+ return fix(Type.getType(desc)).getDescriptor();
+ }
+ }
+
+ private Type fix(final Type t) {
+ if (t.getSort() == Type.OBJECT) {
+ return Type.getObjectType(map(t.getInternalName()));
+ } else if (t.getSort() == Type.ARRAY) {
+ String s = fix(t.getElementType()).getDescriptor();
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return Type.getType(s);
+ } else {
+ return t;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
new file mode 100644
index 0000000..e20cf5c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
@@ -0,0 +1,283 @@
+/***
+ * 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.optimizer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.SimpleRemapper;
+
+/**
+ * A class file shrinker utility.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Shrinker {
+
+ static final HashMap<String, String> MAPPING = new HashMap<String, String>();
+
+ public static void main(final String[] args) throws IOException {
+ Properties properties = new Properties();
+ int n = args.length - 1;
+ for (int i = 0; i < n - 1; ++i) {
+ properties.load(new FileInputStream(args[i]));
+ }
+
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+ MAPPING.put((String) entry.getKey(), (String) entry.getValue());
+ }
+
+ final Set<String> unused = new HashSet<String>(MAPPING.keySet());
+
+ File f = new File(args[n - 1]);
+ File d = new File(args[n]);
+
+ optimize(f, d, new SimpleRemapper(MAPPING) {
+ @Override
+ public String map(String key) {
+ String s = super.map(key);
+ if (s != null) {
+ unused.remove(key);
+ }
+ return s;
+ }
+ });
+
+ Iterator<String> i = unused.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (!s.endsWith("/remove")) {
+ System.out.println("INFO: unused mapping " + s);
+ }
+ }
+ }
+
+ static void optimize(final File f, final File d, final Remapper remapper)
+ throws IOException {
+ if (f.isDirectory()) {
+ File[] files = f.listFiles();
+ for (int i = 0; i < files.length; ++i) {
+ optimize(files[i], d, remapper);
+ }
+ } else if (f.getName().endsWith(".class")) {
+ ConstantPool cp = new ConstantPool();
+ ClassReader cr = new ClassReader(new FileInputStream(f));
+ ClassWriter cw = new ClassWriter(0);
+ ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp);
+ ClassOptimizer co = new ClassOptimizer(ccc, remapper);
+ cr.accept(co, ClassReader.SKIP_DEBUG);
+
+ Set<Constant> constants = new TreeSet<Constant>(
+ new ConstantComparator());
+ constants.addAll(cp.values());
+
+ cr = new ClassReader(cw.toByteArray());
+ cw = new ClassWriter(0);
+ Iterator<Constant> i = constants.iterator();
+ while (i.hasNext()) {
+ Constant c = i.next();
+ c.write(cw);
+ }
+ cr.accept(cw, ClassReader.SKIP_DEBUG);
+
+ if (MAPPING.get(cr.getClassName() + "/remove") != null) {
+ return;
+ }
+ String n = remapper.mapType(cr.getClassName());
+ File g = new File(d, n + ".class");
+ if (!g.exists() || g.lastModified() < f.lastModified()) {
+ if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) {
+ throw new IOException("Cannot create directory "
+ + g.getParentFile());
+ }
+ OutputStream os = new FileOutputStream(g);
+ try {
+ os.write(cw.toByteArray());
+ } finally {
+ os.close();
+ }
+ }
+ }
+ }
+
+ static class ConstantComparator implements Comparator<Constant> {
+
+ public int compare(final Constant c1, final Constant c2) {
+ int d = getSort(c1) - getSort(c2);
+ if (d == 0) {
+ switch (c1.type) {
+ case 'I':
+ return new Integer(c1.intVal).compareTo(new Integer(
+ c2.intVal));
+ case 'J':
+ return new Long(c1.longVal).compareTo(new Long(c2.longVal));
+ case 'F':
+ return new Float(c1.floatVal).compareTo(new Float(
+ c2.floatVal));
+ case 'D':
+ return new Double(c1.doubleVal).compareTo(new Double(
+ c2.doubleVal));
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ return c1.strVal1.compareTo(c2.strVal1);
+ case 'T':
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ }
+ break;
+ case 'y':
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ if (d == 0) {
+ Handle bsm1 = (Handle) c1.objVal3;
+ Handle bsm2 = (Handle) c2.objVal3;
+ d = compareHandle(bsm1, bsm2);
+ if (d == 0) {
+ d = compareObjects(c1.objVals, c2.objVals);
+ }
+ }
+ }
+ break;
+
+ default:
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ if (d == 0) {
+ d = ((String) c1.objVal3)
+ .compareTo((String) c2.objVal3);
+ }
+ }
+ }
+ }
+ return d;
+ }
+
+ private static int compareHandle(Handle h1, Handle h2) {
+ int d = h1.getTag() - h2.getTag();
+ if (d == 0) {
+ d = h1.getOwner().compareTo(h2.getOwner());
+ if (d == 0) {
+ d = h1.getName().compareTo(h2.getName());
+ if (d == 0) {
+ d = h1.getDesc().compareTo(h2.getDesc());
+ }
+ }
+ }
+ return d;
+ }
+
+ private static int compareType(Type mtype1, Type mtype2) {
+ return mtype1.getDescriptor().compareTo(mtype2.getDescriptor());
+ }
+
+ private static int compareObjects(Object[] objVals1, Object[] objVals2) {
+ int length = objVals1.length;
+ int d = length - objVals2.length;
+ if (d == 0) {
+ for (int i = 0; i < length; i++) {
+ Object objVal1 = objVals1[i];
+ Object objVal2 = objVals2[i];
+ d = objVal1.getClass().getName()
+ .compareTo(objVal2.getClass().getName());
+ if (d == 0) {
+ if (objVal1 instanceof Type) {
+ d = compareType((Type) objVal1, (Type) objVal2);
+ } else if (objVal1 instanceof Handle) {
+ d = compareHandle((Handle) objVal1,
+ (Handle) objVal2);
+ } else {
+ d = ((Comparable) objVal1).compareTo(objVal2);
+ }
+ }
+
+ if (d != 0) {
+ return d;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private static int getSort(final Constant c) {
+ switch (c.type) {
+ case 'I':
+ return 0;
+ case 'J':
+ return 1;
+ case 'F':
+ return 2;
+ case 'D':
+ return 3;
+ case 's':
+ return 4;
+ case 'S':
+ return 5;
+ case 'C':
+ return 6;
+ case 'T':
+ return 7;
+ case 'G':
+ return 8;
+ case 'M':
+ return 9;
+ case 'N':
+ return 10;
+ case 'y':
+ return 11;
+ case 't':
+ return 12;
+ default:
+ return 100 + c.type - 'h';
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
new file mode 100644
index 0000000..39cdf9d
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz differ
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
new file mode 100644
index 0000000..a3c7aa6
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz differ
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
new file mode 100644
index 0000000..03fec2e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
@@ -0,0 +1,53 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.anns=-
+org/objectweb/asm/ClassWriter.ianns=-
+
+org/objectweb/asm/FieldWriter.anns=-
+org/objectweb/asm/FieldWriter.ianns=-
+
+org/objectweb/asm/MethodWriter.annd=-
+org/objectweb/asm/MethodWriter.anns=-
+org/objectweb/asm/MethodWriter.ianns=-
+org/objectweb/asm/MethodWriter.panns=-
+org/objectweb/asm/MethodWriter.ipanns=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readParameterAnnotations(I[CZLorg/objectweb/asm/MethodVisitor;)V=-
[17/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
index ac7c671..d899c5e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
@@ -37,7 +37,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* opcodes are therefore not defined in this interface. Likewise for LDC,
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
* JSR_W.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -46,6 +46,7 @@ public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0;
+ int ASM5 = 5 << 16 | 0 << 8 | 0;
// versions
@@ -56,6 +57,7 @@ public interface Opcodes {
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
+ int V1_8 = 0 << 16 | 52;
// access flags
@@ -63,7 +65,7 @@ public interface Opcodes {
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
- int ACC_FINAL = 0x0010; // class, field, method
+ int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_VOLATILE = 0x0040; // field
@@ -74,9 +76,10 @@ public interface Opcodes {
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
- int ACC_SYNTHETIC = 0x1000; // class, field, method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
+ int ACC_MANDATED = 0x8000; // parameter
// ASM specific pseudo access flags
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
index 6011aa4..0b526a0 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
@@ -35,7 +35,7 @@ import java.lang.reflect.Method;
/**
* A Java field or method type. This class can be used to make it easier to
* manipulate type and method descriptors.
- *
+ *
* @author Eric Bruneton
* @author Chris Nokleberg
*/
@@ -189,14 +189,17 @@ public class Type {
/**
* Constructs a reference type.
- *
- * @param sort the sort of the reference type to be constructed.
- * @param buf a buffer containing the descriptor of the previous type.
- * @param off the offset of this descriptor in the previous buffer.
- * @param len the length of this descriptor.
- */
- private Type(final int sort, final char[] buf, final int off, final int len)
- {
+ *
+ * @param sort
+ * the sort of the reference type to be constructed.
+ * @param buf
+ * a buffer containing the descriptor of the previous type.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
+ * @param len
+ * the length of this descriptor.
+ */
+ private Type(final int sort, final char[] buf, final int off, final int len) {
this.sort = sort;
this.buf = buf;
this.off = off;
@@ -205,8 +208,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given type descriptor.
- *
- * @param typeDescriptor a field or method type descriptor.
+ *
+ * @param typeDescriptor
+ * a field or method type descriptor.
* @return the Java type corresponding to the given type descriptor.
*/
public static Type getType(final String typeDescriptor) {
@@ -215,8 +219,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given internal name.
- *
- * @param internalName an internal name.
+ *
+ * @param internalName
+ * an internal name.
* @return the Java type corresponding to the given internal name.
*/
public static Type getObjectType(final String internalName) {
@@ -227,8 +232,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given method descriptor.
* Equivalent to <code>Type.getType(methodDescriptor)</code>.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java type corresponding to the given method descriptor.
*/
public static Type getMethodType(final String methodDescriptor) {
@@ -238,19 +244,24 @@ public class Type {
/**
* Returns the Java method type corresponding to the given argument and
* return types.
- *
- * @param returnType the return type of the method.
- * @param argumentTypes the argument types of the method.
- * @return the Java type corresponding to the given argument and return types.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
+ * @return the Java type corresponding to the given argument and return
+ * types.
*/
- public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
+ public static Type getMethodType(final Type returnType,
+ final Type... argumentTypes) {
return getType(getMethodDescriptor(returnType, argumentTypes));
}
/**
* Returns the Java type corresponding to the given class.
- *
- * @param c a class.
+ *
+ * @param c
+ * a class.
* @return the Java type corresponding to the given class.
*/
public static Type getType(final Class<?> c) {
@@ -281,8 +292,9 @@ public class Type {
/**
* Returns the Java method type corresponding to the given constructor.
- *
- * @param c a {@link Constructor Constructor} object.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
* @return the Java method type corresponding to the given constructor.
*/
public static Type getType(final Constructor<?> c) {
@@ -291,8 +303,9 @@ public class Type {
/**
* Returns the Java method type corresponding to the given method.
- *
- * @param m a {@link Method Method} object.
+ *
+ * @param m
+ * a {@link Method Method} object.
* @return the Java method type corresponding to the given method.
*/
public static Type getType(final Method m) {
@@ -302,8 +315,9 @@ public class Type {
/**
* Returns the Java types corresponding to the argument types of the given
* method descriptor.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java types corresponding to the argument types of the given
* method descriptor.
*/
@@ -337,8 +351,9 @@ public class Type {
/**
* Returns the Java types corresponding to the argument types of the given
* method.
- *
- * @param method a method.
+ *
+ * @param method
+ * a method.
* @return the Java types corresponding to the argument types of the given
* method.
*/
@@ -354,8 +369,9 @@ public class Type {
/**
* Returns the Java type corresponding to the return type of the given
* method descriptor.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java type corresponding to the return type of the given
* method descriptor.
*/
@@ -367,8 +383,9 @@ public class Type {
/**
* Returns the Java type corresponding to the return type of the given
* method.
- *
- * @param method a method.
+ *
+ * @param method
+ * a method.
* @return the Java type corresponding to the return type of the given
* method.
*/
@@ -378,13 +395,14 @@ public class Type {
/**
* Computes the size of the arguments and of the return value of a method.
- *
- * @param desc the descriptor of a method.
+ *
+ * @param desc
+ * the descriptor of a method.
* @return the size of the arguments of the method (plus one for the
* implicit this argument), argSize, and the size of its return
* value, retSize, packed into a single int i =
- * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
- * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+ * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
+ * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
*/
public static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
@@ -418,53 +436,55 @@ public class Type {
* Returns the Java type corresponding to the given type descriptor. For
* method descriptors, buf is supposed to contain nothing more than the
* descriptor itself.
- *
- * @param buf a buffer containing a type descriptor.
- * @param off the offset of this descriptor in the previous buffer.
+ *
+ * @param buf
+ * a buffer containing a type descriptor.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
* @return the Java type corresponding to the given type descriptor.
*/
private static Type getType(final char[] buf, final int off) {
int len;
switch (buf[off]) {
- case 'V':
- return VOID_TYPE;
- case 'Z':
- return BOOLEAN_TYPE;
- case 'C':
- return CHAR_TYPE;
- case 'B':
- return BYTE_TYPE;
- case 'S':
- return SHORT_TYPE;
- case 'I':
- return INT_TYPE;
- case 'F':
- return FLOAT_TYPE;
- case 'J':
- return LONG_TYPE;
- case 'D':
- return DOUBLE_TYPE;
- case '[':
- len = 1;
- while (buf[off + len] == '[') {
- ++len;
- }
- if (buf[off + len] == 'L') {
- ++len;
- while (buf[off + len] != ';') {
- ++len;
- }
- }
- return new Type(ARRAY, buf, off, len + 1);
- case 'L':
- len = 1;
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ len = 1;
+ while (buf[off + len] == '[') {
+ ++len;
+ }
+ if (buf[off + len] == 'L') {
+ ++len;
while (buf[off + len] != ';') {
++len;
}
- return new Type(OBJECT, buf, off + 1, len - 1);
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ case 'L':
+ len = 1;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off + 1, len - 1);
// case '(':
- default:
- return new Type(METHOD, buf, 0, buf.length);
+ default:
+ return new Type(METHOD, buf, off, buf.length - off);
}
}
@@ -474,12 +494,12 @@ public class Type {
/**
* Returns the sort of this Java type.
- *
- * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
- * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
- * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
- * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY},
- * {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
+ * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
+ * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
+ * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
+ * METHOD}.
*/
public int getSort() {
return sort;
@@ -488,7 +508,7 @@ public class Type {
/**
* Returns the number of dimensions of this array type. This method should
* only be used for an array type.
- *
+ *
* @return the number of dimensions of this array type.
*/
public int getDimensions() {
@@ -502,7 +522,7 @@ public class Type {
/**
* Returns the type of the elements of this array type. This method should
* only be used for an array type.
- *
+ *
* @return Returns the type of the elements of this array type.
*/
public Type getElementType() {
@@ -512,39 +532,39 @@ public class Type {
/**
* Returns the binary name of the class corresponding to this type. This
* method must not be used on method types.
- *
+ *
* @return the binary name of the class corresponding to this type.
*/
public String getClassName() {
switch (sort) {
- case VOID:
- return "void";
- case BOOLEAN:
- return "boolean";
- case CHAR:
- return "char";
- case BYTE:
- return "byte";
- case SHORT:
- return "short";
- case INT:
- return "int";
- case FLOAT:
- return "float";
- case LONG:
- return "long";
- case DOUBLE:
- return "double";
- case ARRAY:
- StringBuffer b = new StringBuffer(getElementType().getClassName());
- for (int i = getDimensions(); i > 0; --i) {
- b.append("[]");
- }
- return b.toString();
- case OBJECT:
- return new String(buf, off, len).replace('/', '.');
- default:
- return null;
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ b.append("[]");
+ }
+ return b.toString();
+ case OBJECT:
+ return new String(buf, off, len).replace('/', '.');
+ default:
+ return null;
}
}
@@ -553,7 +573,7 @@ public class Type {
* array type. The internal name of a class is its fully qualified name (as
* returned by Class.getName(), where '.' are replaced by '/'. This method
* should only be used for an object or array type.
- *
+ *
* @return the internal name of the class corresponding to this object type.
*/
public String getInternalName() {
@@ -563,7 +583,7 @@ public class Type {
/**
* Returns the argument types of methods of this type. This method should
* only be used for method types.
- *
+ *
* @return the argument types of methods of this type.
*/
public Type[] getArgumentTypes() {
@@ -573,7 +593,7 @@ public class Type {
/**
* Returns the return type of methods of this type. This method should only
* be used for method types.
- *
+ *
* @return the return type of methods of this type.
*/
public Type getReturnType() {
@@ -583,12 +603,13 @@ public class Type {
/**
* Returns the size of the arguments and of the return value of methods of
* this type. This method should only be used for method types.
- *
+ *
* @return the size of the arguments (plus one for the implicit this
* argument), argSize, and the size of the return value, retSize,
- * packed into a single int i = <tt>(argSize << 2) | retSize</tt>
- * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
- * <tt>i & 0x03</tt>).
+ * packed into a single
+ * int i = <tt>(argSize << 2) | retSize</tt>
+ * (argSize is therefore equal to <tt>i >> 2</tt>,
+ * and retSize to <tt>i & 0x03</tt>).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@@ -600,7 +621,7 @@ public class Type {
/**
* Returns the descriptor corresponding to this Java type.
- *
+ *
* @return the descriptor corresponding to this Java type.
*/
public String getDescriptor() {
@@ -612,16 +633,16 @@ public class Type {
/**
* Returns the descriptor corresponding to the given argument and return
* types.
- *
- * @param returnType the return type of the method.
- * @param argumentTypes the argument types of the method.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
* @return the descriptor corresponding to the given argument and return
* types.
*/
- public static String getMethodDescriptor(
- final Type returnType,
- final Type... argumentTypes)
- {
+ public static String getMethodDescriptor(final Type returnType,
+ final Type... argumentTypes) {
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
@@ -635,12 +656,14 @@ public class Type {
/**
* Appends the descriptor corresponding to this Java type to the given
* string buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
*/
private void getDescriptor(final StringBuffer buf) {
if (this.buf == null) {
- // descriptor is in byte 3 of 'off' for primitive types (buf == null)
+ // descriptor is in byte 3 of 'off' for primitive types (buf ==
+ // null)
buf.append((char) ((off & 0xFF000000) >>> 24));
} else if (sort == OBJECT) {
buf.append('L');
@@ -660,8 +683,9 @@ public class Type {
* Returns the internal name of the given class. The internal name of a
* class is its fully qualified name, as returned by Class.getName(), where
* '.' are replaced by '/'.
- *
- * @param c an object or array class.
+ *
+ * @param c
+ * an object or array class.
* @return the internal name of the given class.
*/
public static String getInternalName(final Class<?> c) {
@@ -670,8 +694,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given Java type.
- *
- * @param c an object class, a primitive class or an array class.
+ *
+ * @param c
+ * an object class, a primitive class or an array class.
* @return the descriptor corresponding to the given class.
*/
public static String getDescriptor(final Class<?> c) {
@@ -682,8 +707,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given constructor.
- *
- * @param c a {@link Constructor Constructor} object.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
* @return the descriptor of the given constructor.
*/
public static String getConstructorDescriptor(final Constructor<?> c) {
@@ -698,8 +724,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given method.
- *
- * @param m a {@link Method Method} object.
+ *
+ * @param m
+ * a {@link Method Method} object.
* @return the descriptor of the given method.
*/
public static String getMethodDescriptor(final Method m) {
@@ -716,9 +743,11 @@ public class Type {
/**
* Appends the descriptor of the given class to the given string buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
- * @param c the class whose descriptor must be computed.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
+ * @param c
+ * the class whose descriptor must be computed.
*/
private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
Class<?> d = c;
@@ -770,7 +799,7 @@ public class Type {
/**
* Returns the size of values of this type. This method must not be used for
* method types.
- *
+ *
* @return the size of values of this type, i.e., 2 for <tt>long</tt> and
* <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
*/
@@ -782,10 +811,11 @@ public class Type {
/**
* Returns a JVM instruction opcode adapted to this Java type. This method
* must not be used for method types.
- *
- * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
- * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
- * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ *
+ * @param opcode
+ * a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
+ * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
* @return an opcode that is similar to the given opcode, but adapted to
* this Java type. For example, if this type is <tt>float</tt> and
* <tt>opcode</tt> is IRETURN, this method returns FRETURN.
@@ -808,8 +838,9 @@ public class Type {
/**
* Tests if the given object is equal to this type.
- *
- * @param o the object to be compared to this type.
+ *
+ * @param o
+ * the object to be compared to this type.
* @return <tt>true</tt> if the given object is equal to this type.
*/
@Override
@@ -839,7 +870,7 @@ public class Type {
/**
* Returns a hash code value for this type.
- *
+ *
* @return a hash code value for this type.
*/
@Override
@@ -855,7 +886,7 @@ public class Type {
/**
* Returns a string representation of this type.
- *
+ *
* @return the descriptor of this type.
*/
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
new file mode 100644
index 0000000..b772d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
@@ -0,0 +1,193 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static
+ * inner type within an enclosing type.
+ *
+ * @author Eric Bruneton
+ */
+public class TypePath {
+
+ /**
+ * A type path step that steps into the element type of an array type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int ARRAY_ELEMENT = 0;
+
+ /**
+ * A type path step that steps into the nested type of a class type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int INNER_TYPE = 1;
+
+ /**
+ * A type path step that steps into the bound of a wildcard type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int WILDCARD_BOUND = 2;
+
+ /**
+ * A type path step that steps into a type argument of a generic type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int TYPE_ARGUMENT = 3;
+
+ /**
+ * The byte array where the path is stored, in Java class file format.
+ */
+ byte[] b;
+
+ /**
+ * The offset of the first byte of the type path in 'b'.
+ */
+ int offset;
+
+ /**
+ * Creates a new type path.
+ *
+ * @param b
+ * the byte array containing the type path in Java class file
+ * format.
+ * @param offset
+ * the offset of the first byte of the type path in 'b'.
+ */
+ TypePath(byte[] b, int offset) {
+ this.b = b;
+ this.offset = offset;
+ }
+
+ /**
+ * Returns the length of this path.
+ *
+ * @return the length of this path.
+ */
+ public int getLength() {
+ return b[offset];
+ }
+
+ /**
+ * Returns the value of the given step of this path.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
+ * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ */
+ public int getStep(int index) {
+ return b[offset + 2 * index + 1];
+ }
+
+ /**
+ * Returns the index of the type argument that the given step is stepping
+ * into. This method should only be used for steps whose value is
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return the index of the type argument that the given step is stepping
+ * into.
+ */
+ public int getStepArgument(int index) {
+ return b[offset + 2 * index + 2];
+ }
+
+ /**
+ * Converts a type path in string form, in the format used by
+ * {@link #toString()}, into a TypePath object.
+ *
+ * @param typePath
+ * a type path in string form, in the format used by
+ * {@link #toString()}. May be null or empty.
+ * @return the corresponding TypePath object, or null if the path is empty.
+ */
+ public static TypePath fromString(final String typePath) {
+ if (typePath == null || typePath.length() == 0) {
+ return null;
+ }
+ int n = typePath.length();
+ ByteVector out = new ByteVector(n);
+ out.putByte(0);
+ for (int i = 0; i < n;) {
+ char c = typePath.charAt(i++);
+ if (c == '[') {
+ out.put11(ARRAY_ELEMENT, 0);
+ } else if (c == '.') {
+ out.put11(INNER_TYPE, 0);
+ } else if (c == '*') {
+ out.put11(WILDCARD_BOUND, 0);
+ } else if (c >= '0' && c <= '9') {
+ int typeArg = c - '0';
+ while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
+ typeArg = typeArg * 10 + c - '0';
+ i += 1;
+ }
+ out.put11(TYPE_ARGUMENT, typeArg);
+ }
+ }
+ out.data[0] = (byte) (out.length / 2);
+ return new TypePath(out.data, 0);
+ }
+
+ /**
+ * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
+ * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
+ * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
+ * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
+ * argument index in decimal form.
+ */
+ @Override
+ public String toString() {
+ int length = getLength();
+ StringBuilder result = new StringBuilder(length * 2);
+ for (int i = 0; i < length; ++i) {
+ switch (getStep(i)) {
+ case ARRAY_ELEMENT:
+ result.append('[');
+ break;
+ case INNER_TYPE:
+ result.append('.');
+ break;
+ case WILDCARD_BOUND:
+ result.append('*');
+ break;
+ case TYPE_ARGUMENT:
+ result.append(getStepArgument(i));
+ break;
+ default:
+ result.append('_');
+ }
+ }
+ return result.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
new file mode 100644
index 0000000..d518864
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -0,0 +1,452 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or
+ * on an instruction. Such a reference designates the part of the class where
+ * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
+ * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
+ * declaration, etc).
+ *
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER = 0x00;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER = 0x01;
+
+ /**
+ * The sort of type references that target the super class of a class or one
+ * of the interfaces it implements. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_EXTENDS = 0x10;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+ /**
+ * The sort of type references that target the type of a field. See
+ * {@link #getSort getSort}.
+ */
+ public final static int FIELD = 0x13;
+
+ /**
+ * The sort of type references that target the return type of a method. See
+ * {@link #getSort getSort}.
+ */
+ public final static int METHOD_RETURN = 0x14;
+
+ /**
+ * The sort of type references that target the receiver type of a method.
+ * See {@link #getSort getSort}.
+ */
+ public final static int METHOD_RECEIVER = 0x15;
+
+ /**
+ * The sort of type references that target the type of a formal parameter of
+ * a method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_FORMAL_PARAMETER = 0x16;
+
+ /**
+ * The sort of type references that target the type of an exception declared
+ * in the throws clause of a method. See {@link #getSort getSort}.
+ */
+ public final static int THROWS = 0x17;
+
+ /**
+ * The sort of type references that target the type of a local variable in a
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int LOCAL_VARIABLE = 0x40;
+
+ /**
+ * The sort of type references that target the type of a resource variable
+ * in a method. See {@link #getSort getSort}.
+ */
+ public final static int RESOURCE_VARIABLE = 0x41;
+
+ /**
+ * The sort of type references that target the type of the exception of a
+ * 'catch' clause in a method. See {@link #getSort getSort}.
+ */
+ public final static int EXCEPTION_PARAMETER = 0x42;
+
+ /**
+ * The sort of type references that target the type declared in an
+ * 'instanceof' instruction. See {@link #getSort getSort}.
+ */
+ public final static int INSTANCEOF = 0x43;
+
+ /**
+ * The sort of type references that target the type of the object created by
+ * a 'new' instruction. See {@link #getSort getSort}.
+ */
+ public final static int NEW = 0x44;
+
+ /**
+ * The sort of type references that target the receiver type of a
+ * constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE = 0x45;
+
+ /**
+ * The sort of type references that target the receiver type of a method
+ * reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE = 0x46;
+
+ /**
+ * The sort of type references that target the type declared in an explicit
+ * or implicit cast instruction. See {@link #getSort getSort}.
+ */
+ public final static int CAST = 0x47;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor call. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method call. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+ /**
+ * The type reference value in Java class file format.
+ */
+ private int value;
+
+ /**
+ * Creates a new TypeReference.
+ *
+ * @param typeRef
+ * the int encoded value of the type reference, as received in a
+ * visit method related to type annotations, like
+ * visitTypeAnnotation.
+ */
+ public TypeReference(int typeRef) {
+ this.value = typeRef;
+ }
+
+ /**
+ * Returns a type reference of the given sort.
+ *
+ * @param sort
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}.
+ * @return a type reference of the given sort.
+ */
+ public static TypeReference newTypeReference(int sort) {
+ return new TypeReference(sort << 24);
+ }
+
+ /**
+ * Returns a reference to a type parameter of a generic class or method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @return a reference to the given generic class or method type parameter.
+ */
+ public static TypeReference newTypeParameterReference(int sort,
+ int paramIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to a type parameter bound of a generic class or
+ * method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @param boundIndex
+ * the type bound index within the above type parameters.
+ * @return a reference to the given generic class or method type parameter
+ * bound.
+ */
+ public static TypeReference newTypeParameterBoundReference(int sort,
+ int paramIndex, int boundIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16)
+ | (boundIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the super class or to an interface of the
+ * 'implements' clause of a class.
+ *
+ * @param itfIndex
+ * the index of an interface in the 'implements' clause of a
+ * class, or -1 to reference the super class of the class.
+ * @return a reference to the given super type of a class.
+ */
+ public static TypeReference newSuperTypeReference(int itfIndex) {
+ itfIndex &= 0xFFFF;
+ return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a formal parameter of a method.
+ *
+ * @param paramIndex
+ * the formal parameter index.
+ *
+ * @return a reference to the type of the given method formal parameter.
+ */
+ public static TypeReference newFormalParameterReference(int paramIndex) {
+ return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
+ | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to the type of an exception, in a 'throws' clause of
+ * a method.
+ *
+ * @param exceptionIndex
+ * the index of an exception in a 'throws' clause of a method.
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newExceptionReference(int exceptionIndex) {
+ return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of the exception declared in a 'catch'
+ * clause of a method.
+ *
+ * @param tryCatchBlockIndex
+ * the index of a try catch block (using the order in which they
+ * are visited with visitTryCatchBlock).
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
+ return new TypeReference((EXCEPTION_PARAMETER << 24)
+ | (tryCatchBlockIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a type argument in a constructor or
+ * method call or reference.
+ *
+ * @param sort
+ * {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ * @param argIndex
+ * the type argument index.
+ *
+ * @return a reference to the type of the given type argument.
+ */
+ public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
+ return new TypeReference((sort << 24) | argIndex);
+ }
+
+ /**
+ * Returns the sort of this type reference.
+ *
+ * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_EXTENDS CLASS_EXTENDS},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
+ * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ */
+ public int getSort() {
+ return value >>> 24;
+ }
+
+ /**
+ * Returns the index of the type parameter referenced by this type
+ * reference. This method must only be used for type references whose sort
+ * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the type parameter bound, within the type parameter
+ * {@link #getTypeParameterIndex}, referenced by this type reference. This
+ * method must only be used for type references whose sort is
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter bound index.
+ */
+ public int getTypeParameterBoundIndex() {
+ return (value & 0x0000FF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the "super type" of a class that is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
+ *
+ * @return the index of an interface in the 'implements' clause of a class,
+ * or -1 if this type reference references the type of the super
+ * class.
+ */
+ public int getSuperTypeIndex() {
+ return (short) ((value & 0x00FFFF00) >> 8);
+ }
+
+ /**
+ * Returns the index of the formal parameter whose type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
+ *
+ * @return a formal parameter index.
+ */
+ public int getFormalParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the exception, in a 'throws' clause of a method,
+ * whose type is referenced by this type reference. This method must only be
+ * used for type references whose sort is {@link #THROWS THROWS}.
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getExceptionIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the try catch block (using the order in which they
+ * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getTryCatchBlockIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the type argument referenced by this type reference.
+ * This method must only be used for type references whose sort is
+ * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeArgumentIndex() {
+ return value & 0xFF;
+ }
+
+ /**
+ * Returns the int encoded value of this type reference, suitable for use in
+ * visit methods related to type annotations, like visitTypeAnnotation.
+ *
+ * @return the int encoded value of this type reference.
+ */
+ public int getValue() {
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
new file mode 100644
index 0000000..a53995b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
@@ -0,0 +1,646 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} to insert before, after and around
+ * advices in methods and constructors.
+ * <p>
+ * The behavior for constructors is like this:
+ * <ol>
+ *
+ * <li>as long as the INVOKESPECIAL for the object initialization has not been
+ * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
+ *
+ * <li>when this one is reached, it is only added in the ctor code visitor and a
+ * JP invoke is added</li>
+ *
+ * <li>after that, only the other code visitor receives the instructions</li>
+ *
+ * </ol>
+ *
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
+
+ private static final Object THIS = new Object();
+
+ private static final Object OTHER = new Object();
+
+ protected int methodAccess;
+
+ protected String methodDesc;
+
+ private boolean constructor;
+
+ private boolean superInitialized;
+
+ private List<Object> stackFrame;
+
+ private Map<Label, List<Object>> branches;
+
+ /**
+ * Creates a new {@link AdviceAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ protected AdviceAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc) {
+ super(api, mv, access, name, desc);
+ methodAccess = access;
+ methodDesc = desc;
+ constructor = "<init>".equals(name);
+ }
+
+ @Override
+ public void visitCode() {
+ mv.visitCode();
+ if (constructor) {
+ stackFrame = new ArrayList<Object>();
+ branches = new HashMap<Label, List<Object>>();
+ } else {
+ superInitialized = true;
+ onMethodEnter();
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ mv.visitLabel(label);
+ if (constructor && branches != null) {
+ List<Object> frame = branches.get(label);
+ if (frame != null) {
+ stackFrame = frame;
+ branches.remove(label);
+ }
+ }
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if (constructor) {
+ int s;
+ switch (opcode) {
+ case RETURN: // empty stack
+ onMethodExit(opcode);
+ break;
+ case IRETURN: // 1 before n/a after
+ case FRETURN: // 1 before n/a after
+ case ARETURN: // 1 before n/a after
+ case ATHROW: // 1 before n/a after
+ popValue();
+ onMethodExit(opcode);
+ break;
+ case LRETURN: // 2 before n/a after
+ case DRETURN: // 2 before n/a after
+ popValue();
+ popValue();
+ onMethodExit(opcode);
+ break;
+ case NOP:
+ case LALOAD: // remove 2 add 2
+ case DALOAD: // remove 2 add 2
+ case LNEG:
+ case DNEG:
+ case FNEG:
+ case INEG:
+ case L2D:
+ case D2L:
+ case F2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ case I2F:
+ case ARRAYLENGTH:
+ break;
+ case ACONST_NULL:
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ case F2L: // 1 before 2 after
+ case F2D:
+ case I2L:
+ case I2D:
+ pushValue(OTHER);
+ break;
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case IALOAD: // remove 2 add 1
+ case FALOAD: // remove 2 add 1
+ case AALOAD: // remove 2 add 1
+ case BALOAD: // remove 2 add 1
+ case CALOAD: // remove 2 add 1
+ case SALOAD: // remove 2 add 1
+ case POP:
+ case IADD:
+ case FADD:
+ case ISUB:
+ case LSHL: // 3 before 2 after
+ case LSHR: // 3 before 2 after
+ case LUSHR: // 3 before 2 after
+ case L2I: // 2 before 1 after
+ case L2F: // 2 before 1 after
+ case D2I: // 2 before 1 after
+ case D2F: // 2 before 1 after
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL: // 2 before 1 after
+ case FCMPG: // 2 before 1 after
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case MONITORENTER:
+ case MONITOREXIT:
+ popValue();
+ break;
+ case POP2:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LADD:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case DADD:
+ case DMUL:
+ case DSUB:
+ case DDIV:
+ case DREM:
+ popValue();
+ popValue();
+ break;
+ case IASTORE:
+ case FASTORE:
+ case AASTORE:
+ case BASTORE:
+ case CASTORE:
+ case SASTORE:
+ case LCMP: // 4 before 1 after
+ case DCMPL:
+ case DCMPG:
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case LASTORE:
+ case DASTORE:
+ popValue();
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case DUP:
+ pushValue(peekValue());
+ break;
+ case DUP_X1:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ break;
+ case DUP_X2:
+ s = stackFrame.size();
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ break;
+ case DUP2:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ break;
+ case DUP2_X1:
+ s = stackFrame.size();
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ break;
+ case DUP2_X2:
+ s = stackFrame.size();
+ stackFrame.add(s - 4, stackFrame.get(s - 1));
+ stackFrame.add(s - 4, stackFrame.get(s - 1));
+ break;
+ case SWAP:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ stackFrame.remove(s);
+ break;
+ }
+ } else {
+ switch (opcode) {
+ case RETURN:
+ case IRETURN:
+ case FRETURN:
+ case ARETURN:
+ case LRETURN:
+ case DRETURN:
+ case ATHROW:
+ onMethodExit(opcode);
+ break;
+ }
+ }
+ mv.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ super.visitVarInsn(opcode, var);
+ if (constructor) {
+ switch (opcode) {
+ case ILOAD:
+ case FLOAD:
+ pushValue(OTHER);
+ break;
+ case LLOAD:
+ case DLOAD:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case ALOAD:
+ pushValue(var == 0 ? THIS : OTHER);
+ break;
+ case ASTORE:
+ case ISTORE:
+ case FSTORE:
+ popValue();
+ break;
+ case LSTORE:
+ case DSTORE:
+ popValue();
+ popValue();
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ if (constructor) {
+ char c = desc.charAt(0);
+ boolean longOrDouble = c == 'J' || c == 'D';
+ switch (opcode) {
+ case GETSTATIC:
+ pushValue(OTHER);
+ if (longOrDouble) {
+ pushValue(OTHER);
+ }
+ break;
+ case PUTSTATIC:
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ }
+ break;
+ case PUTFIELD:
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ popValue();
+ }
+ break;
+ // case GETFIELD:
+ default:
+ if (longOrDouble) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ mv.visitIntInsn(opcode, operand);
+ if (constructor && opcode != NEWARRAY) {
+ pushValue(OTHER);
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ mv.visitLdcInsn(cst);
+ if (constructor) {
+ pushValue(OTHER);
+ if (cst instanceof Double || cst instanceof Long) {
+ pushValue(OTHER);
+ }
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ if (constructor) {
+ for (int i = 0; i < dims; i++) {
+ popValue();
+ }
+ pushValue(OTHER);
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ mv.visitTypeInsn(opcode, type);
+ // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
+ if (constructor && opcode == NEW) {
+ pushValue(OTHER);
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (constructor) {
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; i++) {
+ popValue();
+ if (types[i].getSize() == 2) {
+ popValue();
+ }
+ }
+ switch (opcode) {
+ // case INVOKESTATIC:
+ // break;
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ popValue(); // objectref
+ break;
+ case INVOKESPECIAL:
+ Object type = popValue(); // objectref
+ if (type == THIS && !superInitialized) {
+ onMethodEnter();
+ superInitialized = true;
+ // once super has been initialized it is no longer
+ // necessary to keep track of stack state
+ constructor = false;
+ }
+ break;
+ }
+
+ Type returnType = Type.getReturnType(desc);
+ if (returnType != Type.VOID_TYPE) {
+ pushValue(OTHER);
+ if (returnType.getSize() == 2) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ if (constructor) {
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; i++) {
+ popValue();
+ if (types[i].getSize() == 2) {
+ popValue();
+ }
+ }
+
+ Type returnType = Type.getReturnType(desc);
+ if (returnType != Type.VOID_TYPE) {
+ pushValue(OTHER);
+ if (returnType.getSize() == 2) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ mv.visitJumpInsn(opcode, label);
+ if (constructor) {
+ switch (opcode) {
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case IFNULL:
+ case IFNONNULL:
+ popValue();
+ break;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ popValue();
+ popValue();
+ break;
+ case JSR:
+ pushValue(OTHER);
+ break;
+ }
+ addBranch(label);
+ }
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ if (constructor) {
+ popValue();
+ addBranches(dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ if (constructor) {
+ popValue();
+ addBranches(dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
+ super.visitTryCatchBlock(start, end, handler, type);
+ if (constructor && !branches.containsKey(handler)) {
+ List<Object> stackFrame = new ArrayList<Object>();
+ stackFrame.add(OTHER);
+ branches.put(handler, stackFrame);
+ }
+ }
+
+ private void addBranches(final Label dflt, final Label[] labels) {
+ addBranch(dflt);
+ for (int i = 0; i < labels.length; i++) {
+ addBranch(labels[i]);
+ }
+ }
+
+ private void addBranch(final Label label) {
+ if (branches.containsKey(label)) {
+ return;
+ }
+ branches.put(label, new ArrayList<Object>(stackFrame));
+ }
+
+ private Object popValue() {
+ return stackFrame.remove(stackFrame.size() - 1);
+ }
+
+ private Object peekValue() {
+ return stackFrame.get(stackFrame.size() - 1);
+ }
+
+ private void pushValue(final Object o) {
+ stackFrame.add(o);
+ }
+
+ /**
+ * Called at the beginning of the method or after super class class call in
+ * the constructor. <br>
+ * <br>
+ *
+ * <i>Custom code can use or change all the local variables, but should not
+ * change state of the stack.</i>
+ */
+ protected void onMethodEnter() {
+ }
+
+ /**
+ * Called before explicit exit from the method using either return or throw.
+ * Top element on the stack contains the return value or exception instance.
+ * For example:
+ *
+ * <pre>
+ * public void onMethodExit(int opcode) {
+ * if(opcode==RETURN) {
+ * visitInsn(ACONST_NULL);
+ * } else if(opcode==ARETURN || opcode==ATHROW) {
+ * dup();
+ * } else {
+ * if(opcode==LRETURN || opcode==DRETURN) {
+ * dup2();
+ * } else {
+ * dup();
+ * }
+ * box(Type.getReturnType(this.methodDesc));
+ * }
+ * visitIntInsn(SIPUSH, opcode);
+ * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+ * }
+ *
+ * // an actual call back method
+ * public static void onExit(Object param, int opcode) {
+ * ...
+ * </pre>
+ *
+ * <br>
+ * <br>
+ *
+ * <i>Custom code can use or change all the local variables, but should not
+ * change state of the stack.</i>
+ *
+ * @param opcode
+ * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN
+ * or ATHROW
+ *
+ */
+ protected void onMethodExit(int opcode) {
+ }
+
+ // TODO onException, onMethodCall
+}
[21/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
index dced23c..8c8e29b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassVisitor.java
@@ -30,19 +30,20 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java class. The methods of this class must be called
- * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * A visitor to visit a Java class. The methods of this class must be called in
+ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
- * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
- *
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
+ * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
+ * <tt>visitEnd</tt>.
+ *
* @author Eric Bruneton
*/
public abstract class ClassVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -54,9 +55,10 @@ public abstract class ClassVisitor {
/**
* Constructs a new {@link ClassVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassVisitor(final int api) {
this(api, null);
@@ -64,47 +66,49 @@ public abstract class ClassVisitor {
/**
* Constructs a new {@link ClassVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param cv the class visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param cv
+ * the class visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public ClassVisitor(final int api, final ClassVisitor cv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.cv = cv;
}
/**
* Visits the header of the class.
- *
- * @param version the class version.
- * @param access the class's access flags (see {@link Opcodes}). This
- * parameter also indicates if the class is deprecated.
- * @param name the internal name of the class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param signature the signature of this class. May be <tt>null</tt> if
- * the class is not a generic one, and does not extend or implement
- * generic classes or interfaces.
- * @param superName the internal of name of the super class (see
- * {@link Type#getInternalName() getInternalName}). For interfaces,
- * the super class is {@link Object}. May be <tt>null</tt>, but
- * only for the {@link Object} class.
- * @param interfaces the internal names of the class's interfaces (see
- * {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param version
+ * the class version.
+ * @param access
+ * the class's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the class is deprecated.
+ * @param name
+ * the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param signature
+ * the signature of this class. May be <tt>null</tt> if the class
+ * is not a generic one, and does not extend or implement generic
+ * classes or interfaces.
+ * @param superName
+ * the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For
+ * interfaces, the super class is {@link Object}. May be
+ * <tt>null</tt>, but only for the {@link Object} class.
+ * @param interfaces
+ * the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- public void visit(
- int version,
- int access,
- String name,
- String signature,
- String superName,
- String[] interfaces)
- {
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
}
@@ -112,12 +116,14 @@ public abstract class ClassVisitor {
/**
* Visits the source of the class.
- *
- * @param source the name of the source file from which the class was
- * compiled. May be <tt>null</tt>.
- * @param debug additional debug information to compute the correspondance
- * between source and compiled elements of the class. May be
- * <tt>null</tt>.
+ *
+ * @param source
+ * the name of the source file from which the class was compiled.
+ * May be <tt>null</tt>.
+ * @param debug
+ * additional debug information to compute the correspondance
+ * between source and compiled elements of the class. May be
+ * <tt>null</tt>.
*/
public void visitSource(String source, String debug) {
if (cv != null) {
@@ -128,26 +134,31 @@ public abstract class ClassVisitor {
/**
* Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class.
- *
- * @param owner internal name of the enclosing class of the class.
- * @param name the name of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
- * @param desc the descriptor of the method that contains the class, or
- * <tt>null</tt> if the class is not enclosed in a method of its
- * enclosing class.
+ *
+ * @param owner
+ * internal name of the enclosing class of the class.
+ * @param name
+ * the name of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ * @param desc
+ * the descriptor of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
- if (cv != null) {
+ if (cv != null) {
cv.visitOuterClass(owner, name, desc);
}
}
/**
* Visits an annotation of the class.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -159,9 +170,43 @@ public abstract class ClassVisitor {
}
/**
+ * Visits an annotation on a type in the class signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
+ * CLASS_TYPE_PARAMETER},
+ * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
+ * CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (cv != null) {
+ return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a non standard attribute of the class.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (cv != null) {
@@ -172,24 +217,23 @@ public abstract class ClassVisitor {
/**
* Visits information about an inner class. This inner class is not
* necessarily a member of the class being visited.
- *
- * @param name the internal name of an inner class (see
- * {@link Type#getInternalName() getInternalName}).
- * @param outerName the internal name of the class to which the inner class
- * belongs (see {@link Type#getInternalName() getInternalName}). May
- * be <tt>null</tt> for not member classes.
- * @param innerName the (simple) name of the inner class inside its
- * enclosing class. May be <tt>null</tt> for anonymous inner
- * classes.
- * @param access the access flags of the inner class as originally declared
- * in the enclosing class.
+ *
+ * @param name
+ * the internal name of an inner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param outerName
+ * the internal name of the class to which the inner class
+ * belongs (see {@link Type#getInternalName() getInternalName}).
+ * May be <tt>null</tt> for not member classes.
+ * @param innerName
+ * the (simple) name of the inner class inside its enclosing
+ * class. May be <tt>null</tt> for anonymous inner classes.
+ * @param access
+ * the access flags of the inner class as originally declared in
+ * the enclosing class.
*/
- public void visitInnerClass(
- String name,
- String outerName,
- String innerName,
- int access)
- {
+ public void visitInnerClass(String name, String outerName,
+ String innerName, int access) {
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
@@ -197,34 +241,33 @@ public abstract class ClassVisitor {
/**
* Visits a field of the class.
- *
- * @param access the field's access flags (see {@link Opcodes}). This
- * parameter also indicates if the field is synthetic and/or
- * deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- * @param signature the field's signature. May be <tt>null</tt> if the
- * field's type does not use generic types.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must
- * be an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String} (for <tt>int</tt>,
- * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
- * respectively). <i>This parameter is only used for static fields</i>.
- * Its value is ignored for non static fields, which must be
- * initialized through bytecode instructions in constructors or
- * methods.
+ *
+ * @param access
+ * the field's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt> if the field's
+ * type does not use generic types.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String} (for <tt>int</tt>,
+ * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+ * respectively). <i>This parameter is only used for static
+ * fields</i>. Its value is ignored for non static fields, which
+ * must be initialized through bytecode instructions in
+ * constructors or methods.
* @return a visitor to visit field annotations and attributes, or
- * <tt>null</tt> if this class visitor is not interested in
- * visiting these annotations and attributes.
+ * <tt>null</tt> if this class visitor is not interested in visiting
+ * these annotations and attributes.
*/
- public FieldVisitor visitField(
- int access,
- String name,
- String desc,
- String signature,
- Object value)
- {
+ public FieldVisitor visitField(int access, String name, String desc,
+ String signature, Object value) {
if (cv != null) {
return cv.visitField(access, name, desc, signature, value);
}
@@ -233,31 +276,31 @@ public abstract class ClassVisitor {
/**
* Visits a method of the class. This method <i>must</i> return a new
- * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
- * called, i.e., it should not return a previously returned visitor.
- *
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param signature the method's signature. May be <tt>null</tt> if the
- * method parameters, return type and exceptions do not use generic
- * types.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
+ * i.e., it should not return a previously returned visitor.
+ *
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt> if the method
+ * parameters, return type and exceptions do not use generic
+ * types.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
* @return an object to visit the byte code of the method, or <tt>null</tt>
* if this class visitor is not interested in visiting the code of
* this method.
*/
- public MethodVisitor visitMethod(
- int access,
- String name,
- String desc,
- String signature,
- String[] exceptions)
- {
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, desc, signature, exceptions);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
index ab7547b..6cd89a5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassWriter.java
@@ -35,7 +35,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* file format. It can be used alone, to generate a Java class "from scratch",
* or with one or more {@link ClassReader ClassReader} and adapter class visitor
* to generate a modified class from one or more existing Java classes.
- *
+ *
* @author Eric Bruneton
*/
public class ClassWriter extends ClassVisitor {
@@ -47,7 +47,7 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
* method will be ignored, and computed automatically from the signature and
* the bytecode of each method.
- *
+ *
* @see #ClassWriter(int)
*/
public static final int COMPUTE_MAXS = 1;
@@ -60,18 +60,24 @@ public class ClassWriter extends ClassVisitor {
* {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
* recomputed from the bytecode. In other words, computeFrames implies
* computeMaxs.
- *
+ *
* @see #ClassWriter(int)
*/
public static final int COMPUTE_FRAMES = 2;
/**
- * Pseudo access flag to distinguish between the synthetic attribute and
- * the synthetic access flag.
+ * Pseudo access flag to distinguish between the synthetic attribute and the
+ * synthetic access flag.
*/
static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
/**
+ * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
+ */
+ static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
+ / Opcodes.ACC_SYNTHETIC;
+
+ /**
* The type of instructions without any argument.
*/
static final int NOARG_INSN = 0;
@@ -238,8 +244,8 @@ public class ClassWriter extends ClassVisitor {
/**
* The base value for all CONSTANT_MethodHandle constant pool items.
- * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
- * 9 different items.
+ * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
+ * different items.
*/
static final int HANDLE_BASE = 20;
@@ -266,9 +272,8 @@ public class ClassWriter extends ClassVisitor {
static final int TYPE_MERGED = 32;
/**
- * The type of BootstrapMethods items. These items are stored in a
- * special class attribute named BootstrapMethods and
- * not in the constant pool.
+ * The type of BootstrapMethods items. These items are stored in a special
+ * class attribute named BootstrapMethods and not in the constant pool.
*/
static final int BSM = 33;
@@ -327,10 +332,10 @@ public class ClassWriter extends ClassVisitor {
* necessarily be stored in the constant pool. This type table is used by
* the control flow and data flow analysis algorithm used to compute stack
* map frames from scratch. This array associates to each index <tt>i</tt>
- * the Item whose index is <tt>i</tt>. All Item objects stored in this
- * array are also stored in the {@link #items} hash table. These two arrays
- * allow to retrieve an Item from its index or, conversely, to get the index
- * of an Item from its value. Each Item stores an internal name in its
+ * the Item whose index is <tt>i</tt>. All Item objects stored in this array
+ * are also stored in the {@link #items} hash table. These two arrays allow
+ * to retrieve an Item from its index or, conversely, to get the index of an
+ * Item from its value. Each Item stores an internal name in its
* {@link Item#strVal1} field.
*/
Item[] typeTable;
@@ -412,6 +417,16 @@ public class ClassWriter extends ClassVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this class.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this class.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The non standard attributes of this class.
*/
private Attribute attrs;
@@ -439,16 +454,16 @@ public class ClassWriter extends ClassVisitor {
/**
* The fields of this class. These fields are stored in a linked list of
* {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the first element of
- * this list.
+ * {@link FieldWriter#fv} field. This field stores the first element of this
+ * list.
*/
FieldWriter firstField;
/**
* The fields of this class. These fields are stored in a linked list of
* {@link FieldWriter} objects, linked to each other by their
- * {@link FieldWriter#fv} field. This field stores the last element of
- * this list.
+ * {@link FieldWriter#fv} field. This field stores the last element of this
+ * list.
*/
FieldWriter lastField;
@@ -463,8 +478,8 @@ public class ClassWriter extends ClassVisitor {
/**
* The methods of this class. These methods are stored in a linked list of
* {@link MethodWriter} objects, linked to each other by their
- * {@link MethodWriter#mv} field. This field stores the last element of
- * this list.
+ * {@link MethodWriter#mv} field. This field stores the last element of this
+ * list.
*/
MethodWriter lastMethod;
@@ -472,12 +487,12 @@ public class ClassWriter extends ClassVisitor {
* <tt>true</tt> if the maximum stack size and number of local variables
* must be automatically computed.
*/
- private final boolean computeMaxs;
+ private boolean computeMaxs;
/**
* <tt>true</tt> if the stack map frames must be recomputed from scratch.
*/
- private final boolean computeFrames;
+ private boolean computeFrames;
/**
* <tt>true</tt> if the stack map tables of this class are invalid. The
@@ -583,12 +598,14 @@ public class ClassWriter extends ClassVisitor {
/**
* Constructs a new {@link ClassWriter} object.
- *
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ *
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final int flags) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
index = 1;
pool = new ByteVector();
items = new Item[256];
@@ -605,27 +622,33 @@ public class ClassWriter extends ClassVisitor {
* Constructs a new {@link ClassWriter} object and enables optimizations for
* "mostly add" bytecode transformations. These optimizations are the
* following:
- *
- * <ul> <li>The constant pool from the original class is copied as is in the
- * new class, which saves time. New constant pool entries will be added at
- * the end if necessary, but unused constant pool entries <i>won't be
- * removed</i>.</li> <li>Methods that are not transformed are copied as is
- * in the new class, directly from the original class bytecode (i.e. without
- * emitting visit events for all the method instructions), which saves a
- * <i>lot</i> of time. Untransformed methods are detected by the fact that
- * the {@link ClassReader} receives {@link MethodVisitor} objects that come
- * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
- * instance).</li> </ul>
- *
- * @param classReader the {@link ClassReader} used to read the original
- * class. It will be used to copy the entire constant pool from the
- * original class and also to copy other fragments of original
- * bytecode where applicable.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. <i>These option flags do not affect methods that
- * are copied as is in the new class. This means that the maximum
- * stack size nor the stack frames will be computed for these
- * methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ *
+ * <ul>
+ * <li>The constant pool from the original class is copied as is in the new
+ * class, which saves time. New constant pool entries will be added at the
+ * end if necessary, but unused constant pool entries <i>won't be
+ * removed</i>.</li>
+ * <li>Methods that are not transformed are copied as is in the new class,
+ * directly from the original class bytecode (i.e. without emitting visit
+ * events for all the method instructions), which saves a <i>lot</i> of
+ * time. Untransformed methods are detected by the fact that the
+ * {@link ClassReader} receives {@link MethodVisitor} objects that come from
+ * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+ * instance).</li>
+ * </ul>
+ *
+ * @param classReader
+ * the {@link ClassReader} used to read the original class. It
+ * will be used to copy the entire constant pool from the
+ * original class and also to copy other fragments of original
+ * bytecode where applicable.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. <i>These option flags do not affect methods
+ * that are copied as is in the new class. This means that the
+ * maximum stack size nor the stack frames will be computed for
+ * these methods</i>. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
*/
public ClassWriter(final ClassReader classReader, final int flags) {
this(flags);
@@ -638,14 +661,9 @@ public class ClassWriter extends ClassVisitor {
// ------------------------------------------------------------------------
@Override
- public final void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public final void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces) {
this.version = version;
this.access = access;
this.name = newClass(name);
@@ -669,16 +687,14 @@ public class ClassWriter extends ClassVisitor {
sourceFile = newUTF8(file);
}
if (debug != null) {
- sourceDebug = new ByteVector().putUTF8(debug);
+ sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+ Integer.MAX_VALUE);
}
}
@Override
- public final void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public final void visitOuterClass(final String owner, final String name,
+ final String desc) {
enclosingMethodOwner = newClass(owner);
if (name != null && desc != null) {
enclosingMethod = newNameType(name, desc);
@@ -686,10 +702,8 @@ public class ClassWriter extends ClassVisitor {
}
@Override
- public final AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public final AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -708,55 +722,76 @@ public class ClassWriter extends ClassVisitor {
}
@Override
+ public final AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public final void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
}
@Override
- public final void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
if (innerClasses == null) {
innerClasses = new ByteVector();
}
- ++innerClassesCount;
- innerClasses.putShort(name == null ? 0 : newClass(name));
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
+ // �4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+ // constant_pool table which represents a class or interface C that is
+ // not a package member must have exactly one corresponding entry in the
+ // classes array". To avoid duplicates we keep track in the intVal field
+ // of the Item of each CONSTANT_Class_info entry C whether an inner
+ // class entry has already been added for C (this field is unused for
+ // class entries, and changing its value does not change the hashcode
+ // and equality tests). If so we store the index of this inner class
+ // entry (plus one) in intVal. This hack allows duplicate detection in
+ // O(1) time.
+ Item nameItem = newClassItem(name);
+ if (nameItem.intVal == 0) {
+ ++innerClassesCount;
+ innerClasses.putShort(nameItem.index);
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ nameItem.intVal = innerClassesCount;
+ } else {
+ // Compare the inner classes entry nameItem.intVal - 1 with the
+ // arguments of this method and throw an exception if there is a
+ // difference?
+ }
}
@Override
- public final FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public final FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
return new FieldWriter(this, access, name, desc, signature, value);
}
@Override
- public final MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- return new MethodWriter(this,
- access,
- name,
- desc,
- signature,
- exceptions,
- computeMaxs,
- computeFrames);
+ public final MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ return new MethodWriter(this, access, name, desc, signature,
+ exceptions, computeMaxs, computeFrames);
}
@Override
@@ -769,11 +804,11 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the bytecode of the class that was build with this class writer.
- *
+ *
* @return the bytecode of the class that was build with this class writer.
*/
public byte[] toByteArray() {
- if (index > Short.MAX_VALUE) {
+ if (index > 0xFFFF) {
throw new RuntimeException("Class file too large!");
}
// computes the real size of the bytecode of this class
@@ -793,8 +828,9 @@ public class ClassWriter extends ClassVisitor {
mb = (MethodWriter) mb.mv;
}
int attributeCount = 0;
- if (bootstrapMethods != null) { // we put it as first argument in order
- // to improve a bit ClassReader.copyBootstrapMethods
+ if (bootstrapMethods != null) {
+ // we put it as first attribute in order to improve a bit
+ // ClassReader.copyBootstrapMethods
++attributeCount;
size += 8 + bootstrapMethods.length;
newUTF8("BootstrapMethods");
@@ -811,7 +847,7 @@ public class ClassWriter extends ClassVisitor {
}
if (sourceDebug != null) {
++attributeCount;
- size += sourceDebug.length + 4;
+ size += sourceDebug.length + 6;
newUTF8("SourceDebugExtension");
}
if (enclosingMethodOwner != 0) {
@@ -824,12 +860,13 @@ public class ClassWriter extends ClassVisitor {
size += 6;
newUTF8("Deprecated");
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
- size += 6;
- newUTF8("Synthetic");
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Synthetic");
+ }
}
if (innerClasses != null) {
++attributeCount;
@@ -846,6 +883,16 @@ public class ClassWriter extends ClassVisitor {
size += 8 + ianns.getSize();
newUTF8("RuntimeInvisibleAnnotations");
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ size += 8 + tanns.getSize();
+ newUTF8("RuntimeVisibleTypeAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ size += 8 + itanns.getSize();
+ newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
if (attrs != null) {
attributeCount += attrs.getCount();
size += attrs.getSize(this, null, 0, -1, -1);
@@ -856,9 +903,8 @@ public class ClassWriter extends ClassVisitor {
ByteVector out = new ByteVector(size);
out.putInt(0xCAFEBABE).putInt(version);
out.putShort(index).putByteArray(pool.data, 0, pool.length);
- int mask = Opcodes.ACC_DEPRECATED
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
out.putShort(access & ~mask).putShort(name).putShort(superName);
out.putShort(interfaceCount);
for (int i = 0; i < interfaceCount; ++i) {
@@ -877,9 +923,10 @@ public class ClassWriter extends ClassVisitor {
mb = (MethodWriter) mb.mv;
}
out.putShort(attributeCount);
- if (bootstrapMethods != null) { // should be the first class attribute ?
+ if (bootstrapMethods != null) {
out.putShort(newUTF8("BootstrapMethods"));
- out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+ out.putInt(bootstrapMethods.length + 2).putShort(
+ bootstrapMethodsCount);
out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
}
if (ClassReader.SIGNATURES && signature != 0) {
@@ -889,9 +936,9 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
}
if (sourceDebug != null) {
- int len = sourceDebug.length - 2;
+ int len = sourceDebug.length;
out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
- out.putByteArray(sourceDebug.data, 2, len);
+ out.putByteArray(sourceDebug.data, 0, len);
}
if (enclosingMethodOwner != 0) {
out.putShort(newUTF8("EnclosingMethod")).putInt(4);
@@ -900,10 +947,11 @@ public class ClassWriter extends ClassVisitor {
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(newUTF8("Deprecated")).putInt(0);
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(newUTF8("Synthetic")).putInt(0);
+ }
}
if (innerClasses != null) {
out.putShort(newUTF8("InnerClasses"));
@@ -918,13 +966,34 @@ public class ClassWriter extends ClassVisitor {
out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (attrs != null) {
attrs.put(this, null, 0, -1, -1, out);
}
if (invalidFrames) {
- ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
- new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
- return cw.toByteArray();
+ anns = null;
+ ianns = null;
+ attrs = null;
+ innerClassesCount = 0;
+ innerClasses = null;
+ bootstrapMethodsCount = 0;
+ bootstrapMethods = null;
+ firstField = null;
+ lastField = null;
+ firstMethod = null;
+ lastMethod = null;
+ computeMaxs = false;
+ computeFrames = true;
+ invalidFrames = false;
+ new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+ return toByteArray();
}
return out.data;
}
@@ -936,11 +1005,12 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a number or string constant to the constant pool of the class being
* build. Does nothing if the constant pool already contains a similar item.
- *
- * @param cst the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double}, a {@link String} or a
- * {@link Type}.
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double}, a {@link String} or a
+ * {@link Type}.
* @return a new or already existing constant item with the given value.
*/
Item newConstItem(final Object cst) {
@@ -973,12 +1043,12 @@ public class ClassWriter extends ClassVisitor {
} else if (cst instanceof Type) {
Type t = (Type) cst;
int s = t.getSort();
- if (s == Type.ARRAY) {
- return newClassItem(t.getDescriptor());
- } else if (s == Type.OBJECT) {
+ if (s == Type.OBJECT) {
return newClassItem(t.getInternalName());
- } else { // s == Type.METHOD
+ } else if (s == Type.METHOD) {
return newMethodTypeItem(t.getDescriptor());
+ } else { // s == primitive type or array
+ return newClassItem(t.getDescriptor());
}
} else if (cst instanceof Handle) {
Handle h = (Handle) cst;
@@ -993,10 +1063,11 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param cst the value of the constant to be added to the constant pool.
- * This parameter must be an {@link Integer}, a {@link Float}, a
- * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
* @return the index of a new or already existing constant item with the
* given value.
*/
@@ -1009,8 +1080,9 @@ public class ClassWriter extends ClassVisitor {
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
- *
- * @param value the String value.
+ *
+ * @param value
+ * the String value.
* @return the index of a new or already existing UTF8 item.
*/
public int newUTF8(final String value) {
@@ -1029,8 +1101,9 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param value the internal name of the class.
+ *
+ * @param value
+ * the internal name of the class.
* @return a new or already existing class reference item.
*/
Item newClassItem(final String value) {
@@ -1049,8 +1122,9 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param value the internal name of the class.
+ *
+ * @param value
+ * the internal name of the class.
* @return the index of a new or already existing class reference item.
*/
public int newClass(final String value) {
@@ -1062,8 +1136,9 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc method descriptor of the method type.
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
* @return a new or already existing method type reference item.
*/
Item newMethodTypeItem(final String methodDesc) {
@@ -1082,8 +1157,9 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param methodDesc method descriptor of the method type.
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
* @return the index of a new or already existing method type reference
* item.
*/
@@ -1096,34 +1172,35 @@ public class ClassWriter extends ClassVisitor {
* if the constant pool already contains a similar item. <i>This method is
* intended for {@link Attribute} sub classes, and is normally not needed by
* class generators or adapters.</i>
- *
- * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method owner class.
- * @param name the name of the field or method.
- * @param desc the descriptor of the field or method.
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
* @return a new or an already existing method type reference item.
*/
- Item newHandleItem(
- final int tag,
- final String owner,
- final String name,
- final String desc)
- {
+ Item newHandleItem(final int tag, final String owner, final String name,
+ final String desc) {
key4.set(HANDLE_BASE + tag, owner, name, desc);
Item result = get(key4);
if (result == null) {
if (tag <= Opcodes.H_PUTSTATIC) {
put112(HANDLE, tag, newField(owner, name, desc));
} else {
- put112(HANDLE, tag, newMethod(owner,
- name,
- desc,
- tag == Opcodes.H_INVOKEINTERFACE));
+ put112(HANDLE,
+ tag,
+ newMethod(owner, name, desc,
+ tag == Opcodes.H_INVOKEINTERFACE));
}
result = new Item(index++, key4);
put(result);
@@ -1132,29 +1209,30 @@ public class ClassWriter extends ClassVisitor {
}
/**
- * Adds a handle to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
- * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
- * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
- * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method owner class.
- * @param name the name of the field or method.
- * @param desc the descriptor of the field or method.
+ * Adds a handle to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
* @return the index of a new or already existing method type reference
* item.
*/
- public int newHandle(
- final int tag,
- final String owner,
- final String name,
- final String desc)
- {
+ public int newHandle(final int tag, final String owner, final String name,
+ final String desc) {
return newHandleItem(tag, owner, name, desc).index;
}
@@ -1163,20 +1241,20 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param name name of the invoked method.
- * @param desc descriptor of the invoke method.
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments.
- *
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
* @return a new or an already existing invokedynamic type reference item.
*/
- Item newInvokeDynamicItem(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ Item newInvokeDynamicItem(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
// cache for performance
ByteVector bootstrapMethods = this.bootstrapMethods;
if (bootstrapMethods == null) {
@@ -1186,9 +1264,7 @@ public class ClassWriter extends ClassVisitor {
int position = bootstrapMethods.length; // record current position
int hashCode = bsm.hashCode();
- bootstrapMethods.putShort(newHandle(bsm.tag,
- bsm.owner,
- bsm.name,
+ bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
bsm.desc));
int argsLength = bsmArgs.length;
@@ -1249,35 +1325,37 @@ public class ClassWriter extends ClassVisitor {
* build. Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param name name of the invoked method.
- * @param desc descriptor of the invoke method.
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments.
- *
- * @return the index of a new or already existing invokedynamic
- * reference item.
- */
- public int newInvokeDynamic(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
+ * @return the index of a new or already existing invokedynamic reference
+ * item.
+ */
+ public int newInvokeDynamic(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
}
/**
* Adds a field reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
- *
- * @param owner the internal name of the field's owner class.
- * @param name the field's name.
- * @param desc the field's descriptor.
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
* @return a new or already existing field reference item.
*/
- Item newFieldItem(final String owner, final String name, final String desc)
- {
+ Item newFieldItem(final String owner, final String name, final String desc) {
key3.set(FIELD, owner, name, desc);
Item result = get(key3);
if (result == null) {
@@ -1293,33 +1371,35 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the field's owner class.
- * @param name the field's name.
- * @param desc the field's descriptor.
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
* @return the index of a new or already existing field reference item.
*/
- public int newField(final String owner, final String name, final String desc)
- {
+ public int newField(final String owner, final String name, final String desc) {
return newFieldItem(owner, name, desc).index;
}
/**
* Adds a method reference to the constant pool of the class being build.
* Does nothing if the constant pool already contains a similar item.
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
* @return a new or already existing method reference item.
*/
- Item newMethodItem(
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
+ Item newMethodItem(final String owner, final String name,
+ final String desc, final boolean itf) {
int type = itf ? IMETH : METH;
key3.set(type, owner, name, desc);
Item result = get(key3);
@@ -1336,27 +1416,28 @@ public class ClassWriter extends ClassVisitor {
* Does nothing if the constant pool already contains a similar item.
* <i>This method is intended for {@link Attribute} sub classes, and is
* normally not needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
* @return the index of a new or already existing method reference item.
*/
- public int newMethod(
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
+ public int newMethod(final String owner, final String name,
+ final String desc, final boolean itf) {
return newMethodItem(owner, name, desc, itf).index;
}
/**
* Adds an integer to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
- *
- * @param value the int value.
+ *
+ * @param value
+ * the int value.
* @return a new or already existing int item.
*/
Item newInteger(final int value) {
@@ -1373,8 +1454,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a float to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the float value.
+ *
+ * @param value
+ * the float value.
* @return a new or already existing float item.
*/
Item newFloat(final float value) {
@@ -1391,8 +1473,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a long to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the long value.
+ *
+ * @param value
+ * the long value.
* @return a new or already existing long item.
*/
Item newLong(final long value) {
@@ -1410,8 +1493,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a double to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the double value.
+ *
+ * @param value
+ * the double value.
* @return a new or already existing double item.
*/
Item newDouble(final double value) {
@@ -1429,8 +1513,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a string to the constant pool of the class being build. Does nothing
* if the constant pool already contains a similar item.
- *
- * @param value the String value.
+ *
+ * @param value
+ * the String value.
* @return a new or already existing string item.
*/
private Item newString(final String value) {
@@ -1449,9 +1534,11 @@ public class ClassWriter extends ClassVisitor {
* nothing if the constant pool already contains a similar item. <i>This
* method is intended for {@link Attribute} sub classes, and is normally not
* needed by class generators or adapters.</i>
- *
- * @param name a name.
- * @param desc a type descriptor.
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
* @return the index of a new or already existing name and type item.
*/
public int newNameType(final String name, final String desc) {
@@ -1461,9 +1548,11 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds a name and type to the constant pool of the class being build. Does
* nothing if the constant pool already contains a similar item.
- *
- * @param name a name.
- * @param desc a type descriptor.
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
* @return a new or already existing name and type item.
*/
Item newNameTypeItem(final String name, final String desc) {
@@ -1480,8 +1569,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds the given internal name to {@link #typeTable} and returns its index.
* Does nothing if the type table already contains this internal name.
- *
- * @param type the internal name to be added to the type table.
+ *
+ * @param type
+ * the internal name to be added to the type table.
* @return the index of this internal name in the type table.
*/
int addType(final String type) {
@@ -1497,10 +1587,12 @@ public class ClassWriter extends ClassVisitor {
* Adds the given "uninitialized" type to {@link #typeTable} and returns its
* index. This method is used for UNINITIALIZED types, made of an internal
* name and a bytecode offset.
- *
- * @param type the internal name to be added to the type table.
- * @param offset the bytecode offset of the NEW instruction that created
- * this UNINITIALIZED type value.
+ *
+ * @param type
+ * the internal name to be added to the type table.
+ * @param offset
+ * the bytecode offset of the NEW instruction that created this
+ * UNINITIALIZED type value.
* @return the index of this internal name in the type table.
*/
int addUninitializedType(final String type, final int offset) {
@@ -1517,8 +1609,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Adds the given Item to {@link #typeTable}.
- *
- * @param item the value to be added to the type table.
+ *
+ * @param item
+ * the value to be added to the type table.
* @return the added Item, which a new Item instance with the same value as
* the given Item.
*/
@@ -1543,9 +1636,11 @@ public class ClassWriter extends ClassVisitor {
* method calls {@link #getCommonSuperClass} and caches the result in the
* {@link #items} hash table to speedup future calls with the same
* parameters.
- *
- * @param type1 index of an internal name in {@link #typeTable}.
- * @param type2 index of an internal name in {@link #typeTable}.
+ *
+ * @param type1
+ * index of an internal name in {@link #typeTable}.
+ * @param type2
+ * index of an internal name in {@link #typeTable}.
* @return the index of the common super type of the two given types.
*/
int getMergedType(final int type1, final int type2) {
@@ -1565,20 +1660,21 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the common super type of the two given types. The default
- * implementation of this method <i>loads<i> the two given classes and uses
+ * implementation of this method <i>loads</i> the two given classes and uses
* the java.lang.Class methods to find the common super class. It can be
* overridden to compute this common super type in other ways, in particular
* without actually loading any class, or to take into account the class
* that is currently being generated by this ClassWriter, which can of
* course not be loaded since it is under construction.
- *
- * @param type1 the internal name of a class.
- * @param type2 the internal name of another class.
+ *
+ * @param type1
+ * the internal name of a class.
+ * @param type2
+ * the internal name of another class.
* @return the internal name of the common super class of the two given
* classes.
*/
- protected String getCommonSuperClass(final String type1, final String type2)
- {
+ protected String getCommonSuperClass(final String type1, final String type2) {
Class<?> c, d;
ClassLoader classLoader = getClass().getClassLoader();
try {
@@ -1606,8 +1702,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Returns the constant pool's hash table item which is equal to the given
* item.
- *
- * @param key a constant pool item.
+ *
+ * @param key
+ * a constant pool item.
* @return the constant pool's hash table item which is equal to the given
* item, or <tt>null</tt> if there is no such item.
*/
@@ -1622,8 +1719,9 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts the given item in the constant pool's hash table. The hash table
* <i>must</i> not already contains this item.
- *
- * @param i the item to be added to the constant pool's hash table.
+ *
+ * @param i
+ * the item to be added to the constant pool's hash table.
*/
private void put(final Item i) {
if (index + typeCount > threshold) {
@@ -1650,10 +1748,13 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts one byte and two shorts into the constant pool.
- *
- * @param b a byte.
- * @param s1 a short.
- * @param s2 another short.
+ *
+ * @param b
+ * a byte.
+ * @param s1
+ * a short.
+ * @param s2
+ * another short.
*/
private void put122(final int b, final int s1, final int s2) {
pool.put12(b, s1).putShort(s2);
@@ -1661,10 +1762,13 @@ public class ClassWriter extends ClassVisitor {
/**
* Puts two bytes and one short into the constant pool.
- *
- * @param b1 a byte.
- * @param b2 another byte.
- * @param s a short.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
+ * @param s
+ * a short.
*/
private void put112(final int b1, final int b2, final int s) {
pool.put11(b1, b2).putShort(s);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
new file mode 100644
index 0000000..27983d6
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Context.java
@@ -0,0 +1,145 @@
+/***
+ * 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;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ *
+ * @author Eric Bruneton
+ */
+class Context {
+
+ /**
+ * Prototypes of the attributes that must be parsed for this class.
+ */
+ Attribute[] attrs;
+
+ /**
+ * The {@link ClassReader} option flags for the parsing of this class.
+ */
+ int flags;
+
+ /**
+ * The buffer used to read strings.
+ */
+ char[] buffer;
+
+ /**
+ * The start index of each bootstrap method.
+ */
+ int[] bootstrapMethods;
+
+ /**
+ * The access flags of the method currently being parsed.
+ */
+ int access;
+
+ /**
+ * The name of the method currently being parsed.
+ */
+ String name;
+
+ /**
+ * The descriptor of the method currently being parsed.
+ */
+ String desc;
+
+ /**
+ * The label objects, indexed by bytecode offset, of the method currently
+ * being parsed (only bytecode offsets for which a label is needed have a
+ * non null associated Label object).
+ */
+ Label[] labels;
+
+ /**
+ * The target of the type annotation currently being parsed.
+ */
+ int typeRef;
+
+ /**
+ * The path of the type annotation currently being parsed.
+ */
+ TypePath typePath;
+
+ /**
+ * The offset of the latest stack map frame that has been parsed.
+ */
+ int offset;
+
+ /**
+ * The labels corresponding to the start of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] start;
+
+ /**
+ * The labels corresponding to the end of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] end;
+
+ /**
+ * The local variable indices for each local variable range in the local
+ * variable type annotation currently being parsed.
+ */
+ int[] index;
+
+ /**
+ * The encoding of the latest stack map frame that has been parsed.
+ */
+ int mode;
+
+ /**
+ * The number of locals in the latest stack map frame that has been parsed.
+ */
+ int localCount;
+
+ /**
+ * The number locals in the latest stack map frame that has been parsed,
+ * minus the number of locals in the previous frame.
+ */
+ int localDiff;
+
+ /**
+ * The local values of the latest stack map frame that has been parsed.
+ */
+ Object[] local;
+
+ /**
+ * The stack size of the latest stack map frame that has been parsed.
+ */
+ int stackCount;
+
+ /**
+ * The stack values of the latest stack map frame that has been parsed.
+ */
+ Object[] stack;
+}
\ 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/Edge.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
index 80222bc..9347888 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Edge.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An edge in the control flow graph of a method body. See {@link Label Label}.
- *
+ *
* @author Eric Bruneton
*/
class Edge {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
index 32c23d1..107af8f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldVisitor.java
@@ -30,17 +30,17 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java field. The methods of this class must be called
- * in the following order: ( <tt>visitAnnotation</tt> |
- * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
- *
+ * A visitor to visit a Java field. The methods of this class must be called in
+ * the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
* @author Eric Bruneton
*/
public abstract class FieldVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -52,9 +52,10 @@ public abstract class FieldVisitor {
/**
* Constructs a new {@link FieldVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public FieldVisitor(final int api) {
this(api, null);
@@ -62,25 +63,29 @@ public abstract class FieldVisitor {
/**
* Constructs a new {@link FieldVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param fv the field visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param fv
+ * the field visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public FieldVisitor(final int api, final FieldVisitor fv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.fv = fv;
}
/**
* Visits an annotation of the field.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -92,9 +97,39 @@ public abstract class FieldVisitor {
}
/**
+ * Visits an annotation on the type of the field.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#FIELD FIELD}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (fv != null) {
+ return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a non standard attribute of the field.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (fv != null) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
index b61105a..4a5f406 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/FieldWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An {@link FieldVisitor} that generates Java fields in bytecode form.
- *
+ *
* @author Eric Bruneton
*/
final class FieldWriter extends FieldVisitor {
@@ -81,6 +81,17 @@ final class FieldWriter extends FieldVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this field. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The non standard attributes of this field. May be <tt>null</tt>.
*/
private Attribute attrs;
@@ -91,23 +102,23 @@ final class FieldWriter extends FieldVisitor {
/**
* Constructs a new {@link FieldWriter}.
- *
- * @param cw the class writer to which this field must be added.
- * @param access the field's access flags (see {@link Opcodes}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type}).
- * @param signature the field's signature. May be <tt>null</tt>.
- * @param value the field's constant value. May be <tt>null</tt>.
+ *
+ * @param cw
+ * the class writer to which this field must be added.
+ * @param access
+ * the field's access flags (see {@link Opcodes}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt>.
+ * @param value
+ * the field's constant value. May be <tt>null</tt>.
*/
- FieldWriter(
- final ClassWriter cw,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- super(Opcodes.ASM4);
+ FieldWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ super(Opcodes.ASM5);
if (cw.firstField == null) {
cw.firstField = this;
} else {
@@ -131,10 +142,8 @@ final class FieldWriter extends FieldVisitor {
// ------------------------------------------------------------------------
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -153,6 +162,29 @@ final class FieldWriter extends FieldVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
attr.next = attrs;
attrs = attr;
@@ -168,7 +200,7 @@ final class FieldWriter extends FieldVisitor {
/**
* Returns the size of this field.
- *
+ *
* @return the size of this field.
*/
int getSize() {
@@ -177,11 +209,12 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("ConstantValue");
size += 8;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- cw.newUTF8("Synthetic");
- size += 6;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
@@ -199,6 +232,14 @@ final class FieldWriter extends FieldVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
@@ -207,22 +248,24 @@ final class FieldWriter extends FieldVisitor {
/**
* Puts the content of this field into the given byte vector.
- *
- * @param out where the content of this field must be put.
+ *
+ * @param out
+ * where the content of this field must be put.
*/
void put(final ByteVector out) {
- int mask = Opcodes.ACC_DEPRECATED
- | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
int attributeCount = 0;
if (value != 0) {
++attributeCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
@@ -236,6 +279,12 @@ final class FieldWriter extends FieldVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
if (attrs != null) {
attributeCount += attrs.getCount();
}
@@ -244,10 +293,11 @@ final class FieldWriter extends FieldVisitor {
out.putShort(cw.newUTF8("ConstantValue"));
out.putInt(2).putShort(value);
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
@@ -264,6 +314,14 @@ final class FieldWriter extends FieldVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
[16/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
new file mode 100644
index 0000000..c256825
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AnalyzerAdapter.java
@@ -0,0 +1,947 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} that keeps track of stack map frame changes between
+ * {@link #visitFrame(int, int, Object[], int, Object[]) visitFrame} calls. This
+ * adapter must be used with the
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassReader#EXPAND_FRAMES} option. Each
+ * visit<i>X</i> instruction delegates to the next visitor in the chain, if any,
+ * and then simulates the effect of this instruction on the stack map frame,
+ * represented by {@link #locals} and {@link #stack}. The next visitor in the
+ * chain can get the state of the stack map frame <i>before</i> each instruction
+ * by reading the value of these fields in its visit<i>X</i> methods (this
+ * requires a reference to the AnalyzerAdapter that is before it in the chain).
+ * If this adapter is used with a class that does not contain stack map table
+ * attributes (i.e., pre Java 6 classes) then this adapter may not be able to
+ * compute the stack map frame for each instruction. In this case no exception
+ * is thrown but the {@link #locals} and {@link #stack} fields will be null for
+ * these instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class AnalyzerAdapter extends MethodVisitor {
+
+ /**
+ * <code>List</code> of the local variable slots for current execution
+ * frame. Primitive types are represented by {@link Opcodes#TOP},
+ * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+ * two elements, the second one being TOP). Reference types are represented
+ * by String objects (representing internal names), and uninitialized types
+ * by Label objects (this label designates the NEW instruction that created
+ * this uninitialized value). This field is <tt>null</tt> for unreachable
+ * instructions.
+ */
+ public List<Object> locals;
+
+ /**
+ * <code>List</code> of the operand stack slots for current execution frame.
+ * Primitive types are represented by {@link Opcodes#TOP},
+ * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by
+ * two elements, the second one being TOP). Reference types are represented
+ * by String objects (representing internal names), and uninitialized types
+ * by Label objects (this label designates the NEW instruction that created
+ * this uninitialized value). This field is <tt>null</tt> for unreachable
+ * instructions.
+ */
+ public List<Object> stack;
+
+ /**
+ * The labels that designate the next instruction to be visited. May be
+ * <tt>null</tt>.
+ */
+ private List<Label> labels;
+
+ /**
+ * Information about uninitialized types in the current execution frame.
+ * This map associates internal names to Label objects. Each label
+ * designates a NEW instruction that created the currently uninitialized
+ * types, and the associated internal name represents the NEW operand, i.e.
+ * the final, initialized type value.
+ */
+ public Map<Object, Object> uninitializedTypes;
+
+ /**
+ * The maximum stack size of this method.
+ */
+ private int maxStack;
+
+ /**
+ * The maximum number of local variables of this method.
+ */
+ private int maxLocals;
+
+ /**
+ * The owner's class name.
+ */
+ private String owner;
+
+ /**
+ * Creates a new {@link AnalyzerAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #AnalyzerAdapter(int, String, int, String, String, MethodVisitor)}
+ * version.
+ *
+ * @param owner
+ * the owner's class name.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls. May
+ * be <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public AnalyzerAdapter(final String owner, final int access,
+ final String name, final String desc, final MethodVisitor mv) {
+ this(Opcodes.ASM5, owner, access, name, desc, mv);
+ if (getClass() != AnalyzerAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link AnalyzerAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param owner
+ * the owner's class name.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls. May
+ * be <tt>null</tt>.
+ */
+ protected AnalyzerAdapter(final int api, final String owner,
+ final int access, final String name, final String desc,
+ final MethodVisitor mv) {
+ super(api, mv);
+ this.owner = owner;
+ locals = new ArrayList<Object>();
+ stack = new ArrayList<Object>();
+ uninitializedTypes = new HashMap<Object, Object>();
+
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ locals.add(Opcodes.UNINITIALIZED_THIS);
+ } else {
+ locals.add(owner);
+ }
+ }
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; ++i) {
+ Type type = types[i];
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ locals.add(Opcodes.INTEGER);
+ break;
+ case Type.FLOAT:
+ locals.add(Opcodes.FLOAT);
+ break;
+ case Type.LONG:
+ locals.add(Opcodes.LONG);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.DOUBLE:
+ locals.add(Opcodes.DOUBLE);
+ locals.add(Opcodes.TOP);
+ break;
+ case Type.ARRAY:
+ locals.add(types[i].getDescriptor());
+ break;
+ // case Type.OBJECT:
+ default:
+ locals.add(types[i].getInternalName());
+ }
+ }
+ maxLocals = locals.size();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // uncompressed frame
+ throw new IllegalStateException(
+ "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+ }
+
+ if (mv != null) {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ if (this.locals != null) {
+ this.locals.clear();
+ this.stack.clear();
+ } else {
+ this.locals = new ArrayList<Object>();
+ this.stack = new ArrayList<Object>();
+ }
+ visitFrameTypes(nLocal, local, this.locals);
+ visitFrameTypes(nStack, stack, this.stack);
+ maxStack = Math.max(maxStack, this.stack.size());
+ }
+
+ private static void visitFrameTypes(final int n, final Object[] types,
+ final List<Object> result) {
+ for (int i = 0; i < n; ++i) {
+ Object type = types[i];
+ result.add(type);
+ if (type == Opcodes.LONG || type == Opcodes.DOUBLE) {
+ result.add(Opcodes.TOP);
+ }
+ }
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ execute(opcode, 0, null);
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+ || opcode == Opcodes.ATHROW) {
+ this.locals = null;
+ this.stack = null;
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ execute(opcode, operand, null);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ execute(opcode, var, null);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ if (opcode == Opcodes.NEW) {
+ if (labels == null) {
+ Label l = new Label();
+ labels = new ArrayList<Label>(3);
+ labels.add(l);
+ if (mv != null) {
+ mv.visitLabel(l);
+ }
+ }
+ for (int i = 0; i < labels.size(); ++i) {
+ uninitializedTypes.put(labels.get(i), type);
+ }
+ }
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ execute(opcode, 0, type);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ execute(opcode, 0, desc);
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ pop(desc);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ Object t = pop();
+ if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') {
+ Object u;
+ if (t == Opcodes.UNINITIALIZED_THIS) {
+ u = this.owner;
+ } else {
+ u = uninitializedTypes.get(t);
+ }
+ for (int i = 0; i < locals.size(); ++i) {
+ if (locals.get(i) == t) {
+ locals.set(i, u);
+ }
+ }
+ for (int i = 0; i < stack.size(); ++i) {
+ if (stack.get(i) == t) {
+ stack.set(i, u);
+ }
+ }
+ }
+ }
+ pushDesc(desc);
+ labels = null;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ pop(desc);
+ pushDesc(desc);
+ labels = null;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ execute(opcode, 0, null);
+ if (opcode == Opcodes.GOTO) {
+ this.locals = null;
+ this.stack = null;
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ if (labels == null) {
+ labels = new ArrayList<Label>(3);
+ }
+ labels.add(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ if (cst instanceof Integer) {
+ push(Opcodes.INTEGER);
+ } else if (cst instanceof Long) {
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ } else if (cst instanceof Float) {
+ push(Opcodes.FLOAT);
+ } else if (cst instanceof Double) {
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ } else if (cst instanceof String) {
+ push("java/lang/String");
+ } else if (cst instanceof Type) {
+ int sort = ((Type) cst).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ push("java/lang/Class");
+ } else if (sort == Type.METHOD) {
+ push("java/lang/invoke/MethodType");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ } else if (cst instanceof Handle) {
+ push("java/lang/invoke/MethodHandle");
+ } else {
+ throw new IllegalArgumentException();
+ }
+ labels = null;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ execute(Opcodes.IINC, var, null);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ execute(Opcodes.TABLESWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ execute(Opcodes.LOOKUPSWITCH, 0, null);
+ this.locals = null;
+ this.stack = null;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ execute(Opcodes.MULTIANEWARRAY, dims, desc);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (mv != null) {
+ this.maxStack = Math.max(this.maxStack, maxStack);
+ this.maxLocals = Math.max(this.maxLocals, maxLocals);
+ mv.visitMaxs(this.maxStack, this.maxLocals);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+
+ private Object get(final int local) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ return local < locals.size() ? locals.get(local) : Opcodes.TOP;
+ }
+
+ private void set(final int local, final Object type) {
+ maxLocals = Math.max(maxLocals, local + 1);
+ while (local >= locals.size()) {
+ locals.add(Opcodes.TOP);
+ }
+ locals.set(local, type);
+ }
+
+ private void push(final Object type) {
+ stack.add(type);
+ maxStack = Math.max(maxStack, stack.size());
+ }
+
+ private void pushDesc(final String desc) {
+ int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+ switch (desc.charAt(index)) {
+ case 'V':
+ return;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ push(Opcodes.INTEGER);
+ return;
+ case 'F':
+ push(Opcodes.FLOAT);
+ return;
+ case 'J':
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ return;
+ case 'D':
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ return;
+ case '[':
+ if (index == 0) {
+ push(desc);
+ } else {
+ push(desc.substring(index, desc.length()));
+ }
+ break;
+ // case 'L':
+ default:
+ if (index == 0) {
+ push(desc.substring(1, desc.length() - 1));
+ } else {
+ push(desc.substring(index + 1, desc.length() - 1));
+ }
+ }
+ }
+
+ private Object pop() {
+ return stack.remove(stack.size() - 1);
+ }
+
+ private void pop(final int n) {
+ int size = stack.size();
+ int end = size - n;
+ for (int i = size - 1; i >= end; --i) {
+ stack.remove(i);
+ }
+ }
+
+ private void pop(final String desc) {
+ char c = desc.charAt(0);
+ if (c == '(') {
+ int n = 0;
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; ++i) {
+ n += types[i].getSize();
+ }
+ pop(n);
+ } else if (c == 'J' || c == 'D') {
+ pop(2);
+ } else {
+ pop(1);
+ }
+ }
+
+ private void execute(final int opcode, final int iarg, final String sarg) {
+ if (this.locals == null) {
+ labels = null;
+ return;
+ }
+ Object t1, t2, t3, t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(Opcodes.NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.ALOAD:
+ push(get(iarg));
+ break;
+ case Opcodes.LLOAD:
+ case Opcodes.DLOAD:
+ push(get(iarg));
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ if (t1 instanceof String) {
+ pushDesc(((String) t1).substring(1));
+ } else {
+ push("java/lang/Object");
+ }
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(iarg, t1);
+ if (iarg > 0) {
+ t2 = get(iarg - 1);
+ if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+ set(iarg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(iarg, t1);
+ set(iarg + 1, Opcodes.TOP);
+ if (iarg > 0) {
+ t2 = get(iarg - 1);
+ if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) {
+ set(iarg - 1, Opcodes.TOP);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.IINC:
+ set(iarg, Opcodes.INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(Opcodes.LONG);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(Opcodes.FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(Opcodes.DOUBLE);
+ push(Opcodes.TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(Opcodes.INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException("JSR/RET are not supported");
+ case Opcodes.GETSTATIC:
+ pushDesc(sarg);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(sarg);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ pushDesc(sarg);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(sarg);
+ pop();
+ break;
+ case Opcodes.NEW:
+ push(labels.get(0));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (iarg) {
+ case Opcodes.T_BOOLEAN:
+ pushDesc("[Z");
+ break;
+ case Opcodes.T_CHAR:
+ pushDesc("[C");
+ break;
+ case Opcodes.T_BYTE:
+ pushDesc("[B");
+ break;
+ case Opcodes.T_SHORT:
+ pushDesc("[S");
+ break;
+ case Opcodes.T_INT:
+ pushDesc("[I");
+ break;
+ case Opcodes.T_FLOAT:
+ pushDesc("[F");
+ break;
+ case Opcodes.T_DOUBLE:
+ pushDesc("[D");
+ break;
+ // case Opcodes.T_LONG:
+ default:
+ pushDesc("[J");
+ break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ pop();
+ pushDesc("[" + Type.getObjectType(sarg));
+ break;
+ case Opcodes.CHECKCAST:
+ pop();
+ pushDesc(Type.getObjectType(sarg).getDescriptor());
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(iarg);
+ pushDesc(sarg);
+ break;
+ }
+ labels = null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
new file mode 100644
index 0000000..d146a36
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/CodeSizeEvaluator.java
@@ -0,0 +1,238 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link MethodVisitor} that can be used to approximate method size.
+ *
+ * @author Eugene Kuleshov
+ */
+public class CodeSizeEvaluator extends MethodVisitor implements Opcodes {
+
+ private int minSize;
+
+ private int maxSize;
+
+ public CodeSizeEvaluator(final MethodVisitor mv) {
+ this(Opcodes.ASM5, mv);
+ }
+
+ protected CodeSizeEvaluator(final int api, final MethodVisitor mv) {
+ super(api, mv);
+ }
+
+ public int getMinSize() {
+ return this.minSize;
+ }
+
+ public int getMaxSize() {
+ return this.maxSize;
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ minSize += 1;
+ maxSize += 1;
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ if (opcode == SIPUSH) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ if (var < 4 && opcode != RET) {
+ minSize += 1;
+ maxSize += 1;
+ } else if (var >= 256) {
+ minSize += 4;
+ maxSize += 4;
+ } else {
+ minSize += 2;
+ maxSize += 2;
+ }
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ minSize += 3;
+ maxSize += 3;
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ minSize += 3;
+ maxSize += 3;
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (opcode == INVOKEINTERFACE) {
+ minSize += 5;
+ maxSize += 5;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ minSize += 5;
+ maxSize += 5;
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ minSize += 3;
+ if (opcode == GOTO || opcode == JSR) {
+ maxSize += 5;
+ } else {
+ maxSize += 8;
+ }
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (cst instanceof Long || cst instanceof Double) {
+ minSize += 3;
+ maxSize += 3;
+ } else {
+ minSize += 2;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (var > 255 || increment > 127 || increment < -128) {
+ minSize += 6;
+ maxSize += 6;
+ } else {
+ minSize += 3;
+ maxSize += 3;
+ }
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ minSize += 13 + labels.length * 4;
+ maxSize += 16 + labels.length * 4;
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ minSize += 9 + keys.length * 8;
+ maxSize += 12 + keys.length * 8;
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ minSize += 4;
+ maxSize += 4;
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+}
[15/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
new file mode 100644
index 0000000..ceb051f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/GeneratorAdapter.java
@@ -0,0 +1,1628 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} with convenient methods to generate
+ * code. For example, using this adapter, the class below
+ *
+ * <pre>
+ * public class Example {
+ * public static void main(String[] args) {
+ * System.out.println("Hello world!");
+ * }
+ * }
+ * </pre>
+ *
+ * can be generated as follows:
+ *
+ * <pre>
+ * ClassWriter cw = new ClassWriter(true);
+ * cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
+ *
+ * Method m = Method.getMethod("void <init> ()");
+ * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
+ * mg.loadThis();
+ * mg.invokeConstructor(Type.getType(Object.class), m);
+ * mg.returnValue();
+ * mg.endMethod();
+ *
+ * m = Method.getMethod("void main (String[])");
+ * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
+ * mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
+ * mg.push("Hello world!");
+ * mg.invokeVirtual(Type.getType(PrintStream.class),
+ * Method.getMethod("void println (String)"));
+ * mg.returnValue();
+ * mg.endMethod();
+ *
+ * cw.visitEnd();
+ * </pre>
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ * @author Prashant Deva
+ */
+public class GeneratorAdapter extends LocalVariablesSorter {
+
+ private static final String CLDESC = "Ljava/lang/Class;";
+
+ private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
+
+ private static final Type BOOLEAN_TYPE = Type
+ .getObjectType("java/lang/Boolean");
+
+ private static final Type SHORT_TYPE = Type
+ .getObjectType("java/lang/Short");
+
+ private static final Type CHARACTER_TYPE = Type
+ .getObjectType("java/lang/Character");
+
+ private static final Type INTEGER_TYPE = Type
+ .getObjectType("java/lang/Integer");
+
+ private static final Type FLOAT_TYPE = Type
+ .getObjectType("java/lang/Float");
+
+ private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
+
+ private static final Type DOUBLE_TYPE = Type
+ .getObjectType("java/lang/Double");
+
+ private static final Type NUMBER_TYPE = Type
+ .getObjectType("java/lang/Number");
+
+ private static final Type OBJECT_TYPE = Type
+ .getObjectType("java/lang/Object");
+
+ private static final Method BOOLEAN_VALUE = Method
+ .getMethod("boolean booleanValue()");
+
+ private static final Method CHAR_VALUE = Method
+ .getMethod("char charValue()");
+
+ private static final Method INT_VALUE = Method.getMethod("int intValue()");
+
+ private static final Method FLOAT_VALUE = Method
+ .getMethod("float floatValue()");
+
+ private static final Method LONG_VALUE = Method
+ .getMethod("long longValue()");
+
+ private static final Method DOUBLE_VALUE = Method
+ .getMethod("double doubleValue()");
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int ADD = Opcodes.IADD;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SUB = Opcodes.ISUB;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int MUL = Opcodes.IMUL;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int DIV = Opcodes.IDIV;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int REM = Opcodes.IREM;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int NEG = Opcodes.INEG;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SHL = Opcodes.ISHL;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int SHR = Opcodes.ISHR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int USHR = Opcodes.IUSHR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int AND = Opcodes.IAND;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int OR = Opcodes.IOR;
+
+ /**
+ * Constant for the {@link #math math} method.
+ */
+ public static final int XOR = Opcodes.IXOR;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int EQ = Opcodes.IFEQ;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int NE = Opcodes.IFNE;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int LT = Opcodes.IFLT;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int GE = Opcodes.IFGE;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int GT = Opcodes.IFGT;
+
+ /**
+ * Constant for the {@link #ifCmp ifCmp} method.
+ */
+ public static final int LE = Opcodes.IFLE;
+
+ /**
+ * Access flags of the method visited by this adapter.
+ */
+ private final int access;
+
+ /**
+ * Return type of the method visited by this adapter.
+ */
+ private final Type returnType;
+
+ /**
+ * Argument types of the method visited by this adapter.
+ */
+ private final Type[] argumentTypes;
+
+ /**
+ * Types of the local variables of the method visited by this adapter.
+ */
+ private final List<Type> localTypes = new ArrayList<Type>();
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public GeneratorAdapter(final MethodVisitor mv, final int access,
+ final String name, final String desc) {
+ this(Opcodes.ASM5, mv, access, name, desc);
+ if (getClass() != GeneratorAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ protected GeneratorAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc) {
+ super(api, access, desc, mv);
+ this.access = access;
+ this.returnType = Type.getReturnType(desc);
+ this.argumentTypes = Type.getArgumentTypes(desc);
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param method
+ * the adapted method.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(final int access, final Method method,
+ final MethodVisitor mv) {
+ this(mv, access, null, method.getDescriptor());
+ }
+
+ /**
+ * Creates a new {@link GeneratorAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #GeneratorAdapter(int, MethodVisitor, int, String, String)}
+ * version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param method
+ * the adapted method.
+ * @param signature
+ * the signature of the adapted method (may be <tt>null</tt>).
+ * @param exceptions
+ * the exceptions thrown by the adapted method (may be
+ * <tt>null</tt>).
+ * @param cv
+ * the class visitor to which this adapter delegates calls.
+ */
+ public GeneratorAdapter(final int access, final Method method,
+ final String signature, final Type[] exceptions,
+ final ClassVisitor cv) {
+ this(access, method, cv
+ .visitMethod(access, method.getName(), method.getDescriptor(),
+ signature, getInternalNames(exceptions)));
+ }
+
+ /**
+ * Returns the internal names of the given types.
+ *
+ * @param types
+ * a set of types.
+ * @return the internal names of the given types.
+ */
+ private static String[] getInternalNames(final Type[] types) {
+ if (types == null) {
+ return null;
+ }
+ String[] names = new String[types.length];
+ for (int i = 0; i < names.length; ++i) {
+ names[i] = types[i].getInternalName();
+ }
+ return names;
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to push constants on the stack
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final boolean value) {
+ push(value ? 1 : 0);
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final int value) {
+ if (value >= -1 && value <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + value);
+ } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, value);
+ } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, value);
+ } else {
+ mv.visitLdcInsn(new Integer(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final long value) {
+ if (value == 0L || value == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Long(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final float value) {
+ int bits = Float.floatToIntBits(value);
+ if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Float(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final double value) {
+ long bits = Double.doubleToLongBits(value);
+ if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) value);
+ } else {
+ mv.visitLdcInsn(new Double(value));
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack. May be <tt>null</tt>.
+ */
+ public void push(final String value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(value);
+ }
+ }
+
+ /**
+ * Generates the instruction to push the given value on the stack.
+ *
+ * @param value
+ * the value to be pushed on the stack.
+ */
+ public void push(final Type value) {
+ if (value == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ switch (value.getSort()) {
+ case Type.BOOLEAN:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean",
+ "TYPE", CLDESC);
+ break;
+ case Type.CHAR:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character",
+ "TYPE", CLDESC);
+ break;
+ case Type.BYTE:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE",
+ CLDESC);
+ break;
+ case Type.SHORT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE",
+ CLDESC);
+ break;
+ case Type.INT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer",
+ "TYPE", CLDESC);
+ break;
+ case Type.FLOAT:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE",
+ CLDESC);
+ break;
+ case Type.LONG:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE",
+ CLDESC);
+ break;
+ case Type.DOUBLE:
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double",
+ "TYPE", CLDESC);
+ break;
+ default:
+ mv.visitLdcInsn(value);
+ }
+ }
+ }
+
+ /**
+ * Generates the instruction to push a handle on the stack.
+ *
+ * @param handle
+ * the handle to be pushed on the stack.
+ */
+ public void push(final Handle handle) {
+ mv.visitLdcInsn(handle);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store method arguments
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the index of the given method argument in the frame's local
+ * variables array.
+ *
+ * @param arg
+ * the index of a method argument.
+ * @return the index of the given method argument in the frame's local
+ * variables array.
+ */
+ private int getArgIndex(final int arg) {
+ int index = (access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
+ for (int i = 0; i < arg; i++) {
+ index += argumentTypes[i].getSize();
+ }
+ return index;
+ }
+
+ /**
+ * Generates the instruction to push a local variable on the stack.
+ *
+ * @param type
+ * the type of the local variable to be loaded.
+ * @param index
+ * an index in the frame's local variables array.
+ */
+ private void loadInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a local
+ * variable.
+ *
+ * @param type
+ * the type of the local variable to be stored.
+ * @param index
+ * an index in the frame's local variables array.
+ */
+ private void storeInsn(final Type type, final int index) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
+ }
+
+ /**
+ * Generates the instruction to load 'this' on the stack.
+ */
+ public void loadThis() {
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ throw new IllegalStateException(
+ "no 'this' pointer within static method");
+ }
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ }
+
+ /**
+ * Generates the instruction to load the given method argument on the stack.
+ *
+ * @param arg
+ * the index of a method argument.
+ */
+ public void loadArg(final int arg) {
+ loadInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ /**
+ * Generates the instructions to load the given method arguments on the
+ * stack.
+ *
+ * @param arg
+ * the index of the first method argument to be loaded.
+ * @param count
+ * the number of method arguments to be loaded.
+ */
+ public void loadArgs(final int arg, final int count) {
+ int index = getArgIndex(arg);
+ for (int i = 0; i < count; ++i) {
+ Type t = argumentTypes[arg + i];
+ loadInsn(t, index);
+ index += t.getSize();
+ }
+ }
+
+ /**
+ * Generates the instructions to load all the method arguments on the stack.
+ */
+ public void loadArgs() {
+ loadArgs(0, argumentTypes.length);
+ }
+
+ /**
+ * Generates the instructions to load all the method arguments on the stack,
+ * as a single object array.
+ */
+ public void loadArgArray() {
+ push(argumentTypes.length);
+ newArray(OBJECT_TYPE);
+ for (int i = 0; i < argumentTypes.length; i++) {
+ dup();
+ push(i);
+ loadArg(i);
+ box(argumentTypes[i]);
+ arrayStore(OBJECT_TYPE);
+ }
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given
+ * method argument.
+ *
+ * @param arg
+ * the index of a method argument.
+ */
+ public void storeArg(final int arg) {
+ storeInsn(argumentTypes[arg], getArgIndex(arg));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store local variables
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the type of the given local variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @return the type of the given local variable.
+ */
+ public Type getLocalType(final int local) {
+ return localTypes.get(local - firstLocal);
+ }
+
+ @Override
+ protected void setLocalType(final int local, final Type type) {
+ int index = local - firstLocal;
+ while (localTypes.size() < index + 1) {
+ localTypes.add(null);
+ }
+ localTypes.set(index, type);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void loadLocal(final int local) {
+ loadInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to load the given local variable on the stack.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @param type
+ * the type of this local variable.
+ */
+ public void loadLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ loadInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local
+ * variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void storeLocal(final int local) {
+ storeInsn(getLocalType(local), local);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in the given local
+ * variable.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ * @param type
+ * the type of this local variable.
+ */
+ public void storeLocal(final int local, final Type type) {
+ setLocalType(local, type);
+ storeInsn(type, local);
+ }
+
+ /**
+ * Generates the instruction to load an element from an array.
+ *
+ * @param type
+ * the type of the array element to be loaded.
+ */
+ public void arrayLoad(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ /**
+ * Generates the instruction to store an element in an array.
+ *
+ * @param type
+ * the type of the array element to be stored.
+ */
+ public void arrayStore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to manage the stack
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a POP instruction.
+ */
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ /**
+ * Generates a POP2 instruction.
+ */
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ /**
+ * Generates a DUP instruction.
+ */
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ /**
+ * Generates a DUP2 instruction.
+ */
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ /**
+ * Generates a DUP_X1 instruction.
+ */
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ /**
+ * Generates a DUP_X2 instruction.
+ */
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ /**
+ * Generates a DUP2_X1 instruction.
+ */
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ /**
+ * Generates a DUP2_X2 instruction.
+ */
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ /**
+ * Generates a SWAP instruction.
+ */
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ /**
+ * Generates the instructions to swap the top two stack values.
+ *
+ * @param prev
+ * type of the top - 1 stack value.
+ * @param type
+ * type of the top stack value.
+ */
+ public void swap(final Type prev, final Type type) {
+ if (type.getSize() == 1) {
+ if (prev.getSize() == 1) {
+ swap(); // same as dupX1(), pop();
+ } else {
+ dupX2();
+ pop();
+ }
+ } else {
+ if (prev.getSize() == 1) {
+ dup2X1();
+ pop2();
+ } else {
+ dup2X2();
+ pop2();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to do mathematical and logical operations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to do the specified mathematical or logical
+ * operation.
+ *
+ * @param op
+ * a mathematical or logical operation. Must be one of ADD, SUB,
+ * MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
+ * @param type
+ * the type of the operand(s) for this operation.
+ */
+ public void math(final int op, final Type type) {
+ mv.visitInsn(type.getOpcode(op));
+ }
+
+ /**
+ * Generates the instructions to compute the bitwise negation of the top
+ * stack value.
+ */
+ public void not() {
+ mv.visitInsn(Opcodes.ICONST_1);
+ mv.visitInsn(Opcodes.IXOR);
+ }
+
+ /**
+ * Generates the instruction to increment the given local variable.
+ *
+ * @param local
+ * the local variable to be incremented.
+ * @param amount
+ * the amount by which the local variable must be incremented.
+ */
+ public void iinc(final int local, final int amount) {
+ mv.visitIincInsn(local, amount);
+ }
+
+ /**
+ * Generates the instructions to cast a numerical value from one type to
+ * another.
+ *
+ * @param from
+ * the type of the top stack value
+ * @param to
+ * the type into which this value must be cast.
+ */
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
+ } else {
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
+ } else {
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
+ }
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to do boxing and unboxing operations
+ // ------------------------------------------------------------------------
+
+ private static Type getBoxedType(final Type type) {
+ switch (type.getSort()) {
+ case Type.BYTE:
+ return BYTE_TYPE;
+ case Type.BOOLEAN:
+ return BOOLEAN_TYPE;
+ case Type.SHORT:
+ return SHORT_TYPE;
+ case Type.CHAR:
+ return CHARACTER_TYPE;
+ case Type.INT:
+ return INTEGER_TYPE;
+ case Type.FLOAT:
+ return FLOAT_TYPE;
+ case Type.LONG:
+ return LONG_TYPE;
+ case Type.DOUBLE:
+ return DOUBLE_TYPE;
+ }
+ return type;
+ }
+
+ /**
+ * Generates the instructions to box the top stack value. This value is
+ * replaced by its boxed equivalent on top of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void box(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxed = getBoxedType(type);
+ newInstance(boxed);
+ if (type.getSize() == 2) {
+ // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+ dupX2();
+ dupX2();
+ pop();
+ } else {
+ // p -> po -> opo -> oop -> o
+ dupX1();
+ swap();
+ }
+ invokeConstructor(boxed, new Method("<init>", Type.VOID_TYPE,
+ new Type[] { type }));
+ }
+ }
+
+ /**
+ * Generates the instructions to box the top stack value using Java 5's
+ * valueOf() method. This value is replaced by its boxed equivalent on top
+ * of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void valueOf(final Type type) {
+ if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
+ return;
+ }
+ if (type == Type.VOID_TYPE) {
+ push((String) null);
+ } else {
+ Type boxed = getBoxedType(type);
+ invokeStatic(boxed, new Method("valueOf", boxed,
+ new Type[] { type }));
+ }
+ }
+
+ /**
+ * Generates the instructions to unbox the top stack value. This value is
+ * replaced by its unboxed equivalent on top of the stack.
+ *
+ * @param type
+ * the type of the top stack value.
+ */
+ public void unbox(final Type type) {
+ Type t = NUMBER_TYPE;
+ Method sig = null;
+ switch (type.getSort()) {
+ case Type.VOID:
+ return;
+ case Type.CHAR:
+ t = CHARACTER_TYPE;
+ sig = CHAR_VALUE;
+ break;
+ case Type.BOOLEAN:
+ t = BOOLEAN_TYPE;
+ sig = BOOLEAN_VALUE;
+ break;
+ case Type.DOUBLE:
+ sig = DOUBLE_VALUE;
+ break;
+ case Type.FLOAT:
+ sig = FLOAT_VALUE;
+ break;
+ case Type.LONG:
+ sig = LONG_VALUE;
+ break;
+ case Type.INT:
+ case Type.SHORT:
+ case Type.BYTE:
+ sig = INT_VALUE;
+ }
+ if (sig == null) {
+ checkCast(type);
+ } else {
+ checkCast(t);
+ invokeVirtual(t, sig);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to jump to other instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new {@link Label}.
+ *
+ * @return a new {@link Label}.
+ */
+ public Label newLabel() {
+ return new Label();
+ }
+
+ /**
+ * Marks the current code position with the given label.
+ *
+ * @param label
+ * a label.
+ */
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+
+ /**
+ * Marks the current code position with a new label.
+ *
+ * @return the label that was created to mark the current code position.
+ */
+ public Label mark() {
+ Label label = new Label();
+ mv.visitLabel(label);
+ return label;
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top two stack values.
+ *
+ * @param type
+ * the type of the top two stack values.
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifCmp(final Type type, final int mode, final Label label) {
+ switch (type.getSort()) {
+ case Type.LONG:
+ mv.visitInsn(Opcodes.LCMP);
+ break;
+ case Type.DOUBLE:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.DCMPL
+ : Opcodes.DCMPG);
+ break;
+ case Type.FLOAT:
+ mv.visitInsn(mode == GE || mode == GT ? Opcodes.FCMPL
+ : Opcodes.FCMPG);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ switch (mode) {
+ case EQ:
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ return;
+ case NE:
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ return;
+ }
+ throw new IllegalArgumentException("Bad comparison for type "
+ + type);
+ default:
+ int intOp = -1;
+ switch (mode) {
+ case EQ:
+ intOp = Opcodes.IF_ICMPEQ;
+ break;
+ case NE:
+ intOp = Opcodes.IF_ICMPNE;
+ break;
+ case GE:
+ intOp = Opcodes.IF_ICMPGE;
+ break;
+ case LT:
+ intOp = Opcodes.IF_ICMPLT;
+ break;
+ case LE:
+ intOp = Opcodes.IF_ICMPLE;
+ break;
+ case GT:
+ intOp = Opcodes.IF_ICMPGT;
+ break;
+ }
+ mv.visitJumpInsn(intOp, label);
+ return;
+ }
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top two integer stack values.
+ *
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifICmp(final int mode, final Label label) {
+ ifCmp(Type.INT_TYPE, mode, label);
+ }
+
+ /**
+ * Generates the instructions to jump to a label based on the comparison of
+ * the top integer stack value with zero.
+ *
+ * @param mode
+ * how these values must be compared. One of EQ, NE, LT, GE, GT,
+ * LE.
+ * @param label
+ * where to jump if the comparison result is <tt>true</tt>.
+ */
+ public void ifZCmp(final int mode, final Label label) {
+ mv.visitJumpInsn(mode, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack
+ * value is null.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void ifNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label if the top stack
+ * value is not null.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void ifNonNull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ /**
+ * Generates the instruction to jump to the given label.
+ *
+ * @param label
+ * where to jump if the condition is <tt>true</tt>.
+ */
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ /**
+ * Generates a RET instruction.
+ *
+ * @param local
+ * a local variable identifier, as returned by
+ * {@link LocalVariablesSorter#newLocal(Type) newLocal()}.
+ */
+ public void ret(final int local) {
+ mv.visitVarInsn(Opcodes.RET, local);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys
+ * the switch case keys.
+ * @param generator
+ * a generator to generate the code for the switch cases.
+ */
+ public void tableSwitch(final int[] keys,
+ final TableSwitchGenerator generator) {
+ float density;
+ if (keys.length == 0) {
+ density = 0;
+ } else {
+ density = (float) keys.length
+ / (keys[keys.length - 1] - keys[0] + 1);
+ }
+ tableSwitch(keys, generator, density >= 0.5f);
+ }
+
+ /**
+ * Generates the instructions for a switch statement.
+ *
+ * @param keys
+ * the switch case keys.
+ * @param generator
+ * a generator to generate the code for the switch cases.
+ * @param useTable
+ * <tt>true</tt> to use a TABLESWITCH instruction, or
+ * <tt>false</tt> to use a LOOKUPSWITCH instruction.
+ */
+ public void tableSwitch(final int[] keys,
+ final TableSwitchGenerator generator, final boolean useTable) {
+ for (int i = 1; i < keys.length; ++i) {
+ if (keys[i] < keys[i - 1]) {
+ throw new IllegalArgumentException(
+ "keys must be sorted ascending");
+ }
+ }
+ Label def = newLabel();
+ Label end = newLabel();
+ if (keys.length > 0) {
+ int len = keys.length;
+ int min = keys[0];
+ int max = keys[len - 1];
+ int range = max - min + 1;
+ if (useTable) {
+ Label[] labels = new Label[range];
+ Arrays.fill(labels, def);
+ for (int i = 0; i < len; ++i) {
+ labels[keys[i] - min] = newLabel();
+ }
+ mv.visitTableSwitchInsn(min, max, def, labels);
+ for (int i = 0; i < range; ++i) {
+ Label label = labels[i];
+ if (label != def) {
+ mark(label);
+ generator.generateCase(i + min, end);
+ }
+ }
+ } else {
+ Label[] labels = new Label[len];
+ for (int i = 0; i < len; ++i) {
+ labels[i] = newLabel();
+ }
+ mv.visitLookupSwitchInsn(def, keys, labels);
+ for (int i = 0; i < len; ++i) {
+ mark(labels[i]);
+ generator.generateCase(keys[i], end);
+ }
+ }
+ }
+ mark(def);
+ generator.generateDefault();
+ mark(end);
+ }
+
+ /**
+ * Generates the instruction to return the top stack value to the caller.
+ */
+ public void returnValue() {
+ mv.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to load and store fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a get field or set field instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param ownerType
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param fieldType
+ * the type of the field.
+ */
+ private void fieldInsn(final int opcode, final Type ownerType,
+ final String name, final Type fieldType) {
+ mv.visitFieldInsn(opcode, ownerType.getInternalName(), name,
+ fieldType.getDescriptor());
+ }
+
+ /**
+ * Generates the instruction to push the value of a static field on the
+ * stack.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void getStatic(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.GETSTATIC, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a static field.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void putStatic(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to push the value of a non static field on the
+ * stack.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void getField(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.GETFIELD, owner, name, type);
+ }
+
+ /**
+ * Generates the instruction to store the top stack value in a non static
+ * field.
+ *
+ * @param owner
+ * the class in which the field is defined.
+ * @param name
+ * the name of the field.
+ * @param type
+ * the type of the field.
+ */
+ public void putField(final Type owner, final String name, final Type type) {
+ fieldInsn(Opcodes.PUTFIELD, owner, name, type);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to invoke methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates an invoke method instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param type
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ private void invokeInsn(final int opcode, final Type type,
+ final Method method, final boolean itf) {
+ String owner = type.getSort() == Type.ARRAY ? type.getDescriptor()
+ : type.getInternalName();
+ mv.visitMethodInsn(opcode, owner, method.getName(),
+ method.getDescriptor(), itf);
+ }
+
+ /**
+ * Generates the instruction to invoke a normal method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeVirtual(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke a constructor.
+ *
+ * @param type
+ * the class in which the constructor is defined.
+ * @param method
+ * the constructor to be invoked.
+ */
+ public void invokeConstructor(final Type type, final Method method) {
+ invokeInsn(Opcodes.INVOKESPECIAL, type, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke a static method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeStatic(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKESTATIC, owner, method, false);
+ }
+
+ /**
+ * Generates the instruction to invoke an interface method.
+ *
+ * @param owner
+ * the class in which the method is defined.
+ * @param method
+ * the method to be invoked.
+ */
+ public void invokeInterface(final Type owner, final Method method) {
+ invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true);
+ }
+
+ /**
+ * Generates an invokedynamic instruction.
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the
+ * array so a caller should expect that this array may change.
+ */
+ public void invokeDynamic(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ // ------------------------------------------------------------------------
+ // Instructions to create objects and arrays
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates a type dependent instruction.
+ *
+ * @param opcode
+ * the instruction's opcode.
+ * @param type
+ * the instruction's operand.
+ */
+ private void typeInsn(final int opcode, final Type type) {
+ mv.visitTypeInsn(opcode, type.getInternalName());
+ }
+
+ /**
+ * Generates the instruction to create a new object.
+ *
+ * @param type
+ * the class of the object to be created.
+ */
+ public void newInstance(final Type type) {
+ typeInsn(Opcodes.NEW, type);
+ }
+
+ /**
+ * Generates the instruction to create a new array.
+ *
+ * @param type
+ * the type of the array elements.
+ */
+ public void newArray(final Type type) {
+ int typ;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ typ = Opcodes.T_BOOLEAN;
+ break;
+ case Type.CHAR:
+ typ = Opcodes.T_CHAR;
+ break;
+ case Type.BYTE:
+ typ = Opcodes.T_BYTE;
+ break;
+ case Type.SHORT:
+ typ = Opcodes.T_SHORT;
+ break;
+ case Type.INT:
+ typ = Opcodes.T_INT;
+ break;
+ case Type.FLOAT:
+ typ = Opcodes.T_FLOAT;
+ break;
+ case Type.LONG:
+ typ = Opcodes.T_LONG;
+ break;
+ case Type.DOUBLE:
+ typ = Opcodes.T_DOUBLE;
+ break;
+ default:
+ typeInsn(Opcodes.ANEWARRAY, type);
+ return;
+ }
+ mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+ }
+
+ // ------------------------------------------------------------------------
+ // Miscelaneous instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Generates the instruction to compute the length of an array.
+ */
+ public void arrayLength() {
+ mv.visitInsn(Opcodes.ARRAYLENGTH);
+ }
+
+ /**
+ * Generates the instruction to throw an exception.
+ */
+ public void throwException() {
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+
+ /**
+ * Generates the instructions to create and throw an exception. The
+ * exception class must have a constructor with a single String argument.
+ *
+ * @param type
+ * the class of the exception to be thrown.
+ * @param msg
+ * the detailed message of the exception.
+ */
+ public void throwException(final Type type, final String msg) {
+ newInstance(type);
+ dup();
+ push(msg);
+ invokeConstructor(type, Method.getMethod("void <init> (String)"));
+ throwException();
+ }
+
+ /**
+ * Generates the instruction to check that the top stack value is of the
+ * given type.
+ *
+ * @param type
+ * a class or interface type.
+ */
+ public void checkCast(final Type type) {
+ if (!type.equals(OBJECT_TYPE)) {
+ typeInsn(Opcodes.CHECKCAST, type);
+ }
+ }
+
+ /**
+ * Generates the instruction to test if the top stack value is of the given
+ * type.
+ *
+ * @param type
+ * a class or interface type.
+ */
+ public void instanceOf(final Type type) {
+ typeInsn(Opcodes.INSTANCEOF, type);
+ }
+
+ /**
+ * Generates the instruction to get the monitor of the top stack value.
+ */
+ public void monitorEnter() {
+ mv.visitInsn(Opcodes.MONITORENTER);
+ }
+
+ /**
+ * Generates the instruction to release the monitor of the top stack value.
+ */
+ public void monitorExit() {
+ mv.visitInsn(Opcodes.MONITOREXIT);
+ }
+
+ // ------------------------------------------------------------------------
+ // Non instructions
+ // ------------------------------------------------------------------------
+
+ /**
+ * Marks the end of the visited method.
+ */
+ public void endMethod() {
+ if ((access & Opcodes.ACC_ABSTRACT) == 0) {
+ mv.visitMaxs(0, 0);
+ }
+ mv.visitEnd();
+ }
+
+ /**
+ * Marks the start of an exception handler.
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param exception
+ * internal name of the type of exceptions handled by the
+ * handler.
+ */
+ public void catchException(final Label start, final Label end,
+ final Type exception) {
+ if (exception == null) {
+ mv.visitTryCatchBlock(start, end, mark(), null);
+ } else {
+ mv.visitTryCatchBlock(start, end, mark(),
+ exception.getInternalName());
+ }
+ }
+}
[13/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
new file mode 100644
index 0000000..bffd20e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Remapper.java
@@ -0,0 +1,223 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.apache.tapestry5.internal.plastic.asm.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names. Subclasses can override
+ * the following methods:
+ *
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ *
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+ public String mapDesc(String desc) {
+ Type t = Type.getType(desc);
+ switch (t.getSort()) {
+ case Type.ARRAY:
+ String s = mapDesc(t.getElementType().getDescriptor());
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return s;
+ case Type.OBJECT:
+ String newType = map(t.getInternalName());
+ if (newType != null) {
+ return 'L' + newType + ';';
+ }
+ }
+ return desc;
+ }
+
+ private Type mapType(Type t) {
+ switch (t.getSort()) {
+ case Type.ARRAY:
+ String s = mapDesc(t.getElementType().getDescriptor());
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return Type.getType(s);
+ case Type.OBJECT:
+ s = map(t.getInternalName());
+ return s != null ? Type.getObjectType(s) : t;
+ case Type.METHOD:
+ return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
+ }
+ return t;
+ }
+
+ public String mapType(String type) {
+ if (type == null) {
+ return null;
+ }
+ return mapType(Type.getObjectType(type)).getInternalName();
+ }
+
+ public String[] mapTypes(String[] types) {
+ String[] newTypes = null;
+ boolean needMapping = false;
+ for (int i = 0; i < types.length; i++) {
+ String type = types[i];
+ String newType = map(type);
+ if (newType != null && newTypes == null) {
+ newTypes = new String[types.length];
+ if (i > 0) {
+ System.arraycopy(types, 0, newTypes, 0, i);
+ }
+ needMapping = true;
+ }
+ if (needMapping) {
+ newTypes[i] = newType == null ? type : newType;
+ }
+ }
+ return needMapping ? newTypes : types;
+ }
+
+ public String mapMethodDesc(String desc) {
+ if ("()V".equals(desc)) {
+ return desc;
+ }
+
+ Type[] args = Type.getArgumentTypes(desc);
+ StringBuffer s = new StringBuffer("(");
+ for (int i = 0; i < args.length; i++) {
+ s.append(mapDesc(args[i].getDescriptor()));
+ }
+ Type returnType = Type.getReturnType(desc);
+ if (returnType == Type.VOID_TYPE) {
+ s.append(")V");
+ return s.toString();
+ }
+ s.append(')').append(mapDesc(returnType.getDescriptor()));
+ return s.toString();
+ }
+
+ public Object mapValue(Object value) {
+ if (value instanceof Type) {
+ return mapType((Type) value);
+ }
+ if (value instanceof Handle) {
+ Handle h = (Handle) value;
+ return new Handle(h.getTag(), mapType(h.getOwner()), mapMethodName(
+ h.getOwner(), h.getName(), h.getDesc()),
+ mapMethodDesc(h.getDesc()));
+ }
+ return value;
+ }
+
+ /**
+ *
+ * @param typeSignature
+ * true if signature is a FieldTypeSignature, such as the
+ * signature parameter of the ClassVisitor.visitField or
+ * MethodVisitor.visitLocalVariable methods
+ */
+ public String mapSignature(String signature, boolean typeSignature) {
+ if (signature == null) {
+ return null;
+ }
+ SignatureReader r = new SignatureReader(signature);
+ SignatureWriter w = new SignatureWriter();
+ SignatureVisitor a = createRemappingSignatureAdapter(w);
+ if (typeSignature) {
+ r.acceptType(a);
+ } else {
+ r.accept(a);
+ }
+ return w.toString();
+ }
+
+ protected SignatureVisitor createRemappingSignatureAdapter(
+ SignatureVisitor v) {
+ return new RemappingSignatureAdapter(v, this);
+ }
+
+ /**
+ * Map method name to the new name. Subclasses can override.
+ *
+ * @param owner
+ * owner of the method.
+ * @param name
+ * name of the method.
+ * @param desc
+ * descriptor of the method.
+ * @return new name of the method
+ */
+ public String mapMethodName(String owner, String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map invokedynamic method name to the new name. Subclasses can override.
+ *
+ * @param name
+ * name of the invokedynamic.
+ * @param desc
+ * descriptor of the invokedynamic.
+ * @return new invokdynamic name.
+ */
+ public String mapInvokeDynamicMethodName(String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map field name to the new name. Subclasses can override.
+ *
+ * @param owner
+ * owner of the field.
+ * @param name
+ * name of the field
+ * @param desc
+ * descriptor of the field
+ * @return new name of the field.
+ */
+ public String mapFieldName(String owner, String name, String desc) {
+ return name;
+ }
+
+ /**
+ * Map type name to the new name. Subclasses can override.
+ */
+ public String map(String typeName) {
+ return typeName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
new file mode 100644
index 0000000..2f253dd
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingAnnotationAdapter.java
@@ -0,0 +1,79 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} adapter for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter extends AnnotationVisitor {
+
+ protected final Remapper remapper;
+
+ public RemappingAnnotationAdapter(final AnnotationVisitor av,
+ final Remapper remapper) {
+ this(Opcodes.ASM5, av, remapper);
+ }
+
+ protected RemappingAnnotationAdapter(final int api,
+ final AnnotationVisitor av, final Remapper remapper) {
+ super(api, av);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ av.visit(name, remapper.mapValue(value));
+ }
+
+ @Override
+ public void visitEnum(String name, String desc, String value) {
+ av.visitEnum(name, remapper.mapDesc(desc), value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ AnnotationVisitor v = av.visitAnnotation(name, remapper.mapDesc(desc));
+ return v == null ? null : (v == av ? this
+ : new RemappingAnnotationAdapter(v, remapper));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ AnnotationVisitor v = av.visitArray(name);
+ return v == null ? null : (v == av ? this
+ : new RemappingAnnotationAdapter(v, remapper));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
new file mode 100644
index 0000000..7dbae24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingClassAdapter.java
@@ -0,0 +1,135 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassVisitor {
+
+ protected final Remapper remapper;
+
+ protected String className;
+
+ public RemappingClassAdapter(final ClassVisitor cv, final Remapper remapper) {
+ this(Opcodes.ASM5, cv, remapper);
+ }
+
+ protected RemappingClassAdapter(final int api, final ClassVisitor cv,
+ final Remapper remapper) {
+ super(api, cv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces) {
+ this.className = name;
+ super.visit(version, access, remapper.mapType(name), remapper
+ .mapSignature(signature, false), remapper.mapType(superName),
+ interfaces == null ? null : remapper.mapTypes(interfaces));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? null : createRemappingAnnotationAdapter(av);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? null : createRemappingAnnotationAdapter(av);
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc,
+ String signature, Object value) {
+ FieldVisitor fv = super.visitField(access,
+ remapper.mapFieldName(className, name, desc),
+ remapper.mapDesc(desc), remapper.mapSignature(signature, true),
+ remapper.mapValue(value));
+ return fv == null ? null : createRemappingFieldAdapter(fv);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
+ String newDesc = remapper.mapMethodDesc(desc);
+ MethodVisitor mv = super.visitMethod(access, remapper.mapMethodName(
+ className, name, desc), newDesc, remapper.mapSignature(
+ signature, false),
+ exceptions == null ? null : remapper.mapTypes(exceptions));
+ return mv == null ? null : createRemappingMethodAdapter(access,
+ newDesc, mv);
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName,
+ String innerName, int access) {
+ // TODO should innerName be changed?
+ super.visitInnerClass(remapper.mapType(name), outerName == null ? null
+ : remapper.mapType(outerName), innerName, access);
+ }
+
+ @Override
+ public void visitOuterClass(String owner, String name, String desc) {
+ super.visitOuterClass(remapper.mapType(owner), name == null ? null
+ : remapper.mapMethodName(owner, name, desc),
+ desc == null ? null : remapper.mapMethodDesc(desc));
+ }
+
+ protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+ return new RemappingFieldAdapter(fv, remapper);
+ }
+
+ protected MethodVisitor createRemappingMethodAdapter(int access,
+ String newDesc, MethodVisitor mv) {
+ return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+ }
+
+ protected AnnotationVisitor createRemappingAnnotationAdapter(
+ AnnotationVisitor av) {
+ return new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
new file mode 100644
index 0000000..8a8420d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} adapter for type remapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter extends FieldVisitor {
+
+ private final Remapper remapper;
+
+ public RemappingFieldAdapter(final FieldVisitor fv, final Remapper remapper) {
+ this(Opcodes.ASM5, fv, remapper);
+ }
+
+ protected RemappingFieldAdapter(final int api, final FieldVisitor fv,
+ final Remapper remapper) {
+ super(api, fv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
new file mode 100644
index 0000000..1dec924
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingMethodAdapter.java
@@ -0,0 +1,224 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link LocalVariablesSorter} for type mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+ protected final Remapper remapper;
+
+ public RemappingMethodAdapter(final int access, final String desc,
+ final MethodVisitor mv, final Remapper remapper) {
+ this(Opcodes.ASM5, access, desc, mv, remapper);
+ }
+
+ protected RemappingMethodAdapter(final int api, final int access,
+ final String desc, final MethodVisitor mv, final Remapper remapper) {
+ super(api, access, desc, mv);
+ this.remapper = remapper;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ AnnotationVisitor av = super.visitAnnotationDefault();
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationVisitor av = super.visitAnnotation(remapper.mapDesc(desc),
+ visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
+ AnnotationVisitor av = super.visitParameterAnnotation(parameter,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+ Object[] stack) {
+ super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack,
+ remapEntries(nStack, stack));
+ }
+
+ private Object[] remapEntries(int n, Object[] entries) {
+ for (int i = 0; i < n; i++) {
+ if (entries[i] instanceof String) {
+ Object[] newEntries = new Object[n];
+ if (i > 0) {
+ System.arraycopy(entries, 0, newEntries, 0, i);
+ }
+ do {
+ Object t = entries[i];
+ newEntries[i++] = t instanceof String ? remapper
+ .mapType((String) t) : t;
+ } while (i < n);
+ return newEntries;
+ }
+ }
+ return entries;
+ }
+
+ @Override
+ public void visitFieldInsn(int opcode, String owner, String name,
+ String desc) {
+ super.visitFieldInsn(opcode, remapper.mapType(owner),
+ remapper.mapFieldName(owner, name, desc),
+ remapper.mapDesc(desc));
+ }
+
+ @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(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ // Calling super.visitMethodInsn requires to call the correct version
+ // depending on this.api (otherwise infinite loops can occur). To
+ // simplify and to make it easier to automatically remove the backward
+ // compatibility code, we inline the code of the overridden method here.
+ // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN
+ // LocalVariableSorter.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, remapper.mapType(owner),
+ remapper.mapMethodName(owner, name, desc),
+ remapper.mapMethodDesc(desc), itf);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ for (int i = 0; i < bsmArgs.length; i++) {
+ bsmArgs[i] = remapper.mapValue(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(
+ remapper.mapInvokeDynamicMethodName(name, desc),
+ remapper.mapMethodDesc(desc), (Handle) remapper.mapValue(bsm),
+ bsmArgs);
+ }
+
+ @Override
+ public void visitTypeInsn(int opcode, String type) {
+ super.visitTypeInsn(opcode, remapper.mapType(type));
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ super.visitLdcInsn(remapper.mapValue(cst));
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitInsnAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
+ super.visitTryCatchBlock(start, end, handler, type == null ? null
+ : remapper.mapType(type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ AnnotationVisitor av = super.visitTryCatchAnnotation(typeRef, typePath,
+ remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+
+ @Override
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
+ super.visitLocalVariable(name, remapper.mapDesc(desc),
+ remapper.mapSignature(signature, true), start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ AnnotationVisitor av = super.visitLocalVariableAnnotation(typeRef,
+ typePath, start, end, index, remapper.mapDesc(desc), visible);
+ return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
new file mode 100644
index 0000000..ff608a4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/RemappingSignatureAdapter.java
@@ -0,0 +1,155 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} adapter for type mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter extends SignatureVisitor {
+
+ private final SignatureVisitor v;
+
+ private final Remapper remapper;
+
+ private String className;
+
+ public RemappingSignatureAdapter(final SignatureVisitor v,
+ final Remapper remapper) {
+ this(Opcodes.ASM5, v, remapper);
+ }
+
+ protected RemappingSignatureAdapter(final int api,
+ final SignatureVisitor v, final Remapper remapper) {
+ super(api);
+ this.v = v;
+ this.remapper = remapper;
+ }
+
+ @Override
+ public void visitClassType(String name) {
+ className = name;
+ v.visitClassType(remapper.mapType(name));
+ }
+
+ @Override
+ public void visitInnerClassType(String name) {
+ String remappedOuter = remapper.mapType(className) + '$';
+ className = className + '$' + name;
+ String remappedName = remapper.mapType(className);
+ int index = remappedName.startsWith(remappedOuter) ? remappedOuter
+ .length() : remappedName.lastIndexOf('$') + 1;
+ v.visitInnerClassType(remappedName.substring(index));
+ }
+
+ @Override
+ public void visitFormalTypeParameter(String name) {
+ v.visitFormalTypeParameter(name);
+ }
+
+ @Override
+ public void visitTypeVariable(String name) {
+ v.visitTypeVariable(name);
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ v.visitArrayType();
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(char descriptor) {
+ v.visitBaseType(descriptor);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ v.visitClassBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ v.visitExceptionType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ v.visitInterface();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ v.visitInterfaceBound();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ v.visitParameterType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ v.visitReturnType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ v.visitSuperclass();
+ return this;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ v.visitTypeArgument();
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(char wildcard) {
+ v.visitTypeArgument(wildcard);
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ v.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
new file mode 100644
index 0000000..04dcc9b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SerialVersionUIDAdder.java
@@ -0,0 +1,540 @@
+/***
+ * 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.commons;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that adds a serial version unique identifier to a
+ * class if missing. Here is typical usage of this class:
+ *
+ * <pre>
+ * ClassWriter cw = new ClassWriter(...);
+ * ClassVisitor sv = new SerialVersionUIDAdder(cw);
+ * ClassVisitor ca = new MyClassAdapter(sv);
+ * new ClassReader(orginalClass).accept(ca, false);
+ * </pre>
+ *
+ * The SVUID algorithm can be found <a href=
+ * "http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html"
+ * >http://java.sun.com/j2se/1.4.2/docs/guide/serialization/spec/class.html</a>:
+ *
+ * <pre>
+ * The serialVersionUID is computed using the signature of a stream of bytes
+ * that reflect the class definition. The National Institute of Standards and
+ * Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a
+ * signature for the stream. The first two 32-bit quantities are used to form a
+ * 64-bit hash. A java.lang.DataOutputStream is used to convert primitive data
+ * types to a sequence of bytes. The values input to the stream are defined by
+ * the Java Virtual Machine (VM) specification for classes.
+ *
+ * The sequence of items in the stream is as follows:
+ *
+ * 1. The class name written using UTF encoding.
+ * 2. The class modifiers written as a 32-bit integer.
+ * 3. The name of each interface sorted by name written using UTF encoding.
+ * 4. For each field of the class sorted by field name (except private static
+ * and private transient fields):
+ * 1. The name of the field in UTF encoding.
+ * 2. The modifiers of the field written as a 32-bit integer.
+ * 3. The descriptor of the field in UTF encoding
+ * 5. If a class initializer exists, write out the following:
+ * 1. The name of the method, <clinit>, in UTF encoding.
+ * 2. The modifier of the method, java.lang.reflect.Modifier.STATIC,
+ * written as a 32-bit integer.
+ * 3. The descriptor of the method, ()V, in UTF encoding.
+ * 6. For each non-private constructor sorted by method name and signature:
+ * 1. The name of the method, <init>, in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 7. For each non-private method sorted by method name and signature:
+ * 1. The name of the method in UTF encoding.
+ * 2. The modifiers of the method written as a 32-bit integer.
+ * 3. The descriptor of the method in UTF encoding.
+ * 8. The SHA-1 algorithm is executed on the stream of bytes produced by
+ * DataOutputStream and produces five 32-bit values sha[0..4].
+ *
+ * 9. The hash value is assembled from the first and second 32-bit values of
+ * the SHA-1 message digest. If the result of the message digest, the five
+ * 32-bit words H0 H1 H2 H3 H4, is in an array of five int values named
+ * sha, the hash value would be computed as follows:
+ *
+ * long hash = ((sha[0] >>> 24) & 0xFF) |
+ * ((sha[0] >>> 16) & 0xFF) << 8 |
+ * ((sha[0] >>> 8) & 0xFF) << 16 |
+ * ((sha[0] >>> 0) & 0xFF) << 24 |
+ * ((sha[1] >>> 24) & 0xFF) << 32 |
+ * ((sha[1] >>> 16) & 0xFF) << 40 |
+ * ((sha[1] >>> 8) & 0xFF) << 48 |
+ * ((sha[1] >>> 0) & 0xFF) << 56;
+ * </pre>
+ *
+ * @author Rajendra Inamdar, Vishal Vishnoi
+ */
+public class SerialVersionUIDAdder extends ClassVisitor {
+
+ /**
+ * Flag that indicates if we need to compute SVUID.
+ */
+ private boolean computeSVUID;
+
+ /**
+ * Set to true if the class already has SVUID.
+ */
+ private boolean hasSVUID;
+
+ /**
+ * Classes access flags.
+ */
+ private int access;
+
+ /**
+ * Internal name of the class
+ */
+ private String name;
+
+ /**
+ * Interfaces implemented by the class.
+ */
+ private String[] interfaces;
+
+ /**
+ * Collection of fields. (except private static and private transient
+ * fields)
+ */
+ private Collection<Item> svuidFields;
+
+ /**
+ * Set to true if the class has static initializer.
+ */
+ private boolean hasStaticInitializer;
+
+ /**
+ * Collection of non-private constructors.
+ */
+ private Collection<Item> svuidConstructors;
+
+ /**
+ * Collection of non-private methods.
+ */
+ private Collection<Item> svuidMethods;
+
+ /**
+ * Creates a new {@link SerialVersionUIDAdder}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #SerialVersionUIDAdder(int, ClassVisitor)} version.
+ *
+ * @param cv
+ * a {@link ClassVisitor} to which this visitor will delegate
+ * calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public SerialVersionUIDAdder(final ClassVisitor cv) {
+ this(Opcodes.ASM5, cv);
+ if (getClass() != SerialVersionUIDAdder.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link SerialVersionUIDAdder}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param cv
+ * a {@link ClassVisitor} to which this visitor will delegate
+ * calls.
+ */
+ protected SerialVersionUIDAdder(final int api, final ClassVisitor cv) {
+ super(api, cv);
+ svuidFields = new ArrayList<Item>();
+ svuidConstructors = new ArrayList<Item>();
+ svuidMethods = new ArrayList<Item>();
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ /*
+ * Visit class header and get class name, access , and interfaces
+ * information (step 1,2, and 3) for SVUID computation.
+ */
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ computeSVUID = (access & Opcodes.ACC_INTERFACE) == 0;
+
+ if (computeSVUID) {
+ this.name = name;
+ this.access = access;
+ this.interfaces = new String[interfaces.length];
+ System.arraycopy(interfaces, 0, this.interfaces, 0,
+ interfaces.length);
+ }
+
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ /*
+ * Visit the methods and get constructor and method information (step 5 and
+ * 7). Also determine if there is a class initializer (step 6).
+ */
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ if (computeSVUID) {
+ if ("<clinit>".equals(name)) {
+ hasStaticInitializer = true;
+ }
+ /*
+ * Remembers non private constructors and methods for SVUID
+ * computation For constructor and method modifiers, only the
+ * ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
+ * ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT flags
+ * are used.
+ */
+ int mods = access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL | Opcodes.ACC_SYNCHRONIZED
+ | Opcodes.ACC_NATIVE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_STRICT);
+
+ // all non private methods
+ if ((access & Opcodes.ACC_PRIVATE) == 0) {
+ if ("<init>".equals(name)) {
+ svuidConstructors.add(new Item(name, mods, desc));
+ } else if (!"<clinit>".equals(name)) {
+ svuidMethods.add(new Item(name, mods, desc));
+ }
+ }
+ }
+
+ return super.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ /*
+ * Gets class field information for step 4 of the algorithm. Also determines
+ * if the class already has a SVUID.
+ */
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if (computeSVUID) {
+ if ("serialVersionUID".equals(name)) {
+ // since the class already has SVUID, we won't be computing it.
+ computeSVUID = false;
+ hasSVUID = true;
+ }
+ /*
+ * Remember field for SVUID computation For field modifiers, only
+ * the ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC,
+ * ACC_FINAL, ACC_VOLATILE, and ACC_TRANSIENT flags are used when
+ * computing serialVersionUID values.
+ */
+ if ((access & Opcodes.ACC_PRIVATE) == 0
+ || (access & (Opcodes.ACC_STATIC | Opcodes.ACC_TRANSIENT)) == 0) {
+ int mods = access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE
+ | Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC
+ | Opcodes.ACC_FINAL | Opcodes.ACC_VOLATILE | Opcodes.ACC_TRANSIENT);
+ svuidFields.add(new Item(name, mods, desc));
+ }
+ }
+
+ return super.visitField(access, name, desc, signature, value);
+ }
+
+ /**
+ * Handle a bizarre special case. Nested classes (static classes declared
+ * inside another class) that are protected have their access bit set to
+ * public in their class files to deal with some odd reflection situation.
+ * Our SVUID computation must do as the JVM does and ignore access bits in
+ * the class file in favor of the access bits InnerClass attribute.
+ */
+ @Override
+ public void visitInnerClass(final String aname, final String outerName,
+ final String innerName, final int attr_access) {
+ if ((name != null) && name.equals(aname)) {
+ this.access = attr_access;
+ }
+ super.visitInnerClass(aname, outerName, innerName, attr_access);
+ }
+
+ /*
+ * Add the SVUID if class doesn't have one
+ */
+ @Override
+ public void visitEnd() {
+ // compute SVUID and add it to the class
+ if (computeSVUID && !hasSVUID) {
+ try {
+ addSVUID(computeSVUID());
+ } catch (Throwable e) {
+ throw new RuntimeException("Error while computing SVUID for "
+ + name, e);
+ }
+ }
+
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns true if the class already has a SVUID field. The result of this
+ * method is only valid when visitEnd is or has been called.
+ *
+ * @return true if the class already has a SVUID field.
+ */
+ public boolean hasSVUID() {
+ return hasSVUID;
+ }
+
+ protected void addSVUID(long svuid) {
+ FieldVisitor fv = super.visitField(Opcodes.ACC_FINAL
+ + Opcodes.ACC_STATIC, "serialVersionUID", "J", null, new Long(
+ svuid));
+ if (fv != null) {
+ fv.visitEnd();
+ }
+ }
+
+ /**
+ * Computes and returns the value of SVUID.
+ *
+ * @return Returns the serial version UID
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ protected long computeSVUID() throws IOException {
+ ByteArrayOutputStream bos;
+ DataOutputStream dos = null;
+ long svuid = 0;
+
+ try {
+ bos = new ByteArrayOutputStream();
+ dos = new DataOutputStream(bos);
+
+ /*
+ * 1. The class name written using UTF encoding.
+ */
+ dos.writeUTF(name.replace('/', '.'));
+
+ /*
+ * 2. The class modifiers written as a 32-bit integer.
+ */
+ dos.writeInt(access
+ & (Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL
+ | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT));
+
+ /*
+ * 3. The name of each interface sorted by name written using UTF
+ * encoding.
+ */
+ Arrays.sort(interfaces);
+ for (int i = 0; i < interfaces.length; i++) {
+ dos.writeUTF(interfaces[i].replace('/', '.'));
+ }
+
+ /*
+ * 4. For each field of the class sorted by field name (except
+ * private static and private transient fields):
+ *
+ * 1. The name of the field in UTF encoding. 2. The modifiers of the
+ * field written as a 32-bit integer. 3. The descriptor of the field
+ * in UTF encoding
+ *
+ * Note that field signatures are not dot separated. Method and
+ * constructor signatures are dot separated. Go figure...
+ */
+ writeItems(svuidFields, dos, false);
+
+ /*
+ * 5. If a class initializer exists, write out the following: 1. The
+ * name of the method, <clinit>, in UTF encoding. 2. The modifier of
+ * the method, java.lang.reflect.Modifier.STATIC, written as a
+ * 32-bit integer. 3. The descriptor of the method, ()V, in UTF
+ * encoding.
+ */
+ if (hasStaticInitializer) {
+ dos.writeUTF("<clinit>");
+ dos.writeInt(Opcodes.ACC_STATIC);
+ dos.writeUTF("()V");
+ } // if..
+
+ /*
+ * 6. For each non-private constructor sorted by method name and
+ * signature: 1. The name of the method, <init>, in UTF encoding. 2.
+ * The modifiers of the method written as a 32-bit integer. 3. The
+ * descriptor of the method in UTF encoding.
+ */
+ writeItems(svuidConstructors, dos, true);
+
+ /*
+ * 7. For each non-private method sorted by method name and
+ * signature: 1. The name of the method in UTF encoding. 2. The
+ * modifiers of the method written as a 32-bit integer. 3. The
+ * descriptor of the method in UTF encoding.
+ */
+ writeItems(svuidMethods, dos, true);
+
+ dos.flush();
+
+ /*
+ * 8. The SHA-1 algorithm is executed on the stream of bytes
+ * produced by DataOutputStream and produces five 32-bit values
+ * sha[0..4].
+ */
+ byte[] hashBytes = computeSHAdigest(bos.toByteArray());
+
+ /*
+ * 9. The hash value is assembled from the first and second 32-bit
+ * values of the SHA-1 message digest. If the result of the message
+ * digest, the five 32-bit words H0 H1 H2 H3 H4, is in an array of
+ * five int values named sha, the hash value would be computed as
+ * follows:
+ *
+ * long hash = ((sha[0] >>> 24) & 0xFF) | ((sha[0] >>> 16) & 0xFF)
+ * << 8 | ((sha[0] >>> 8) & 0xFF) << 16 | ((sha[0] >>> 0) & 0xFF) <<
+ * 24 | ((sha[1] >>> 24) & 0xFF) << 32 | ((sha[1] >>> 16) & 0xFF) <<
+ * 40 | ((sha[1] >>> 8) & 0xFF) << 48 | ((sha[1] >>> 0) & 0xFF) <<
+ * 56;
+ */
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ svuid = (svuid << 8) | (hashBytes[i] & 0xFF);
+ }
+ } finally {
+ // close the stream (if open)
+ if (dos != null) {
+ dos.close();
+ }
+ }
+
+ return svuid;
+ }
+
+ /**
+ * Returns the SHA-1 message digest of the given value.
+ *
+ * @param value
+ * the value whose SHA message digest must be computed.
+ * @return the SHA-1 message digest of the given value.
+ */
+ protected byte[] computeSHAdigest(final byte[] value) {
+ try {
+ return MessageDigest.getInstance("SHA").digest(value);
+ } catch (Exception e) {
+ throw new UnsupportedOperationException(e.toString());
+ }
+ }
+
+ /**
+ * Sorts the items in the collection and writes it to the data output stream
+ *
+ * @param itemCollection
+ * collection of items
+ * @param dos
+ * a <code>DataOutputStream</code> value
+ * @param dotted
+ * a <code>boolean</code> value
+ * @exception IOException
+ * if an error occurs
+ */
+ private static void writeItems(final Collection<Item> itemCollection,
+ final DataOutput dos, final boolean dotted) throws IOException {
+ int size = itemCollection.size();
+ Item[] items = itemCollection.toArray(new Item[size]);
+ Arrays.sort(items);
+ for (int i = 0; i < size; i++) {
+ dos.writeUTF(items[i].name);
+ dos.writeInt(items[i].access);
+ dos.writeUTF(dotted ? items[i].desc.replace('/', '.')
+ : items[i].desc);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Inner classes
+ // ------------------------------------------------------------------------
+
+ private static class Item implements Comparable<Item> {
+
+ final String name;
+
+ final int access;
+
+ final String desc;
+
+ Item(final String name, final int access, final String desc) {
+ this.name = name;
+ this.access = access;
+ this.desc = desc;
+ }
+
+ public int compareTo(final Item other) {
+ int retVal = name.compareTo(other.name);
+ if (retVal == 0) {
+ retVal = desc.compareTo(other.desc);
+ }
+ return retVal;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o instanceof Item) {
+ return compareTo((Item) o) == 0;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (name + desc).hashCode();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
new file mode 100644
index 0000000..25b594d
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/SimpleRemapper.java
@@ -0,0 +1,69 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * A {@link Remapper} using a {@link Map} to define its mapping.
+ *
+ * @author Eugene Kuleshov
+ */
+public class SimpleRemapper extends Remapper {
+
+ private final Map<String, String> mapping;
+
+ public SimpleRemapper(Map<String, String> mapping) {
+ this.mapping = mapping;
+ }
+
+ public SimpleRemapper(String oldName, String newName) {
+ this.mapping = Collections.singletonMap(oldName, newName);
+ }
+
+ @Override
+ public String mapMethodName(String owner, String name, String desc) {
+ String s = map(owner + '.' + name + desc);
+ return s == null ? name : s;
+ }
+
+ @Override
+ public String mapFieldName(String owner, String name, String desc) {
+ String s = map(owner + '.' + name);
+ return s == null ? name : s;
+ }
+
+ @Override
+ public String map(String key) {
+ return mapping.get(key);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.java
new file mode 100644
index 0000000..8291c66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/StaticInitMerger.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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that merges clinit methods into a single one.
+ *
+ * @author Eric Bruneton
+ */
+public class StaticInitMerger extends ClassVisitor {
+
+ private String name;
+
+ private MethodVisitor clinit;
+
+ private final String prefix;
+
+ private int counter;
+
+ public StaticInitMerger(final String prefix, final ClassVisitor cv) {
+ this(Opcodes.ASM5, prefix, cv);
+ }
+
+ protected StaticInitMerger(final int api, final String prefix,
+ final ClassVisitor cv) {
+ super(api, cv);
+ this.prefix = prefix;
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ this.name = name;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodVisitor mv;
+ if ("<clinit>".equals(name)) {
+ int a = Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC;
+ String n = prefix + counter++;
+ mv = cv.visitMethod(a, n, desc, signature, exceptions);
+
+ if (clinit == null) {
+ clinit = cv.visitMethod(a, name, desc, null, null);
+ }
+ clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc,
+ false);
+ } else {
+ mv = cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+ return mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ if (clinit != null) {
+ clinit.visitInsn(Opcodes.RETURN);
+ clinit.visitMaxs(0, 0);
+ }
+ cv.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
new file mode 100644
index 0000000..322d7bb
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TableSwitchGenerator.java
@@ -0,0 +1,57 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+
+/**
+ * A code generator for switch statements.
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public interface TableSwitchGenerator {
+
+ /**
+ * Generates the code for a switch case.
+ *
+ * @param key
+ * the switch case key.
+ * @param end
+ * a label that corresponds to the end of the switch statement.
+ */
+ void generateCase(int key, Label end);
+
+ /**
+ * Generates the code for the default switch case.
+ */
+ void generateDefault();
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
new file mode 100644
index 0000000..4b4641a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/TryCatchBlockSorter.java
@@ -0,0 +1,96 @@
+/***
+ * 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.commons;
+
+import java.util.Collections;
+import java.util.Comparator;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+
+/**
+ * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers
+ * are sorted in a method innermost-to-outermost. This allows the programmer to
+ * add handlers without worrying about ordering them correctly with respect to
+ * existing, in-code handlers.
+ *
+ * Behavior is only defined for properly-nested handlers. If any "try" blocks
+ * overlap (something that isn't possible in Java code) then this may not do
+ * what you want. In fact, this adapter just sorts by the length of the "try"
+ * block, taking advantage of the fact that a given try block must be larger
+ * than any block it contains).
+ *
+ * @author Adrian Sampson
+ */
+public class TryCatchBlockSorter extends MethodNode {
+
+ public TryCatchBlockSorter(final MethodVisitor mv, final int access,
+ final String name, final String desc, final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+ }
+
+ protected TryCatchBlockSorter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ super(api, access, name, desc, signature, exceptions);
+ this.mv = mv;
+ }
+
+ @Override
+ public void visitEnd() {
+ // Compares TryCatchBlockNodes by the length of their "try" block.
+ Comparator<TryCatchBlockNode> comp = new Comparator<TryCatchBlockNode>() {
+
+ public int compare(TryCatchBlockNode t1, TryCatchBlockNode t2) {
+ int len1 = blockLength(t1);
+ int len2 = blockLength(t2);
+ return len1 - len2;
+ }
+
+ private int blockLength(TryCatchBlockNode block) {
+ int startidx = instructions.indexOf(block.start);
+ int endidx = instructions.indexOf(block.end);
+ return endidx - startidx;
+ }
+ };
+ Collections.sort(tryCatchBlocks, comp);
+ // Updates the 'target' of each try catch block annotation.
+ for (int i = 0; i < tryCatchBlocks.size(); ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
+ }
+ if (mv != null) {
+ accept(mv);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
new file mode 100644
index 0000000..4ce0db8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/package.html
@@ -0,0 +1,48 @@
+<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>
+Provides some useful class and method adapters. <i>The preferred way of using
+these adapters is by chaining them together and to custom adapters (instead of
+inheriting from them)</i>. Indeed this approach provides more combination
+possibilities than inheritance. For instance, suppose you want to implement an
+adapter MyAdapter than needs sorted local variables and intermediate stack map
+frame values taking into account the local variables sort. By using inheritance,
+this would require MyAdapter to extend AnalyzerAdapter, itself extending
+LocalVariablesSorter. But AnalyzerAdapter is not a subclass of
+LocalVariablesSorter, so this is not possible. On the contrary, by using
+delegation, you can make LocalVariablesSorter delegate to AnalyzerAdapter,
+itself delegating to MyAdapter. In this case AnalyzerAdapter computes
+intermediate frames based on the output of LocalVariablesSorter, and MyAdapter
+can add new locals by calling the newLocal method on LocalVariablesSorter, and
+can get the stack map frame state before each instruction by reading the locals
+and stack fields in AnalyzerAdapter (this requires references from MyAdapter
+back to LocalVariablesSorter and AnalyzerAdapter).
+</body>
\ 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/optimizer/AnnotationConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
new file mode 100644
index 0000000..84aff49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/AnnotationConstantsCollector.java
@@ -0,0 +1,147 @@
+/***
+ * 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.optimizer;
+
+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 collects the {@link Constant}s of the
+ * annotations it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class AnnotationConstantsCollector extends AnnotationVisitor {
+
+ private final ConstantPool cp;
+
+ public AnnotationConstantsCollector(final AnnotationVisitor av,
+ final ConstantPool cp) {
+ super(Opcodes.ASM5, av);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ if (value instanceof Byte) {
+ cp.newInteger(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ cp.newInteger(((Boolean) value).booleanValue() ? 1 : 0);
+ } else if (value instanceof Character) {
+ cp.newInteger(((Character) value).charValue());
+ } else if (value instanceof Short) {
+ cp.newInteger(((Short) value).shortValue());
+ } else if (value instanceof Type) {
+ cp.newUTF8(((Type) value).getDescriptor());
+ } else if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i] ? 1 : 0);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newInteger(v[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newLong(v[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newFloat(v[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ cp.newDouble(v[i]);
+ }
+ } else {
+ cp.newConst(value);
+ }
+ av.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ cp.newUTF8(desc);
+ cp.newUTF8(value);
+ av.visitEnum(name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ cp.newUTF8(desc);
+ return new AnnotationConstantsCollector(av.visitAnnotation(name, desc),
+ cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ return new AnnotationConstantsCollector(av.visitArray(name), cp);
+ }
+
+ @Override
+ public void visitEnd() {
+ av.visitEnd();
+ }
+}
[19/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
index f0676b7..4585e67 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
@@ -30,27 +30,33 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java method. The methods of this class must be
- * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
- * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
- * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
- * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
- * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ]
- * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
- * and <tt>visitLabel</tt> methods must be called in the sequential order of
- * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
- * must be called <i>before</i> the labels passed as arguments have been
- * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
- * methods must be called <i>after</i> the labels passed as arguments have been
- * visited.
- *
+ * A visitor to visit a Java method. The methods of this class must be called in
+ * the following order: ( <tt>visitParameter</tt> )* [
+ * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [
+ * <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> |
+ * <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> |
+ * <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
+ * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
+ * addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must
+ * be called in the sequential order of the bytecode instructions of the visited
+ * code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
+ * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
+ * corresponding try catch block has been visited, and the
+ * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
+ * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
+ * passed as arguments have been visited.
+ *
* @author Eric Bruneton
*/
public abstract class MethodVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -62,9 +68,10 @@ public abstract class MethodVisitor {
/**
* Constructs a new {@link MethodVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodVisitor(final int api) {
this(api, null);
@@ -72,30 +79,51 @@ public abstract class MethodVisitor {
/**
* Constructs a new {@link MethodVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv the method visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public MethodVisitor(final int api, final MethodVisitor mv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.mv = mv;
}
// -------------------------------------------------------------------------
- // Annotations and non standard attributes
+ // Parameters, annotations and non standard attributes
// -------------------------------------------------------------------------
/**
+ * Visits a parameter of this method.
+ *
+ * @param name
+ * parameter name or null if none is provided.
+ * @param access
+ * the parameter's access flags, only <tt>ACC_FINAL</tt>,
+ * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
+ * allowed (see {@link Opcodes}).
+ */
+ public void visitParameter(String name, int access) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ mv.visitParameter(name, access);
+ }
+ }
+
+ /**
* Visits the default value of this annotation interface method.
- *
+ *
* @return a visitor to the visit the actual default value of this
- * annotation interface method, or <tt>null</tt> if this visitor
- * is not interested in visiting this default value. The 'name'
+ * annotation interface method, or <tt>null</tt> if this visitor is
+ * not interested in visiting this default value. The 'name'
* parameters passed to the methods of this annotation visitor are
* ignored. Moreover, exacly one visit method must be called on this
* annotation visitor, followed by visitEnd.
@@ -109,9 +137,11 @@ public abstract class MethodVisitor {
/**
* Visits an annotation of this method.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -123,19 +153,55 @@ public abstract class MethodVisitor {
}
/**
+ * Visits an annotation on a type in the method signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
+ * METHOD_TYPE_PARAMETER},
+ * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
+ * METHOD_TYPE_PARAMETER_BOUND},
+ * {@link TypeReference#METHOD_RETURN METHOD_RETURN},
+ * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link TypeReference#METHOD_FORMAL_PARAMETER
+ * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
+ * THROWS}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits an annotation of a parameter this method.
- *
- * @param parameter the parameter index.
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param parameter
+ * the parameter index.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
- public AnnotationVisitor visitParameterAnnotation(
- int parameter,
- String desc,
- boolean visible)
- {
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
if (mv != null) {
return mv.visitParameterAnnotation(parameter, desc, visible);
}
@@ -144,8 +210,9 @@ public abstract class MethodVisitor {
/**
* Visits a non standard attribute of this method.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (mv != null) {
@@ -169,57 +236,76 @@ public abstract class MethodVisitor {
* such as GOTO or THROW, that is the target of a jump instruction, or that
* starts an exception handler block. The visited types must describe the
* values of the local variables and of the operand stack elements <i>just
- * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
- * for classes whose version is greater than or equal to
- * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
- * "deltas" from the state of the previous frame (very first frame is
- * implicitly defined by the method's parameters and access flags): <ul>
+ * before</i> <b>i</b> is executed.<br>
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or
+ * equal to {@link Opcodes#V1_6 V1_6}. <br>
+ * <br>
+ * The frames of a method must be given either in expanded form, or in
+ * compressed form (all frames must use the same format, i.e. you must not
+ * mix expanded and compressed frames within a single method):
+ * <ul>
+ * <li>In expanded form, all frames must have the F_NEW type.</li>
+ * <li>In compressed form, frames are basically "deltas" from the state of
+ * the previous frame:
+ * <ul>
* <li>{@link Opcodes#F_SAME} representing frame with exactly the same
- * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
- * representing frame with exactly the same locals as the previous frame and
- * with single value on the stack (<code>nStack</code> is 1 and
- * <code>stack[0]</code> contains value for the type of the stack item).</li>
+ * locals as the previous frame and with the empty stack.</li>
+ * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
+ * locals as the previous frame and with single value on the stack (
+ * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
+ * type of the stack item).</li>
* <li>{@link Opcodes#F_APPEND} representing frame with current locals are
* the same as the locals in the previous frame, except that additional
* locals are defined (<code>nLocal</code> is 1, 2 or 3 and
* <code>local</code> elements contains values representing added types).</li>
- * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
- * the same as the locals in the previous frame, except that the last 1-3
- * locals are absent and with the empty stack (<code>nLocals</code> is 1,
- * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
- * data.</li> </li> </ul>
- *
- * @param type the type of this stack map frame. Must be
- * {@link Opcodes#F_NEW} for expanded frames, or
- * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
- * frames.
- * @param nLocal the number of local variables in the visited frame.
- * @param local the local variable types in this frame. This array must not
- * be modified. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are represented
- * by String objects (representing internal names), and uninitialized
- * types by Label objects (this label designates the NEW instruction
- * that created this uninitialized value).
- * @param nStack the number of operand stack elements in the visited frame.
- * @param stack the operand stack types in this frame. This array must not
- * be modified. Its content has the same format as the "local" array.
- * @throws IllegalStateException if a frame is visited just after another
- * one, without any instruction between the two (unless this frame
- * is a Opcodes#F_SAME frame, in which case it is silently ignored).
- */
- public void visitFrame(
- int type,
- int nLocal,
- Object[] local,
- int nStack,
- Object[] stack)
- {
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
+ * same as the locals in the previous frame, except that the last 1-3 locals
+ * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
+ * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * <br>
+ * In both cases the first frame, corresponding to the method's parameters
+ * and access flags, is implicit and must not be visited. Also, it is
+ * illegal to visit two or more frames for the same code location (i.e., at
+ * least one instruction must be visited between two calls to visitFrame).
+ *
+ * @param type
+ * the type of this stack map frame. Must be
+ * {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
+ * compressed frames.
+ * @param nLocal
+ * the number of local variables in the visited frame.
+ * @param local
+ * the local variable types in this frame. This array must not be
+ * modified. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are
+ * represented by String objects (representing internal names),
+ * and uninitialized types by Label objects (this label
+ * designates the NEW instruction that created this uninitialized
+ * value).
+ * @param nStack
+ * the number of operand stack elements in the visited frame.
+ * @param stack
+ * the operand stack types in this frame. This array must not be
+ * modified. Its content has the same format as the "local"
+ * array.
+ * @throws IllegalStateException
+ * if a frame is visited just after another one, without any
+ * instruction between the two (unless this frame is a
+ * Opcodes#F_SAME frame, in which case it is silently ignored).
+ */
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+ Object[] stack) {
if (mv != null) {
mv.visitFrame(type, nLocal, local, nStack, stack);
}
@@ -231,21 +317,23 @@ public abstract class MethodVisitor {
/**
* Visits a zero operand instruction.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either 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, IALOAD, LALOAD, FALOAD,
- * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, 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,
- * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
- * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
- * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
- * MONITORENTER, or MONITOREXIT.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either 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, IALOAD,
+ * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+ * 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, I2L, I2F, I2D,
+ * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+ * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+ * or MONITOREXIT.
*/
public void visitInsn(int opcode) {
if (mv != null) {
@@ -255,18 +343,21 @@ public abstract class MethodVisitor {
/**
* Visits an instruction with a single int operand.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand the operand of the instruction to be visited.<br> When
- * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
- * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
- * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
- * opcode is NEWARRAY, operand value should be one of
- * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
- * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
- * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
- * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand
+ * the operand of the instruction to be visited.<br>
+ * When opcode is BIPUSH, operand value should be between
+ * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+ * When opcode is SIPUSH, operand value should be between
+ * Short.MIN_VALUE and Short.MAX_VALUE.<br>
+ * When opcode is NEWARRAY, operand value should be one of
+ * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+ * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+ * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+ * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
*/
public void visitIntInsn(int opcode, int operand) {
if (mv != null) {
@@ -277,12 +368,14 @@ public abstract class MethodVisitor {
/**
* Visits a local variable instruction. A local variable instruction is an
* instruction that loads or stores the value of a local variable.
- *
- * @param opcode the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
- * LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be visited. This operand is
- * the index of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be visited.
+ * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
+ * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be visited. This operand is
+ * the index of a local variable.
*/
public void visitVarInsn(int opcode, int var) {
if (mv != null) {
@@ -293,12 +386,14 @@ public abstract class MethodVisitor {
/**
* Visits a type instruction. A type instruction is an instruction that
* takes the internal name of a class as parameter.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param type the operand of the instruction to be visited. This operand
- * must be the internal name of an object or array class (see {@link
- * Type#getInternalName() getInternalName}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type
+ * the operand of the instruction to be visited. This operand
+ * must be the internal name of an object or array class (see
+ * {@link Type#getInternalName() getInternalName}).
*/
public void visitTypeInsn(int opcode, String type) {
if (mv != null) {
@@ -309,15 +404,20 @@ public abstract class MethodVisitor {
/**
* Visits a field instruction. A field instruction is an instruction that
* loads or stores the value of a field of an object.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner the internal name of the field's owner class (see {@link
- * Type#getInternalName() getInternalName}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- */
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner
+ * the internal name of the field's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ */
+ public void visitFieldInsn(int opcode, String owner, String name,
+ String desc) {
if (mv != null) {
mv.visitFieldInsn(opcode, owner, name, desc);
}
@@ -326,34 +426,83 @@ public abstract class MethodVisitor {
/**
* Visits a method instruction. A method instruction is an instruction that
* invokes a method.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
- * or INVOKEINTERFACE.
- * @param owner the internal name of the method's owner class (see {@link
- * Type#getInternalName() getInternalName}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- */
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ @Deprecated
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, desc);
}
}
/**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param itf
+ * if the method's owner class is an interface.
+ */
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ /**
* Visits an invokedynamic instruction.
- *
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments. Each argument
- * must be an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the array
- * so a caller should expect that this array may change.
- */
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the
+ * array so a caller should expect that this array may change.
+ */
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
if (mv != null) {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
@@ -362,14 +511,16 @@ public abstract class MethodVisitor {
/**
* Visits a jump instruction. A jump instruction is an instruction that may
* jump to another instruction.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
- * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label the operand of the instruction to be visited. This operand
- * is a label that designates the instruction to which the jump
- * instruction may jump.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label
+ * the operand of the instruction to be visited. This operand is
+ * a label that designates the instruction to which the jump
+ * instruction may jump.
*/
public void visitJumpInsn(int opcode, Label label) {
if (mv != null) {
@@ -380,8 +531,9 @@ public abstract class MethodVisitor {
/**
* Visits a label. A label designates the instruction that will be visited
* just after it.
- *
- * @param label a {@link Label Label} object.
+ *
+ * @param label
+ * a {@link Label Label} object.
*/
public void visitLabel(Label label) {
if (mv != null) {
@@ -398,41 +550,44 @@ public abstract class MethodVisitor {
* future versions of the Java Virtual Machine. To easily detect new
* constant types, implementations of this method should check for
* unexpected constant types, like this:
+ *
* <pre>
* if (cst instanceof Integer) {
- * // ...
+ * // ...
* } else if (cst instanceof Float) {
- * // ...
+ * // ...
* } else if (cst instanceof Long) {
- * // ...
- * } else if (cst instanceof Double) {
- * // ...
- * } else if (cst instanceof String) {
- * // ...
- * } else if (cst instanceof Type) {
- * int sort = ((Type) cst).getSort();
- * if (sort == Type.OBJECT) {
* // ...
- * } else if (sort == Type.ARRAY) {
+ * } else if (cst instanceof Double) {
* // ...
- * } else if (sort == Type.METHOD) {
+ * } else if (cst instanceof String) {
* // ...
- * } else {
- * // throw an exception
- * }
+ * } else if (cst instanceof Type) {
+ * int sort = ((Type) cst).getSort();
+ * if (sort == Type.OBJECT) {
+ * // ...
+ * } else if (sort == Type.ARRAY) {
+ * // ...
+ * } else if (sort == Type.METHOD) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
* } else if (cst instanceof Handle) {
- * // ...
+ * // ...
* } else {
- * // throw an exception
- * }</pre>
- *
- * @param cst the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY
- * sort for <tt>.class</tt> constants, for classes whose version is
- * 49.0, a {@link Type} of METHOD sort or a {@link Handle} for
- * MethodType and MethodHandle constants, for classes whose version
- * is 51.0.
+ * // throw an exception
+ * }
+ * </pre>
+ *
+ * @param cst
+ * the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double}, a {@link String}, a {@link Type} of OBJECT or
+ * ARRAY sort for <tt>.class</tt> constants, for classes whose
+ * version is 49.0, a {@link Type} of METHOD sort or a
+ * {@link Handle} for MethodType and MethodHandle constants, for
+ * classes whose version is 51.0.
*/
public void visitLdcInsn(Object cst) {
if (mv != null) {
@@ -442,9 +597,11 @@ public abstract class MethodVisitor {
/**
* Visits an IINC instruction.
- *
- * @param var index of the local variable to be incremented.
- * @param increment amount to increment the local variable by.
+ *
+ * @param var
+ * index of the local variable to be incremented.
+ * @param increment
+ * amount to increment the local variable by.
*/
public void visitIincInsn(int var, int increment) {
if (mv != null) {
@@ -454,14 +611,19 @@ public abstract class MethodVisitor {
/**
* Visits a TABLESWITCH instruction.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>min + i</tt> key.
- */
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public void visitTableSwitchInsn(int min, int max, Label dflt,
+ Label... labels) {
if (mv != null) {
mv.visitTableSwitchInsn(min, max, dflt, labels);
}
@@ -469,11 +631,14 @@ public abstract class MethodVisitor {
/**
* Visits a LOOKUPSWITCH instruction.
- *
- * @param dflt beginning of the default handler block.
- * @param keys the values of the keys.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ *
+ * @param dflt
+ * beginning of the default handler block.
+ * @param keys
+ * the values of the keys.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>keys[i]</tt> key.
*/
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
if (mv != null) {
@@ -483,9 +648,11 @@ public abstract class MethodVisitor {
/**
* Visits a MULTIANEWARRAY instruction.
- *
- * @param desc an array type descriptor (see {@link Type Type}).
- * @param dims number of dimensions of the array to allocate.
+ *
+ * @param desc
+ * an array type descriptor (see {@link Type Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
*/
public void visitMultiANewArrayInsn(String desc, int dims) {
if (mv != null) {
@@ -493,68 +660,191 @@ public abstract class MethodVisitor {
}
}
+ /**
+ * Visits an annotation on an instruction. This method must be called just
+ * <i>after</i> the annotated instruction. It can be called several times
+ * for the same instruction.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
+ * {@link TypeReference#NEW NEW},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE
+ * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
+ * METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
+ * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
// -------------------------------------------------------------------------
// Exceptions table entries, debug information, max stack and max locals
// -------------------------------------------------------------------------
/**
* Visits a try catch block.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for "finally"
- * blocks).
- * @throws IllegalArgumentException if one of the labels has already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
- */
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
+ * @throws IllegalArgumentException
+ * if one of the labels has already been visited by this visitor
+ * (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
if (mv != null) {
mv.visitTryCatchBlock(start, end, handler, type);
}
}
/**
+ * Visits an annotation on an exception handler type. This method must be
+ * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
+ * exception handler. It can be called several times for the same exception
+ * handler.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#EXCEPTION_PARAMETER
+ * EXCEPTION_PARAMETER}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a local variable declaration.
- *
- * @param name the name of a local variable.
- * @param desc the type descriptor of this local variable.
- * @param signature the type signature of this local variable. May be
- * <tt>null</tt> if the local variable type does not use generic
- * types.
- * @param start the first instruction corresponding to the scope of this
- * local variable (inclusive).
- * @param end the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index the local variable's index.
- * @throws IllegalArgumentException if one of the labels has not already
- * been visited by this visitor (by the
- * {@link #visitLabel visitLabel} method).
- */
- public void visitLocalVariable(
- String name,
- String desc,
- String signature,
- Label start,
- Label end,
- int index)
- {
+ *
+ * @param name
+ * the name of a local variable.
+ * @param desc
+ * the type descriptor of this local variable.
+ * @param signature
+ * the type signature of this local variable. May be
+ * <tt>null</tt> if the local variable type does not use generic
+ * types.
+ * @param start
+ * the first instruction corresponding to the scope of this local
+ * variable (inclusive).
+ * @param end
+ * the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index
+ * the local variable's index.
+ * @throws IllegalArgumentException
+ * if one of the labels has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
if (mv != null) {
mv.visitLocalVariable(name, desc, signature, start, end, index);
}
}
/**
+ * Visits an annotation on a local variable type.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#LOCAL_VARIABLE
+ * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
+ * RESOURCE_VARIABLE}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
+ end, index, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a line number declaration.
- *
- * @param line a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start the first instruction corresponding to this line number.
- * @throws IllegalArgumentException if <tt>start</tt> has not already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
+ *
+ * @param line
+ * a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start
+ * the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException
+ * if <tt>start</tt> has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
*/
public void visitLineNumber(int line, Label start) {
if (mv != null) {
@@ -565,9 +855,11 @@ public abstract class MethodVisitor {
/**
* Visits the maximum stack size and the maximum number of local variables
* of the method.
- *
- * @param maxStack maximum stack size of the method.
- * @param maxLocals maximum number of local variables for the method.
+ *
+ * @param maxStack
+ * maximum stack size of the method.
+ * @param maxLocals
+ * maximum number of local variables for the method.
*/
public void visitMaxs(int maxStack, int maxLocals) {
if (mv != null) {
[18/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
index 70b26b8..3128ff6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodWriter.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* A {@link MethodVisitor} that generates methods in bytecode form. Each visit
* method of this class appends the bytecode corresponding to the visited
* instruction to a byte vector, in the order these methods are called.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -42,7 +42,7 @@ class MethodWriter extends MethodVisitor {
/**
* Pseudo access flag used to denote constructors.
*/
- static final int ACC_CONSTRUCTOR = 262144;
+ static final int ACC_CONSTRUCTOR = 0x80000;
/**
* Frame has exactly the same locals as the previous stack map frame and
@@ -96,7 +96,7 @@ class MethodWriter extends MethodVisitor {
* Indicates that the stack map frames must be recomputed from scratch. In
* this case the maximum stack size and number of local variables is also
* recomputed from scratch.
- *
+ *
* @see #compute
*/
private static final int FRAMES = 0;
@@ -104,14 +104,14 @@ class MethodWriter extends MethodVisitor {
/**
* Indicates that the maximum stack size and number of local variables must
* be automatically computed.
- *
+ *
* @see #compute
*/
private static final int MAXS = 1;
/**
* Indicates that nothing must be automatically computed.
- *
+ *
* @see #compute
*/
private static final int NOTHING = 2;
@@ -192,6 +192,18 @@ class MethodWriter extends MethodVisitor {
private AnnotationWriter ianns;
/**
+ * The runtime visible type annotations of this method. May be <tt>null</tt>
+ * .
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
* The runtime visible parameter annotations of this method. May be
* <tt>null</tt>.
*/
@@ -229,7 +241,7 @@ class MethodWriter extends MethodVisitor {
private int maxLocals;
/**
- * Number of local variables in the current stack map frame.
+ * Number of local variables in the current stack map frame.
*/
private int currentLocals;
@@ -251,17 +263,12 @@ class MethodWriter extends MethodVisitor {
/**
* The last frame that was written in the StackMapTable attribute.
- *
+ *
* @see #frame
*/
private int[] previousFrame;
/**
- * Index of the next element to be added in {@link #frame}.
- */
- private int frameIndex;
-
- /**
* The current stack map frame. The first element contains the offset of the
* instruction to which the frame corresponds, the second element is the
* number of locals and the third one is the number of stack elements. The
@@ -288,6 +295,16 @@ class MethodWriter extends MethodVisitor {
private Handler lastHandler;
/**
+ * Number of entries in the MethodParameters attribute.
+ */
+ private int methodParametersCount;
+
+ /**
+ * The MethodParameters attribute.
+ */
+ private ByteVector methodParameters;
+
+ /**
* Number of entries in the LocalVariableTable attribute.
*/
private int localVarCount;
@@ -318,6 +335,21 @@ class MethodWriter extends MethodVisitor {
private ByteVector lineNumber;
/**
+ * The start offset of the last visited instruction.
+ */
+ private int lastCodeOffset;
+
+ /**
+ * The runtime visible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ctanns;
+
+ /**
+ * The runtime invisible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ictanns;
+
+ /**
* The non standard attributes of the method's code.
*/
private Attribute cattrs;
@@ -346,7 +378,7 @@ class MethodWriter extends MethodVisitor {
/**
* Indicates what must be automatically computed.
- *
+ *
* @see #FRAMES
* @see #MAXS
* @see #NOTHING
@@ -357,7 +389,8 @@ class MethodWriter extends MethodVisitor {
* A list of labels. This list is the list of basic blocks in the method,
* i.e. a list of Label objects linked to each other by their
* {@link Label#successor} field, in the order they are visited by
- * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+ * {@link MethodVisitor#visitLabel}, and starting with the first basic
+ * block.
*/
private Label labels;
@@ -395,30 +428,32 @@ class MethodWriter extends MethodVisitor {
/**
* Constructs a new {@link MethodWriter}.
- *
- * @param cw the class writer in which the method must be added.
- * @param access the method's access flags (see {@link Opcodes}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exceptions. May be
- * <tt>null</tt>.
- * @param computeMaxs <tt>true</tt> if the maximum stack size and number
- * of local variables must be automatically computed.
- * @param computeFrames <tt>true</tt> if the stack map tables must be
- * recomputed from scratch.
- */
- MethodWriter(
- final ClassWriter cw,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions,
- final boolean computeMaxs,
- final boolean computeFrames)
- {
- super(Opcodes.ASM4);
+ *
+ * @param cw
+ * the class writer in which the method must be added.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exceptions. May be
+ * <tt>null</tt>.
+ * @param computeMaxs
+ * <tt>true</tt> if the maximum stack size and number of local
+ * variables must be automatically computed.
+ * @param computeFrames
+ * <tt>true</tt> if the stack map tables must be recomputed from
+ * scratch.
+ */
+ MethodWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions, final boolean computeMaxs,
+ final boolean computeFrames) {
+ super(Opcodes.ASM5);
if (cw.firstMethod == null) {
cw.firstMethod = this;
} else {
@@ -427,6 +462,9 @@ class MethodWriter extends MethodVisitor {
cw.lastMethod = this;
this.cw = cw;
this.access = access;
+ if ("<init>".equals(name)) {
+ this.access |= ACC_CONSTRUCTOR;
+ }
this.name = cw.newUTF8(name);
this.desc = cw.newUTF8(desc);
this.descriptor = desc;
@@ -442,9 +480,6 @@ class MethodWriter extends MethodVisitor {
}
this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
if (computeMaxs || computeFrames) {
- if (computeFrames && "<init>".equals(name)) {
- this.access |= ACC_CONSTRUCTOR;
- }
// updates maxLocals
int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
if ((access & Opcodes.ACC_STATIC) != 0) {
@@ -464,6 +499,16 @@ class MethodWriter extends MethodVisitor {
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(String name, int access) {
+ if (methodParameters == null) {
+ methodParameters = new ByteVector();
+ }
+ ++methodParametersCount;
+ methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
+ .putShort(access);
+ }
+
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
if (!ClassReader.ANNOTATIONS) {
return null;
@@ -473,10 +518,8 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -495,11 +538,31 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
@@ -545,20 +608,18 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
if (!ClassReader.FRAMES || compute == FRAMES) {
return;
}
if (type == Opcodes.F_NEW) {
+ if (previousFrame == null) {
+ visitImplicitFirstFrame();
+ }
currentLocals = nLocal;
- startFrame(code.length, nLocal, nStack);
+ int frameIndex = startFrame(code.length, nLocal, nStack);
for (int i = 0; i < nLocal; ++i) {
if (local[i] instanceof String) {
frame[frameIndex++] = Frame.OBJECT
@@ -601,48 +662,44 @@ class MethodWriter extends MethodVisitor {
}
switch (type) {
- case Opcodes.F_FULL:
- currentLocals = nLocal;
- stackMap.putByte(FULL_FRAME)
- .putShort(delta)
- .putShort(nLocal);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- stackMap.putShort(nStack);
- for (int i = 0; i < nStack; ++i) {
- writeFrameType(stack[i]);
- }
- break;
- case Opcodes.F_APPEND:
- currentLocals += nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
- .putShort(delta);
- for (int i = 0; i < nLocal; ++i) {
- writeFrameType(local[i]);
- }
- break;
- case Opcodes.F_CHOP:
- currentLocals -= nLocal;
- stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+ case Opcodes.F_FULL:
+ currentLocals = nLocal;
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ stackMap.putShort(nStack);
+ for (int i = 0; i < nStack; ++i) {
+ writeFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ currentLocals += nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ currentLocals -= nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
+ break;
+ case Opcodes.F_SAME:
+ if (delta < 64) {
+ stackMap.putByte(delta);
+ } else {
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (delta < 64) {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ } else {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
.putShort(delta);
- break;
- case Opcodes.F_SAME:
- if (delta < 64) {
- stackMap.putByte(delta);
- } else {
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- }
- break;
- case Opcodes.F_SAME1:
- if (delta < 64) {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- } else {
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- }
- writeFrameType(stack[0]);
- break;
+ }
+ writeFrameType(stack[0]);
+ break;
}
previousFrameOffset = code.length;
@@ -655,6 +712,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitInsn(final int opcode) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
code.putByte(opcode);
// update currentBlock
@@ -672,8 +730,7 @@ class MethodWriter extends MethodVisitor {
}
// if opcode == ATHROW or xRETURN, ends current block (no successor)
if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
- || opcode == Opcodes.ATHROW)
- {
+ || opcode == Opcodes.ATHROW) {
noSuccessor();
}
}
@@ -681,6 +738,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIntInsn(final int opcode, final int operand) {
+ lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -705,6 +763,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitVarInsn(final int opcode, final int var) {
+ lastCodeOffset = code.length;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
if (compute == FRAMES) {
@@ -731,8 +790,7 @@ class MethodWriter extends MethodVisitor {
// updates max locals
int n;
if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
- || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
- {
+ || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
n = var + 2;
} else {
n = var + 1;
@@ -764,6 +822,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitTypeInsn(final int opcode, final String type) {
+ lastCodeOffset = code.length;
Item i = cw.newClassItem(type);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -784,12 +843,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ lastCodeOffset = code.length;
Item i = cw.newFieldItem(owner, name, desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -800,19 +856,19 @@ class MethodWriter extends MethodVisitor {
// computes the stack size variation
char c = desc.charAt(0);
switch (opcode) {
- case Opcodes.GETSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
- break;
- case Opcodes.PUTSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
- break;
- case Opcodes.GETFIELD:
- size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
- break;
- // case Constants.PUTFIELD:
- default:
- size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
- break;
+ case Opcodes.GETSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+ break;
+ case Opcodes.PUTSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+ break;
+ case Opcodes.GETFIELD:
+ size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+ break;
+ // case Constants.PUTFIELD:
+ default:
+ size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+ break;
}
// updates current and max stack sizes
if (size > maxStackSize) {
@@ -826,13 +882,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ lastCodeOffset = code.length;
Item i = cw.newMethodItem(owner, name, desc, itf);
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
@@ -870,7 +922,7 @@ class MethodWriter extends MethodVisitor {
}
}
// adds the instruction to the bytecode of the method
- if (itf) {
+ if (opcode == Opcodes.INVOKEINTERFACE) {
if (argSize == 0) {
argSize = Type.getArgumentsAndReturnSizes(desc);
i.intVal = argSize;
@@ -882,12 +934,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitInvokeDynamicInsn(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
+ lastCodeOffset = code.length;
Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
int argSize = i.intVal;
// Label currentBlock = this.currentBlock;
@@ -927,6 +976,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitJumpInsn(final int opcode, final Label label) {
+ lastCodeOffset = code.length;
Label nextInsn = null;
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -967,8 +1017,7 @@ class MethodWriter extends MethodVisitor {
}
// adds the instruction to the bytecode of the method
if ((label.status & Label.RESOLVED) != 0
- && label.position - code.length < Short.MIN_VALUE)
- {
+ && label.position - code.length < Short.MIN_VALUE) {
/*
* case of a backward jump with an offset < -32768. In this case we
* automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
@@ -986,8 +1035,7 @@ class MethodWriter extends MethodVisitor {
if (nextInsn != null) {
nextInsn.status |= Label.TARGET;
}
- code.putByte(opcode <= 166
- ? ((opcode + 1) ^ 1) - 1
+ code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
: opcode ^ 1);
code.putShort(8); // jump offset
code.putByte(200); // GOTO_W
@@ -1074,6 +1122,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitLdcInsn(final Object cst) {
+ lastCodeOffset = code.length;
Item i = cw.newConstItem(cst);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1082,8 +1131,7 @@ class MethodWriter extends MethodVisitor {
} else {
int size;
// computes the stack size variation
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
- {
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
size = stackSize + 2;
} else {
size = stackSize + 1;
@@ -1108,6 +1156,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitIincInsn(final int var, final int increment) {
+ lastCodeOffset = code.length;
if (currentBlock != null) {
if (compute == FRAMES) {
currentBlock.frame.execute(Opcodes.IINC, var, null, null);
@@ -1122,8 +1171,7 @@ class MethodWriter extends MethodVisitor {
}
// adds the instruction to the bytecode of the method
if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /* WIDE */)
- .put12(Opcodes.IINC, var)
+ code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
.putShort(increment);
} else {
code.putByte(Opcodes.IINC).put11(var, increment);
@@ -1131,12 +1179,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.TABLESWITCH);
@@ -1151,11 +1196,9 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ lastCodeOffset = code.length;
// adds the instruction to the bytecode of the method
int source = code.length;
code.putByte(Opcodes.LOOKUPSWITCH);
@@ -1198,6 +1241,7 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ lastCodeOffset = code.length;
Item i = cw.newClassItem(desc);
// Label currentBlock = this.currentBlock;
if (currentBlock != null) {
@@ -1214,12 +1258,32 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
++handlerCount;
Handler h = new Handler();
h.start = start;
@@ -1236,14 +1300,32 @@ class MethodWriter extends MethodVisitor {
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
if (signature != null) {
if (localVarType == null) {
localVarType = new ByteVector();
@@ -1251,8 +1333,7 @@ class MethodWriter extends MethodVisitor {
++localVarTypeCount;
localVarType.putShort(start.position)
.putShort(end.position - start.position)
- .putShort(cw.newUTF8(name))
- .putShort(cw.newUTF8(signature))
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
.putShort(index);
}
if (localVar == null) {
@@ -1261,8 +1342,7 @@ class MethodWriter extends MethodVisitor {
++localVarCount;
localVar.putShort(start.position)
.putShort(end.position - start.position)
- .putShort(cw.newUTF8(name))
- .putShort(cw.newUTF8(desc))
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
.putShort(index);
if (compute != NOTHING) {
// updates max locals
@@ -1275,6 +1355,41 @@ class MethodWriter extends MethodVisitor {
}
@Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ bv.putByte(typeRef >>> 24).putShort(start.length);
+ for (int i = 0; i < start.length; ++i) {
+ bv.putShort(start[i].position)
+ .putShort(end[i].position - start[i].position)
+ .putShort(index[i]);
+ }
+ if (typePath == null) {
+ bv.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ bv.putByteArray(typePath.b, typePath.offset, length);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
public void visitLineNumber(final int line, final Label start) {
if (lineNumber == null) {
lineNumber = new ByteVector();
@@ -1286,6 +1401,14 @@ class MethodWriter extends MethodVisitor {
@Override
public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
if (ClassReader.FRAMES && compute == FRAMES) {
// completes the control flow graph with exception handler blocks
Handler handler = firstHandler;
@@ -1294,8 +1417,7 @@ class MethodWriter extends MethodVisitor {
Label h = handler.handler.getFirst();
Label e = handler.end.getFirst();
// computes the kind of the edges to 'h'
- String t = handler.desc == null
- ? "java/lang/Throwable"
+ String t = handler.desc == null ? "java/lang/Throwable"
: handler.desc;
int kind = Frame.OBJECT | cw.addType(t);
// h is an exception handler
@@ -1382,11 +1504,12 @@ class MethodWriter extends MethodVisitor {
}
code.data[end] = (byte) Opcodes.ATHROW;
// emits a frame for this unreachable block
- startFrame(start, 0, 1);
- frame[frameIndex++] = Frame.OBJECT
+ int frameIndex = startFrame(start, 0, 1);
+ frame[frameIndex] = Frame.OBJECT
| cw.addType("java/lang/Throwable");
endFrame();
- // removes the start-end range from the exception handlers
+ // removes the start-end range from the exception
+ // handlers
firstHandler = Handler.remove(firstHandler, l, k);
}
}
@@ -1534,9 +1657,11 @@ class MethodWriter extends MethodVisitor {
/**
* Adds a successor to the {@link #currentBlock currentBlock} block.
- *
- * @param info information about the control flow edge to be added.
- * @param successor the successor block to be added to the current block.
+ *
+ * @param info
+ * information about the control flow edge to be added.
+ * @param successor
+ * the successor block to be added to the current block.
*/
private void addSuccessor(final int info, final Label successor) {
// creates and initializes an Edge object...
@@ -1572,8 +1697,9 @@ class MethodWriter extends MethodVisitor {
/**
* Visits a frame that has been computed from scratch.
- *
- * @param f the frame that must be visited.
+ *
+ * @param f
+ * the frame that must be visited.
*/
private void visitFrame(final Frame f) {
int i, t;
@@ -1606,7 +1732,7 @@ class MethodWriter extends MethodVisitor {
}
}
// visits the frame and its content
- startFrame(f.owner.position, nLocal, nStack);
+ int frameIndex = startFrame(f.owner.position, nLocal, nStack);
for (i = 0; nLocal > 0; ++i, --nLocal) {
t = locals[i];
frame[frameIndex++] = t;
@@ -1625,15 +1751,78 @@ class MethodWriter extends MethodVisitor {
}
/**
+ * Visit the implicit first frame of this method.
+ */
+ private void visitImplicitFirstFrame() {
+ // There can be at most descriptor.length() + 1 locals
+ int frameIndex = startFrame(0, descriptor.length() + 1, 0);
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & ACC_CONSTRUCTOR) == 0) {
+ frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
+ } else {
+ frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+ }
+ }
+ int i = 1;
+ loop: while (true) {
+ int j = i;
+ switch (descriptor.charAt(i++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ frame[frameIndex++] = 1; // Opcodes.INTEGER;
+ break;
+ case 'F':
+ frame[frameIndex++] = 2; // Opcodes.FLOAT;
+ break;
+ case 'J':
+ frame[frameIndex++] = 4; // Opcodes.LONG;
+ break;
+ case 'D':
+ frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (descriptor.charAt(i) == '[') {
+ ++i;
+ }
+ if (descriptor.charAt(i) == 'L') {
+ ++i;
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j, ++i));
+ break;
+ case 'L':
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j + 1, i++));
+ break;
+ default:
+ break loop;
+ }
+ }
+ frame[1] = frameIndex - 3;
+ endFrame();
+ }
+
+ /**
* Starts the visit of a stack map frame.
- *
- * @param offset the offset of the instruction to which the frame
- * corresponds.
- * @param nLocal the number of local variables in the frame.
- * @param nStack the number of stack elements in the frame.
- */
- private void startFrame(final int offset, final int nLocal, final int nStack)
- {
+ *
+ * @param offset
+ * the offset of the instruction to which the frame corresponds.
+ * @param nLocal
+ * the number of local variables in the frame.
+ * @param nStack
+ * the number of stack elements in the frame.
+ * @return the index of the next element to be written in this frame.
+ */
+ private int startFrame(final int offset, final int nLocal, final int nStack) {
int n = 3 + nLocal + nStack;
if (frame == null || frame.length < n) {
frame = new int[n];
@@ -1641,7 +1830,7 @@ class MethodWriter extends MethodVisitor {
frame[0] = offset;
frame[1] = nLocal;
frame[2] = nStack;
- frameIndex = 3;
+ return 3;
}
/**
@@ -1686,24 +1875,23 @@ class MethodWriter extends MethodVisitor {
if (cstackSize == 0) {
k = clocalsSize - localsSize;
switch (k) {
- case -3:
- case -2:
- case -1:
- type = CHOP_FRAME;
- localsSize = clocalsSize;
- break;
- case 0:
- type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
- break;
- case 1:
- case 2:
- case 3:
- type = APPEND_FRAME;
- break;
+ case -3:
+ case -2:
+ case -1:
+ type = CHOP_FRAME;
+ localsSize = clocalsSize;
+ break;
+ case 0:
+ type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ type = APPEND_FRAME;
+ break;
}
} else if (clocalsSize == localsSize && cstackSize == 1) {
- type = delta < 63
- ? SAME_LOCALS_1_STACK_ITEM_FRAME
+ type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
: SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
}
if (type != FULL_FRAME) {
@@ -1718,36 +1906,34 @@ class MethodWriter extends MethodVisitor {
}
}
switch (type) {
- case SAME_FRAME:
- stackMap.putByte(delta);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
- stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- .putShort(delta);
- writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
- break;
- case SAME_FRAME_EXTENDED:
- stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
- break;
- case CHOP_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- break;
- case APPEND_FRAME:
- stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
- writeFrameTypes(3 + localsSize, 3 + clocalsSize);
- break;
- // case FULL_FRAME:
- default:
- stackMap.putByte(FULL_FRAME)
- .putShort(delta)
- .putShort(clocalsSize);
- writeFrameTypes(3, 3 + clocalsSize);
- stackMap.putShort(cstackSize);
- writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ case SAME_FRAME:
+ stackMap.putByte(delta);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
+ delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_FRAME_EXTENDED:
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ break;
+ case CHOP_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ break;
+ case APPEND_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+ break;
+ // case FULL_FRAME:
+ default:
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
}
}
@@ -1756,9 +1942,11 @@ class MethodWriter extends MethodVisitor {
* StackMapTableAttribute. This method converts types from the format used
* in {@link Label} to the format used in StackMapTable attributes. In
* particular, it converts type table indexes to constant pool indexes.
- *
- * @param start index of the first type in {@link #frame} to write.
- * @param end index of last type in {@link #frame} to write (exclusive).
+ *
+ * @param start
+ * index of the first type in {@link #frame} to write.
+ * @param end
+ * index of last type in {@link #frame} to write (exclusive).
*/
private void writeFrameTypes(final int start, final int end) {
for (int i = start; i < end; ++i) {
@@ -1767,15 +1955,15 @@ class MethodWriter extends MethodVisitor {
if (d == 0) {
int v = t & Frame.BASE_VALUE;
switch (t & Frame.BASE_KIND) {
- case Frame.OBJECT:
- stackMap.putByte(7)
- .putShort(cw.newClass(cw.typeTable[v].strVal1));
- break;
- case Frame.UNINITIALIZED:
- stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
- break;
- default:
- stackMap.putByte(v);
+ case Frame.OBJECT:
+ stackMap.putByte(7).putShort(
+ cw.newClass(cw.typeTable[v].strVal1));
+ break;
+ case Frame.UNINITIALIZED:
+ stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+ break;
+ default:
+ stackMap.putByte(v);
}
} else {
StringBuffer buf = new StringBuffer();
@@ -1789,29 +1977,29 @@ class MethodWriter extends MethodVisitor {
buf.append(';');
} else {
switch (t & 0xF) {
- case 1:
- buf.append('I');
- break;
- case 2:
- buf.append('F');
- break;
- case 3:
- buf.append('D');
- break;
- case 9:
- buf.append('Z');
- break;
- case 10:
- buf.append('B');
- break;
- case 11:
- buf.append('C');
- break;
- case 12:
- buf.append('S');
- break;
- default:
- buf.append('J');
+ case 1:
+ buf.append('I');
+ break;
+ case 2:
+ buf.append('F');
+ break;
+ case 3:
+ buf.append('D');
+ break;
+ case 9:
+ buf.append('Z');
+ break;
+ case 10:
+ buf.append('B');
+ break;
+ case 11:
+ buf.append('C');
+ break;
+ case 12:
+ buf.append('S');
+ break;
+ default:
+ buf.append('J');
}
}
stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
@@ -1835,21 +2023,13 @@ class MethodWriter extends MethodVisitor {
/**
* Returns the size of the bytecode of this method.
- *
+ *
* @return the size of the bytecode of this method.
*/
final int getSize() {
if (classReaderOffset != 0) {
return 6 + classReaderLength;
}
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- if (ClassReader.RESIZE) {
- resizeInstructions();
- } else {
- throw new RuntimeException("Method code too large!");
- }
- }
int size = 8;
if (code.length > 0) {
if (code.length > 65536) {
@@ -1874,11 +2054,16 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(zip ? "StackMapTable" : "StackMap");
size += 8 + stackMap.length;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + ictanns.getSize();
+ }
if (cattrs != null) {
- size += cattrs.getSize(cw,
- code.data,
- code.length,
- maxStack,
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
}
}
@@ -1886,11 +2071,12 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8("Exceptions");
size += 8 + 2 * exceptionCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- cw.newUTF8("Synthetic");
- size += 6;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
@@ -1901,6 +2087,10 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8(signature);
size += 8;
}
+ if (methodParameters != null) {
+ cw.newUTF8("MethodParameters");
+ size += 7 + methodParameters.length;
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
cw.newUTF8("AnnotationDefault");
size += 6 + annd.length;
@@ -1913,6 +2103,14 @@ class MethodWriter extends MethodVisitor {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
cw.newUTF8("RuntimeVisibleParameterAnnotations");
size += 7 + 2 * (panns.length - synthetics);
@@ -1935,14 +2133,16 @@ class MethodWriter extends MethodVisitor {
/**
* Puts the bytecode of this method in the given byte vector.
- *
- * @param out the byte vector into which the bytecode of this method must be
- * copied.
+ *
+ * @param out
+ * the byte vector into which the bytecode of this method must be
+ * copied.
*/
final void put(final ByteVector out) {
- int mask = Opcodes.ACC_DEPRECATED
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
| ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
- | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
if (classReaderOffset != 0) {
out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
@@ -1955,10 +2155,11 @@ class MethodWriter extends MethodVisitor {
if (exceptionCount > 0) {
++attributeCount;
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- ++attributeCount;
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
@@ -1966,6 +2167,9 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.SIGNATURES && signature != null) {
++attributeCount;
}
+ if (methodParameters != null) {
+ ++attributeCount;
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
++attributeCount;
}
@@ -1975,6 +2179,12 @@ class MethodWriter extends MethodVisitor {
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
++attributeCount;
}
@@ -1999,11 +2209,14 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
size += 8 + stackMap.length;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ size += 8 + ictanns.getSize();
+ }
if (cattrs != null) {
- size += cattrs.getSize(cw,
- code.data,
- code.length,
- maxStack,
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
maxLocals);
}
out.putShort(cw.newUTF8("Code")).putInt(size);
@@ -2013,10 +2226,8 @@ class MethodWriter extends MethodVisitor {
if (handlerCount > 0) {
Handler h = firstHandler;
while (h != null) {
- out.putShort(h.start.position)
- .putShort(h.end.position)
- .putShort(h.handler.position)
- .putShort(h.type);
+ out.putShort(h.start.position).putShort(h.end.position)
+ .putShort(h.handler.position).putShort(h.type);
h = h.next;
}
}
@@ -2033,6 +2244,12 @@ class MethodWriter extends MethodVisitor {
if (stackMap != null) {
++attributeCount;
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ ++attributeCount;
+ }
if (cattrs != null) {
attributeCount += cattrs.getCount();
}
@@ -2058,31 +2275,45 @@ class MethodWriter extends MethodVisitor {
out.putInt(stackMap.length + 2).putShort(frameCount);
out.putByteArray(stackMap.data, 0, stackMap.length);
}
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ ctanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ ictanns.put(out);
+ }
if (cattrs != null) {
cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
}
}
if (exceptionCount > 0) {
- out.putShort(cw.newUTF8("Exceptions"))
- .putInt(2 * exceptionCount + 2);
+ out.putShort(cw.newUTF8("Exceptions")).putInt(
+ 2 * exceptionCount + 2);
out.putShort(exceptionCount);
for (int i = 0; i < exceptionCount; ++i) {
out.putShort(exceptions[i]);
}
}
- if ((access & Opcodes.ACC_SYNTHETIC) != 0
- && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
- {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
}
if (ClassReader.SIGNATURES && signature != null) {
- out.putShort(cw.newUTF8("Signature"))
- .putInt(2)
+ out.putShort(cw.newUTF8("Signature")).putInt(2)
.putShort(cw.newUTF8(signature));
}
+ if (methodParameters != null) {
+ out.putShort(cw.newUTF8("MethodParameters"));
+ out.putInt(methodParameters.length + 1).putByte(
+ methodParametersCount);
+ out.putByteArray(methodParameters.data, 0, methodParameters.length);
+ }
if (ClassReader.ANNOTATIONS && annd != null) {
out.putShort(cw.newUTF8("AnnotationDefault"));
out.putInt(annd.length);
@@ -2096,6 +2327,14 @@ class MethodWriter extends MethodVisitor {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
if (ClassReader.ANNOTATIONS && panns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
AnnotationWriter.put(panns, synthetics, out);
@@ -2123,10 +2362,12 @@ class MethodWriter extends MethodVisitor {
* 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
* 32765. This, in turn, may require to increase the size of another jump
* instruction, and so on... All these operations are handled automatically
- * by this method. <p> <i>This method must be called after all the method
- * that is being built has been visited</i>. In particular, the
- * {@link Label Label} objects used to construct the method are no longer
- * valid after this method has been called.
+ * by this method.
+ * <p>
+ * <i>This method must be called after all the method that is being built
+ * has been visited</i>. In particular, the {@link Label Label} objects used
+ * to construct the method are no longer valid after this method has been
+ * called.
*/
private void resizeInstructions() {
byte[] b = code.data; // bytecode of the method
@@ -2138,17 +2379,17 @@ class MethodWriter extends MethodVisitor {
* so on. The first step of the algorithm consists in finding all the
* instructions that need to be resized, without modifying the code.
* This is done by the following "fix point" algorithm:
- *
+ *
* Parse the code to find the jump instructions whose offset will need
* more than 2 bytes to be stored (the future offset is computed from
* the current offset and from the number of bytes that will be inserted
* or removed between the source and target instructions). For each such
* instruction, adds an entry in (a copy of) the indexes and sizes
* arrays (if this has not already been done in a previous iteration!).
- *
+ *
* If at least one entry has been added during the previous step, go
* back to the beginning, otherwise stop.
- *
+ *
* In fact the real algorithm is complicated by the fact that the size
* of TABLESWITCH and LOOKUPSWITCH instructions depends on their
* position in the bytecode (because of padding). In order to ensure the
@@ -2176,158 +2417,14 @@ class MethodWriter extends MethodVisitor {
int insert = 0; // bytes to be added after this instruction
switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // converts temporary opcodes 202 to 217, 218 and
- // 219 to IFEQ ... JSR (inclusive), IFNULL and
- // IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (newOffset < Short.MIN_VALUE
- || newOffset > Short.MAX_VALUE)
- {
- if (!resize[u]) {
- if (opcode == Opcodes.GOTO
- || opcode == Opcodes.JSR)
- {
- // two additional bytes will be required to
- // replace this GOTO or JSR instruction with
- // a GOTO_W or a JSR_W
- insert = 2;
- } else {
- // five additional bytes will be required to
- // replace this IFxxx <l> instruction with
- // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
- // is the "opposite" opcode of IFxxx (i.e.,
- // IFNE for IFEQ) and where <l'> designates
- // the instruction just after the GOTO_W.
- insert = 5;
- }
- resize[u] = true;
- }
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- if (state == 1) {
- // true number of bytes to be added (or removed)
- // from this instruction = (future number of padding
- // bytes - current number of padding byte) -
- // previously over estimated variation =
- // = ((3 - newOffset%4) - (3 - u%4)) - u%4
- // = (-newOffset%4 + u%4) - u%4
- // = -(newOffset & 3)
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // over estimation of the number of bytes to be
- // added to this instruction = 3 - current number
- // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
- break;
- case ClassWriter.LOOK_INSN:
- if (state == 1) {
- // like TABL_INSN
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // like TABL_INSN
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 8 * readInt(b, u + 4) + 8;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- u += 5;
- break;
- // case ClassWriter.MANA_INSN:
- default:
- u += 4;
- break;
- }
- if (insert != 0) {
- // adds a new (u, insert) entry in the allIndexes and
- // allSizes arrays
- int[] newIndexes = new int[allIndexes.length + 1];
- int[] newSizes = new int[allSizes.length + 1];
- System.arraycopy(allIndexes,
- 0,
- newIndexes,
- 0,
- allIndexes.length);
- System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
- newIndexes[allIndexes.length] = u;
- newSizes[allSizes.length] = insert;
- allIndexes = newIndexes;
- allSizes = newSizes;
- if (insert > 0) {
- state = 3;
- }
- }
- }
- if (state < 3) {
- --state;
- }
- } while (state != 0);
-
- // 2nd step:
- // copies the bytecode of the method into a new bytevector, updates the
- // offsets, and inserts (or removes) bytes as requested.
-
- ByteVector newCode = new ByteVector(code.length);
-
- u = 0;
- while (u < code.length) {
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
case ClassWriter.NOARG_INSN:
case ClassWriter.IMPLVAR_INSN:
- newCode.putByte(opcode);
u += 1;
break;
case ClassWriter.LABEL_INSN:
if (opcode > 201) {
- // changes temporary opcodes 202 to 217 (inclusive), 218
- // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // converts temporary opcodes 202 to 217, 218 and
+ // 219 to IFEQ ... JSR (inclusive), IFNULL and
// IFNONNULL
opcode = opcode < 218 ? opcode - 49 : opcode - 20;
label = u + readUnsignedShort(b, u + 1);
@@ -2335,100 +2432,78 @@ class MethodWriter extends MethodVisitor {
label = u + readShort(b, u + 1);
}
newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (resize[u]) {
- // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
- // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
- // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
- // and where <l'> designates the instruction just after
- // the GOTO_W.
- if (opcode == Opcodes.GOTO) {
- newCode.putByte(200); // GOTO_W
- } else if (opcode == Opcodes.JSR) {
- newCode.putByte(201); // JSR_W
- } else {
- newCode.putByte(opcode <= 166
- ? ((opcode + 1) ^ 1) - 1
- : opcode ^ 1);
- newCode.putShort(8); // jump offset
- newCode.putByte(200); // GOTO_W
- // newOffset now computed from start of GOTO_W
- newOffset -= 3;
+ if (newOffset < Short.MIN_VALUE
+ || newOffset > Short.MAX_VALUE) {
+ if (!resize[u]) {
+ if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+ // two additional bytes will be required to
+ // replace this GOTO or JSR instruction with
+ // a GOTO_W or a JSR_W
+ insert = 2;
+ } else {
+ // five additional bytes will be required to
+ // replace this IFxxx <l> instruction with
+ // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+ // is the "opposite" opcode of IFxxx (i.e.,
+ // IFNE for IFEQ) and where <l'> designates
+ // the instruction just after the GOTO_W.
+ insert = 5;
+ }
+ resize[u] = true;
}
- newCode.putInt(newOffset);
- } else {
- newCode.putByte(opcode);
- newCode.putShort(newOffset);
}
u += 3;
break;
case ClassWriter.LABELW_INSN:
- label = u + readInt(b, u + 1);
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- newCode.putByte(opcode);
- newCode.putInt(newOffset);
u += 5;
break;
case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.TABLESWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- j = readInt(b, u) - j + 1;
- u += 4;
- newCode.putInt(readInt(b, u - 4));
- for (; j > 0; --j) {
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
+ if (state == 1) {
+ // true number of bytes to be added (or removed)
+ // from this instruction = (future number of padding
+ // bytes - current number of padding byte) -
+ // previously over estimated variation =
+ // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+ // = (-newOffset%4 + u%4) - u%4
+ // = -(newOffset & 3)
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // over estimation of the number of bytes to be
+ // added to this instruction = 3 - current number
+ // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+ insert = u & 3;
+ resize[u] = true;
}
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
break;
case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- newCode.putByte(Opcodes.LOOKUPSWITCH);
- newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u);
- u += 4;
- newCode.putInt(j);
- for (; j > 0; --j) {
- newCode.putInt(readInt(b, u));
- u += 4;
- label = v + readInt(b, u);
- u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
+ if (state == 1) {
+ // like TABL_INSN
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // like TABL_INSN
+ insert = u & 3;
+ resize[u] = true;
}
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 8 * readInt(b, u + 4) + 8;
break;
case ClassWriter.WIDE_INSN:
opcode = b[u + 1] & 0xFF;
if (opcode == Opcodes.IINC) {
- newCode.putByteArray(b, u, 6);
u += 6;
} else {
- newCode.putByteArray(b, u, 4);
u += 4;
}
break;
case ClassWriter.VAR_INSN:
case ClassWriter.SBYTE_INSN:
case ClassWriter.LDC_INSN:
- newCode.putByteArray(b, u, 2);
u += 2;
break;
case ClassWriter.SHORT_INSN:
@@ -2436,66 +2511,225 @@ class MethodWriter extends MethodVisitor {
case ClassWriter.FIELDORMETH_INSN:
case ClassWriter.TYPE_INSN:
case ClassWriter.IINC_INSN:
- newCode.putByteArray(b, u, 3);
u += 3;
break;
case ClassWriter.ITFMETH_INSN:
case ClassWriter.INDYMETH_INSN:
- newCode.putByteArray(b, u, 5);
u += 5;
break;
- // case MANA_INSN:
+ // case ClassWriter.MANA_INSN:
default:
- newCode.putByteArray(b, u, 4);
u += 4;
break;
+ }
+ if (insert != 0) {
+ // adds a new (u, insert) entry in the allIndexes and
+ // allSizes arrays
+ int[] newIndexes = new int[allIndexes.length + 1];
+ int[] newSizes = new int[allSizes.length + 1];
+ System.arraycopy(allIndexes, 0, newIndexes, 0,
+ allIndexes.length);
+ System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+ newIndexes[allIndexes.length] = u;
+ newSizes[allSizes.length] = insert;
+ allIndexes = newIndexes;
+ allSizes = newSizes;
+ if (insert > 0) {
+ state = 3;
+ }
+ }
}
- }
+ if (state < 3) {
+ --state;
+ }
+ } while (state != 0);
- // recomputes the stack map frames
- if (frameCount > 0) {
- if (compute == FRAMES) {
- frameCount = 0;
- stackMap = null;
- previousFrame = null;
- frame = null;
- Frame f = new Frame();
- f.owner = labels;
- Type[] args = Type.getArgumentTypes(descriptor);
- f.initInputFrame(cw, access, args, maxLocals);
- visitFrame(f);
- Label l = labels;
- while (l != null) {
- /*
- * here we need the original label position. getNewOffset
- * must therefore never have been called for this label.
- */
- u = l.position - 3;
- if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
- {
- getNewOffset(allIndexes, allSizes, l);
- // TODO update offsets in UNINITIALIZED values
- visitFrame(l.frame);
+ // 2nd step:
+ // copies the bytecode of the method into a new bytevector, updates the
+ // offsets, and inserts (or removes) bytes as requested.
+
+ ByteVector newCode = new ByteVector(code.length);
+
+ u = 0;
+ while (u < code.length) {
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ newCode.putByte(opcode);
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (resize[u]) {
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where <l'> designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO) {
+ newCode.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ newCode.putByte(201); // JSR_W
+ } else {
+ newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ newCode.putShort(8); // jump offset
+ newCode.putByte(200); // GOTO_W
+ // newOffset now computed from start of GOTO_W
+ newOffset -= 3;
}
- l = l.successor;
+ newCode.putInt(newOffset);
+ } else {
+ newCode.putByte(opcode);
+ newCode.putShort(newOffset);
}
- } else {
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ label = u + readInt(b, u + 1);
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ newCode.putByte(opcode);
+ newCode.putInt(newOffset);
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.TABLESWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ j = readInt(b, u) - j + 1;
+ u += 4;
+ newCode.putInt(readInt(b, u - 4));
+ for (; j > 0; --j) {
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.LOOKUPSWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ for (; j > 0; --j) {
+ newCode.putInt(readInt(b, u));
+ u += 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ newCode.putByteArray(b, u, 6);
+ u += 6;
+ } else {
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ newCode.putByteArray(b, u, 2);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ newCode.putByteArray(b, u, 3);
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ newCode.putByteArray(b, u, 5);
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ break;
+ }
+ }
+
+ // updates the stack map frame labels
+ if (compute == FRAMES) {
+ Label l = labels;
+ while (l != null) {
/*
- * Resizing an existing stack map frame table is really hard.
- * Not only the table must be parsed to update the offets, but
- * new frames may be needed for jump instructions that were
- * inserted by this method. And updating the offsets or
- * inserting frames can change the format of the following
- * frames, in case of packed frames. In practice the whole table
- * must be recomputed. For this the frames are marked as
- * potentially invalid. This will cause the whole class to be
- * reread and rewritten with the COMPUTE_FRAMES option (see the
- * ClassWriter.toByteArray method). This is not very efficient
- * but is much easier and requires much less code than any other
- * method I can think of.
+ * Detects the labels that are just after an IF instruction that
+ * has been resized with the IFNOT GOTO_W pattern. These labels
+ * are now the target of a jump instruction (the IFNOT
+ * instruction). Note that we need the original label position
+ * here. getNewOffset must therefore never have been called for
+ * this label.
*/
- cw.invalidFrames = true;
+ u = l.position - 3;
+ if (u >= 0 && resize[u]) {
+ l.status |= Label.TARGET;
+ }
+ getNewOffset(allIndexes, allSizes, l);
+ l = l.successor;
+ }
+ // Update the offsets in the uninitialized types
+ for (i = 0; i < cw.typeTable.length; ++i) {
+ Item item = cw.typeTable[i];
+ if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+ item.intVal = getNewOffset(allIndexes, allSizes, 0,
+ item.intVal);
+ }
}
+ // The stack map frames are not serialized yet, so we don't need
+ // to update them. They will be serialized in visitMaxs.
+ } else if (frameCount > 0) {
+ /*
+ * Resizing an existing stack map frame table is really hard. Not
+ * only the table must be parsed to update the offets, but new
+ * frames may be needed for jump instructions that were inserted by
+ * this method. And updating the offsets or inserting frames can
+ * change the format of the following frames, in case of packed
+ * frames. In practice the whole table must be recomputed. For this
+ * the frames are marked as potentially invalid. This will cause the
+ * whole class to be reread and rewritten with the COMPUTE_FRAMES
+ * option (see the ClassWriter.toByteArray method). This is not very
+ * efficient but is much easier and requires much less code than any
+ * other method I can think of.
+ */
+ cw.invalidFrames = true;
}
// updates the exception handler block labels
Handler h = firstHandler;
@@ -2528,10 +2762,11 @@ class MethodWriter extends MethodVisitor {
b = lineNumber.data;
u = 0;
while (u < lineNumber.length) {
- writeShort(b, u, getNewOffset(allIndexes,
- allSizes,
- 0,
- readUnsignedShort(b, u)));
+ writeShort(
+ b,
+ u,
+ getNewOffset(allIndexes, allSizes, 0,
+ readUnsignedShort(b, u)));
u += 4;
}
}
@@ -2553,9 +2788,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads an unsigned short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static int readUnsignedShort(final byte[] b, final int index) {
@@ -2564,9 +2801,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads a signed short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static short readShort(final byte[] b, final int index) {
@@ -2575,9 +2814,11 @@ class MethodWriter extends MethodVisitor {
/**
* Reads a signed int value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
* @return the read value.
*/
static int readInt(final byte[] b, final int index) {
@@ -2587,10 +2828,13 @@ class MethodWriter extends MethodVisitor {
/**
* Writes a short value in the given byte array.
- *
- * @param b a byte array.
- * @param index where the first byte of the short value must be written.
- * @param s the value to be written in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * where the first byte of the short value must be written.
+ * @param s
+ * the value to be written in the given byte array.
*/
static void writeShort(final byte[] b, final int index, final int s) {
b[index] = (byte) (s >>> 8);
@@ -2598,32 +2842,34 @@ class MethodWriter extends MethodVisitor {
}
/**
- * Computes the future value of a bytecode offset. <p> Note: it is possible
- * to have several entries for the same instruction in the <tt>indexes</tt>
- * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
- * are equivalent to a single entry (index=a,size=b+b').
- *
<TRUNCATED>
[10/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
index a248cdf..d6c9c90 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
@@ -29,14 +29,19 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A node that represents a field.
- *
+ *
* @author Eric Bruneton
*/
public class FieldNode extends FieldVisitor {
@@ -63,8 +68,8 @@ public class FieldNode extends FieldVisitor {
public String signature;
/**
- * The field's initial value. This field, which may be <tt>null</tt> if
- * the field does not have an initial value, must be an {@link Integer}, a
+ * The field's initial value. This field, which may be <tt>null</tt> if the
+ * field does not have an initial value, must be an {@link Integer}, a
* {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public Object value;
@@ -72,8 +77,8 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime visible annotations of this field. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -81,17 +86,35 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime invisible annotations of this field. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this field. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this field. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this field. This list is a list of
- * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
@@ -99,56 +122,60 @@ public class FieldNode extends FieldVisitor {
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #FieldNode(int, int, String, String, String, Object)} version.
- *
- * @param access the field's access flags (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
- * if the field is synthetic and/or deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
- * Type}).
- * @param signature the field's signature.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must be
- * an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ *
+ * @param access
+ * the field's access flags (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+ * indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+ * Type}).
+ * @param signature
+ * the field's signature.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public FieldNode(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- this(Opcodes.ASM4, access, name, desc, signature, value);
+ public FieldNode(final int access, final String name, final String desc,
+ final String signature, final Object value) {
+ this(Opcodes.ASM5, access, name, desc, signature, value);
+ if (getClass() != FieldNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #FieldNode(int, int, String, String, String, Object)} version.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param access the field's access flags (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
- * if the field is synthetic and/or deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
- * Type}).
- * @param signature the field's signature.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must be
- * an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ * constructor</i>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * the field's access flags (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+ * indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+ * Type}).
+ * @param signature
+ * the field's signature.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
*/
- public FieldNode(
- final int api,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public FieldNode(final int api, final int access, final String name,
+ final String desc, final String signature, final Object value) {
super(api);
this.access = access;
this.name = name;
@@ -162,10 +189,8 @@ public class FieldNode extends FieldVisitor {
// ------------------------------------------------------------------------
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -182,6 +207,24 @@ public class FieldNode extends FieldVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
attrs = new ArrayList<Attribute>(1);
@@ -202,17 +245,29 @@ public class FieldNode extends FieldVisitor {
* This methods checks that this node, and all its nodes recursively, do not
* contain elements that were introduced in more recent versions of the ASM
* API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
}
/**
* Makes the given class visitor visit this field.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
@@ -230,6 +285,19 @@ public class FieldNode extends FieldVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(fv.visitAnnotation(an.desc, false));
}
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
fv.visitAttribute(attrs.get(i));
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
index c2564e3..8600566 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a stack map frame. These nodes are pseudo instruction
* nodes in order to be inserted in an instruction list. In fact these nodes
@@ -45,18 +45,19 @@ import java.util.Map;
* the target of a jump instruction, or that starts an exception handler block.
* The stack map frame types must describe the values of the local variables and
* of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
- * <br> (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#V1_6 V1_6}.
- *
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or equal
+ * to {@link Opcodes#V1_6 V1_6}.
+ *
* @author Eric Bruneton
*/
public class FrameNode extends AbstractInsnNode {
/**
- * The type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for expanded
- * frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
+ * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
*/
public int type;
@@ -82,49 +83,49 @@ public class FrameNode extends AbstractInsnNode {
/**
* Constructs a new {@link FrameNode}.
- *
- * @param type the type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for
- * expanded frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
- * @param nLocal number of local variables of this stack map frame.
- * @param local the types of the local variables of this stack map frame.
- * Elements of this list can be Integer, String or LabelNode objects
- * (for primitive, reference and uninitialized types respectively -
- * see {@link MethodVisitor}).
- * @param nStack number of operand stack elements of this stack map frame.
- * @param stack the types of the operand stack elements of this stack map
- * frame. Elements of this list can be Integer, String or LabelNode
- * objects (for primitive, reference and uninitialized types
- * respectively - see {@link MethodVisitor}).
+ *
+ * @param type
+ * the type of this frame. Must be {@link Opcodes#F_NEW} for
+ * expanded frames, or {@link Opcodes#F_FULL},
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+ * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_SAME1} for compressed frames.
+ * @param nLocal
+ * number of local variables of this stack map frame.
+ * @param local
+ * the types of the local variables of this stack map frame.
+ * Elements of this list can be Integer, String or LabelNode
+ * objects (for primitive, reference and uninitialized types
+ * respectively - see {@link MethodVisitor}).
+ * @param nStack
+ * number of operand stack elements of this stack map frame.
+ * @param stack
+ * the types of the operand stack elements of this stack map
+ * frame. Elements of this list can be Integer, String or
+ * LabelNode objects (for primitive, reference and uninitialized
+ * types respectively - see {@link MethodVisitor}).
*/
- public FrameNode(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public FrameNode(final int type, final int nLocal, final Object[] local,
+ final int nStack, final Object[] stack) {
super(-1);
this.type = type;
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- this.local = asList(nLocal, local);
- this.stack = asList(nStack, stack);
- break;
- case Opcodes.F_APPEND:
- this.local = asList(nLocal, local);
- break;
- case Opcodes.F_CHOP:
- this.local = Arrays.asList(new Object[nLocal]);
- break;
- case Opcodes.F_SAME:
- break;
- case Opcodes.F_SAME1:
- this.stack = asList(1, stack);
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ this.local = asList(nLocal, local);
+ this.stack = asList(nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ this.local = asList(nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ this.local = Arrays.asList(new Object[nLocal]);
+ break;
+ case Opcodes.F_SAME:
+ break;
+ case Opcodes.F_SAME1:
+ this.stack = asList(1, stack);
+ break;
}
}
@@ -135,32 +136,30 @@ public class FrameNode extends AbstractInsnNode {
/**
* Makes the given visitor visit this stack map frame.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
@Override
public void accept(final MethodVisitor mv) {
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- mv.visitFrame(type,
- local.size(),
- asArray(local),
- stack.size(),
- asArray(stack));
- break;
- case Opcodes.F_APPEND:
- mv.visitFrame(type, local.size(), asArray(local), 0, null);
- break;
- case Opcodes.F_CHOP:
- mv.visitFrame(type, local.size(), null, 0, null);
- break;
- case Opcodes.F_SAME:
- mv.visitFrame(type, 0, null, 0, null);
- break;
- case Opcodes.F_SAME1:
- mv.visitFrame(type, 0, null, 1, asArray(stack));
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mv.visitFrame(type, local.size(), asArray(local), stack.size(),
+ asArray(stack));
+ break;
+ case Opcodes.F_APPEND:
+ mv.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_CHOP:
+ mv.visitFrame(type, local.size(), null, 0, null);
+ break;
+ case Opcodes.F_SAME:
+ mv.visitFrame(type, 0, null, 0, null);
+ break;
+ case Opcodes.F_SAME1:
+ mv.visitFrame(type, 0, null, 1, asArray(stack));
+ break;
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
index c1b13dd..729dd3e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an IINC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class IincInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class IincInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link IincInsnNode}.
- *
- * @param var index of the local variable to be incremented.
- * @param incr increment amount to increment the local variable by.
+ *
+ * @param var
+ * index of the local variable to be incremented.
+ * @param incr
+ * increment amount to increment the local variable by.
*/
public IincInsnNode(final int var, final int incr) {
super(Opcodes.IINC);
@@ -71,10 +73,11 @@ public class IincInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIincInsn(var, incr);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IincInsnNode(var, incr);
+ return new IincInsnNode(var, incr).cloneAnnotations(this);
}
}
\ 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/InnerClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
index bfc16b0..877430f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
/**
* A node that represents an inner class.
- *
+ *
* @author Eric Bruneton
*/
public class InnerClassNode {
@@ -46,8 +46,8 @@ public class InnerClassNode {
/**
* The internal name of the class to which the inner class belongs (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May
- * be <tt>null</tt>.
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
public String outerName;
@@ -65,25 +65,24 @@ public class InnerClassNode {
/**
* Constructs a new {@link InnerClassNode}.
- *
- * @param name the internal name of an inner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param outerName the internal name of the class to which the inner class
- * belongs (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * May be <tt>null</tt>.
- * @param innerName the (simple) name of the inner class inside its
- * enclosing class. May be <tt>null</tt> for anonymous inner
- * classes.
- * @param access the access flags of the inner class as originally declared
- * in the enclosing class.
+ *
+ * @param name
+ * the internal name of an inner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param outerName
+ * the internal name of the class to which the inner class
+ * belongs (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}). May be <tt>null</tt>.
+ * @param innerName
+ * the (simple) name of the inner class inside its enclosing
+ * class. May be <tt>null</tt> for anonymous inner classes.
+ * @param access
+ * the access flags of the inner class as originally declared in
+ * the enclosing class.
*/
- public InnerClassNode(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public InnerClassNode(final String name, final String outerName,
+ final String innerName, final int access) {
this.name = name;
this.outerName = outerName;
this.innerName = innerName;
@@ -92,8 +91,9 @@ public class InnerClassNode {
/**
* Makes the given class visitor visit this inner class.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
cv.visitInnerClass(name, outerName, innerName, access);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
index c4fa98a..8eaaf68 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
@@ -29,11 +29,11 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.ListIterator;
import java.util.NoSuchElementException;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This
* implementation is not thread safe</i>.
@@ -63,7 +63,7 @@ public class InsnList {
/**
* Returns the number of instructions in this list.
- *
+ *
* @return the number of instructions in this list.
*/
public int size() {
@@ -72,9 +72,9 @@ public class InsnList {
/**
* Returns the first instruction in this list.
- *
- * @return the first instruction in this list, or <tt>null</tt> if the
- * list is empty.
+ *
+ * @return the first instruction in this list, or <tt>null</tt> if the list
+ * is empty.
*/
public AbstractInsnNode getFirst() {
return first;
@@ -82,7 +82,7 @@ public class InsnList {
/**
* Returns the last instruction in this list.
- *
+ *
* @return the last instruction in this list, or <tt>null</tt> if the list
* is empty.
*/
@@ -95,10 +95,12 @@ public class InsnList {
* of the instructions in this list to avoid scanning the whole list each
* time it is called. Once the cache is built, this method run in constant
* time. This cache is invalidated by all the methods that modify the list.
- *
- * @param index the index of the instruction that must be returned.
+ *
+ * @param index
+ * the index of the instruction that must be returned.
* @return the instruction whose index is given.
- * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+ * @throws IndexOutOfBoundsException
+ * if (index < 0 || index >= size()).
*/
public AbstractInsnNode get(final int index) {
if (index < 0 || index >= size) {
@@ -111,11 +113,12 @@ public class InsnList {
}
/**
- * Returns <tt>true</tt> if the given instruction belongs to this list.
- * This method always scans the instructions of this list until it finds the
+ * Returns <tt>true</tt> if the given instruction belongs to this list. This
+ * method always scans the instructions of this list until it finds the
* given instruction or reaches the end of the list.
- *
- * @param insn an instruction.
+ *
+ * @param insn
+ * an instruction.
* @return <tt>true</tt> if the given instruction belongs to this list.
*/
public boolean contains(final AbstractInsnNode insn) {
@@ -132,8 +135,9 @@ public class InsnList {
* list each time it is called. Once the cache is built, this method run in
* constant time. The cache is invalidated by all the methods that modify
* the list.
- *
- * @param insn an instruction <i>of this list</i>.
+ *
+ * @param insn
+ * an instruction <i>of this list</i>.
* @return the index of the given instruction in this list. <i>The result of
* this method is undefined if the given instruction does not belong
* to this list</i>. Use {@link #contains contains} to test if an
@@ -148,8 +152,9 @@ public class InsnList {
/**
* Makes the given visitor visit all of the instructions in this list.
- *
- * @param mv the method visitor that must visit the instructions.
+ *
+ * @param mv
+ * the method visitor that must visit the instructions.
*/
public void accept(final MethodVisitor mv) {
AbstractInsnNode insn = first;
@@ -161,7 +166,7 @@ public class InsnList {
/**
* Returns an iterator over the instructions in this list.
- *
+ *
* @return an iterator over the instructions in this list.
*/
public ListIterator<AbstractInsnNode> iterator() {
@@ -170,7 +175,7 @@ public class InsnList {
/**
* Returns an iterator over the instructions in this list.
- *
+ *
* @return an iterator over the instructions in this list.
*/
@SuppressWarnings("unchecked")
@@ -180,7 +185,7 @@ public class InsnList {
/**
* Returns an array containing all of the instructions in this list.
- *
+ *
* @return an array containing all of the instructions in this list.
*/
public AbstractInsnNode[] toArray() {
@@ -197,10 +202,12 @@ public class InsnList {
/**
* Replaces an instruction of this list with another instruction.
- *
- * @param location an instruction <i>of this list</i>.
- * @param insn another instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i>.
+ * @param insn
+ * another instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
AbstractInsnNode next = location.next;
@@ -231,9 +238,10 @@ public class InsnList {
/**
* Adds the given instruction to the end of this list.
- *
- * @param insn an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param insn
+ * an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void add(final AbstractInsnNode insn) {
++size;
@@ -251,9 +259,10 @@ public class InsnList {
/**
* Adds the given instructions to the end of this list.
- *
- * @param insns an instruction list, which is cleared during the process.
- * This list must be different from 'this'.
+ *
+ * @param insns
+ * an instruction list, which is cleared during the process. This
+ * list must be different from 'this'.
*/
public void add(final InsnList insns) {
if (insns.size == 0) {
@@ -275,9 +284,10 @@ public class InsnList {
/**
* Inserts the given instruction at the begining of this list.
- *
- * @param insn an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param insn
+ * an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void insert(final AbstractInsnNode insn) {
++size;
@@ -295,9 +305,10 @@ public class InsnList {
/**
* Inserts the given instructions at the begining of this list.
- *
- * @param insns an instruction list, which is cleared during the process.
- * This list must be different from 'this'.
+ *
+ * @param insns
+ * an instruction list, which is cleared during the process. This
+ * list must be different from 'this'.
*/
public void insert(final InsnList insns) {
if (insns.size == 0) {
@@ -319,13 +330,16 @@ public class InsnList {
/**
* Inserts the given instruction after the specified instruction.
- *
- * @param location an instruction <i>of this list</i> after which insn must be
- * inserted.
- * @param insn the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i> after which insn must be
+ * inserted.
+ * @param insn
+ * the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
*/
- public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ public void insert(final AbstractInsnNode location,
+ final AbstractInsnNode insn) {
++size;
AbstractInsnNode next = location.next;
if (next == null) {
@@ -342,11 +356,13 @@ public class InsnList {
/**
* Inserts the given instructions after the specified instruction.
- *
- * @param location an instruction <i>of this list</i> after which the
- * instructions must be inserted.
- * @param insns the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
+ *
+ * @param location
+ * an instruction <i>of this list</i> after which the
+ * instructions must be inserted.
+ * @param insns
+ * the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
*/
public void insert(final AbstractInsnNode location, final InsnList insns) {
if (insns.size == 0) {
@@ -370,13 +386,16 @@ public class InsnList {
/**
* Inserts the given instruction before the specified instruction.
- *
- * @param location an instruction <i>of this list</i> before which insn must be
- * inserted.
- * @param insn the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i> before which insn must be
+ * inserted.
+ * @param insn
+ * the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
*/
- public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ public void insertBefore(final AbstractInsnNode location,
+ final AbstractInsnNode insn) {
++size;
AbstractInsnNode prev = location.prev;
if (prev == null) {
@@ -393,38 +412,40 @@ public class InsnList {
/**
* Inserts the given instructions before the specified instruction.
- *
- * @param location an instruction <i>of this list</i> before which the instructions
- * must be inserted.
- * @param insns the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
+ *
+ * @param location
+ * an instruction <i>of this list</i> before which the
+ * instructions must be inserted.
+ * @param insns
+ * the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
*/
- public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+ public void insertBefore(final AbstractInsnNode location,
+ final InsnList insns) {
if (insns.size == 0) {
return;
}
size += insns.size;
AbstractInsnNode ifirst = insns.first;
AbstractInsnNode ilast = insns.last;
- AbstractInsnNode prev = location .prev;
+ AbstractInsnNode prev = location.prev;
if (prev == null) {
first = ifirst;
} else {
prev.next = ifirst;
}
- location .prev = ilast;
- ilast.next = location ;
+ location.prev = ilast;
+ ilast.next = location;
ifirst.prev = prev;
cache = null;
insns.removeAll(false);
}
-
-
/**
* Removes the given instruction from this list.
- *
- * @param insn the instruction <i>of this list</i> that must be removed.
+ *
+ * @param insn
+ * the instruction <i>of this list</i> that must be removed.
*/
public void remove(final AbstractInsnNode insn) {
--size;
@@ -455,9 +476,10 @@ public class InsnList {
/**
* Removes all of the instructions of this list.
- *
- * @param mark if the instructions must be marked as no longer belonging to
- * any {@link InsnList}.
+ *
+ * @param mark
+ * if the instructions must be marked as no longer belonging to
+ * any {@link InsnList}.
*/
void removeAll(final boolean mark) {
if (mark) {
@@ -499,14 +521,16 @@ public class InsnList {
}
// this class is not generified because it will create bridges
- private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ {
+ private final class InsnListIterator implements ListIterator {
AbstractInsnNode next;
AbstractInsnNode prev;
+ AbstractInsnNode remove;
+
InsnListIterator(int index) {
- if(index==size()) {
+ if (index == size()) {
next = null;
prev = getLast();
} else {
@@ -526,12 +550,22 @@ public class InsnList {
AbstractInsnNode result = next;
prev = result;
next = result.next;
+ remove = result;
return result;
}
public void remove() {
- InsnList.this.remove(prev);
- prev = prev.prev;
+ if (remove != null) {
+ if (remove == next) {
+ next = next.next;
+ } else {
+ prev = prev.prev;
+ }
+ InsnList.this.remove(remove);
+ remove = null;
+ } else {
+ throw new IllegalStateException();
+ }
}
public boolean hasPrevious() {
@@ -542,6 +576,7 @@ public class InsnList {
AbstractInsnNode result = prev;
next = result;
prev = result.prev;
+ remove = result;
return result;
}
@@ -568,6 +603,7 @@ public class InsnList {
public void add(Object o) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
prev = (AbstractInsnNode) o;
+ remove = null;
}
public void set(Object o) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
index 6abed41..7eb2359 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
@@ -29,34 +29,36 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a zero operand instruction.
- *
+ *
* @author Eric Bruneton
*/
public class InsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link InsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed. This
- * opcode must be 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, IALOAD, LALOAD,
- * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, 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, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
- * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
- * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
- * MONITORENTER, or MONITOREXIT.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed. This opcode
+ * must be 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, IALOAD,
+ * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+ * 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, I2L, I2F, I2D,
+ * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+ * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+ * or MONITOREXIT.
*/
public InsnNode(final int opcode) {
super(opcode);
@@ -69,16 +71,18 @@ public class InsnNode extends AbstractInsnNode {
/**
* Makes the given visitor visit this instruction.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
@Override
public void accept(final MethodVisitor mv) {
mv.visitInsn(opcode);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InsnNode(opcode);
+ return new InsnNode(opcode).cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
index 03c0d54..5b0c351 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
@@ -29,13 +29,13 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents an instruction with a single int operand.
- *
+ *
* @author Eric Bruneton
*/
public class IntInsnNode extends AbstractInsnNode {
@@ -47,10 +47,12 @@ public class IntInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link IntInsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed. This
- * opcode must be BIPUSH, SIPUSH or NEWARRAY.
- * @param operand the operand of the instruction to be constructed.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed. This opcode
+ * must be BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand
+ * the operand of the instruction to be constructed.
*/
public IntInsnNode(final int opcode, final int operand) {
super(opcode);
@@ -59,9 +61,10 @@ public class IntInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be BIPUSH,
- * SIPUSH or NEWARRAY.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be BIPUSH, SIPUSH
+ * or NEWARRAY.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -75,10 +78,11 @@ public class IntInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIntInsn(opcode, operand);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IntInsnNode(opcode, operand);
+ return new IntInsnNode(opcode, operand).cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
index d67b72f..2578768 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
@@ -29,15 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an invokedynamic instruction.
- *
+ *
* @author Remi Forax
*/
public class InvokeDynamicInsnNode extends AbstractInsnNode {
@@ -64,18 +64,18 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link InvokeDynamicInsnNode}.
- *
- * @param name invokedynamic name.
- * @param desc invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param bsm the bootstrap method.
- * @param bsmArgs the boostrap constant arguments.
+ *
+ * @param name
+ * invokedynamic name.
+ * @param desc
+ * invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the boostrap constant arguments.
*/
- public InvokeDynamicInsnNode(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ public InvokeDynamicInsnNode(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
super(Opcodes.INVOKEDYNAMIC);
this.name = name;
this.desc = desc;
@@ -91,10 +91,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
+ return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
+ .cloneAnnotations(this);
}
}
\ 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/JumpInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
index d0011a2..386c900 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a jump instruction. A jump instruction is an
* instruction that may jump to another instruction.
- *
+ *
* @author Eric Bruneton
*/
public class JumpInsnNode extends AbstractInsnNode {
@@ -49,14 +49,16 @@ public class JumpInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link JumpInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
- * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label the operand of the instruction to be constructed. This
- * operand is a label that designates the instruction to which the
- * jump instruction may jump.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label
+ * the operand of the instruction to be constructed. This operand
+ * is a label that designates the instruction to which the jump
+ * instruction may jump.
*/
public JumpInsnNode(final int opcode, final LabelNode label) {
super(opcode);
@@ -65,11 +67,12 @@ public class JumpInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
- * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
- * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
- * IFNULL or IFNONNULL.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be IFEQ, IFNE,
+ * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+ * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
+ * JSR, IFNULL or IFNONNULL.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -83,10 +86,12 @@ public class JumpInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitJumpInsn(opcode, label.getLabel());
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new JumpInsnNode(opcode, clone(label, labels));
+ return new JumpInsnNode(opcode, clone(label, labels))
+ .cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
index a21f0d0..39c08ef 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
@@ -29,11 +29,11 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import java.util.Map;
-
/**
* An {@link AbstractInsnNode} that encapsulates a {@link Label}.
*/
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
index 82748cb..e048e74 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an LDC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LdcInsnNode extends AbstractInsnNode {
@@ -50,10 +50,11 @@ public class LdcInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link LdcInsnNode}.
- *
- * @param cst the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object cst) {
super(Opcodes.LDC);
@@ -68,10 +69,11 @@ public class LdcInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitLdcInsn(cst);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new LdcInsnNode(cst);
+ return new LdcInsnNode(cst).cloneAnnotations(this);
}
}
\ 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/LineNumberNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
index fe4d39b..c475ee8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a line number declaration. These nodes are pseudo
* instruction nodes in order to be inserted in an instruction list.
- *
+ *
* @author Eric Bruneton
*/
public class LineNumberNode extends AbstractInsnNode {
@@ -54,10 +54,12 @@ public class LineNumberNode extends AbstractInsnNode {
/**
* Constructs a new {@link LineNumberNode}.
- *
- * @param line a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start the first instruction corresponding to this line number.
+ *
+ * @param line
+ * a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start
+ * the first instruction corresponding to this line number.
*/
public LineNumberNode(final int line, final LabelNode start) {
super(-1);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
new file mode 100644
index 0000000..27f6e09
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
@@ -0,0 +1,157 @@
+/***
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotation on a local or resource variable.
+ *
+ * @author Eric Bruneton
+ */
+public class LocalVariableAnnotationNode extends TypeAnnotationNode {
+
+ /**
+ * The fist instructions corresponding to the continuous ranges that make
+ * the scope of this local variable (inclusive). Must not be <tt>null</tt>.
+ */
+ public List<LabelNode> start;
+
+ /**
+ * The last instructions corresponding to the continuous ranges that make
+ * the scope of this local variable (exclusive). This list must have the
+ * same size as the 'start' list. Must not be <tt>null</tt>.
+ */
+ public List<LabelNode> end;
+
+ /**
+ * The local variable's index in each range. This list must have the same
+ * size as the 'start' list. Must not be <tt>null</tt>.
+ */
+ public List<Integer> index;
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the
+ * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)}
+ * version.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
+ LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+ this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc);
+ }
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
+ LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+ super(api, typeRef, typePath, desc);
+ this.start = new ArrayList<LabelNode>(start.length);
+ this.start.addAll(Arrays.asList(start));
+ this.end = new ArrayList<LabelNode>(end.length);
+ this.end.addAll(Arrays.asList(end));
+ this.index = new ArrayList<Integer>(index.length);
+ for (int i : index) {
+ this.index.add(i);
+ }
+ }
+
+ /**
+ * Makes the given visitor visit this type annotation.
+ *
+ * @param mv
+ * the visitor that must visit this annotation.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ */
+ public void accept(final MethodVisitor mv, boolean visible) {
+ Label[] start = new Label[this.start.size()];
+ Label[] end = new Label[this.end.size()];
+ int[] index = new int[this.index.size()];
+ for (int i = 0; i < start.length; ++i) {
+ start[i] = this.start.get(i).getLabel();
+ end[i] = this.end.get(i).getLabel();
+ index[i] = this.index.get(i);
+ }
+ accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, true));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
index 8494414..775a6e8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a local variable declaration.
- *
+ *
* @author Eric Bruneton
*/
public class LocalVariableNode {
@@ -72,25 +72,25 @@ public class LocalVariableNode {
/**
* Constructs a new {@link LocalVariableNode}.
- *
- * @param name the name of a local variable.
- * @param desc the type descriptor of this local variable.
- * @param signature the signature of this local variable. May be
- * <tt>null</tt>.
- * @param start the first instruction corresponding to the scope of this
- * local variable (inclusive).
- * @param end the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index the local variable's index.
+ *
+ * @param name
+ * the name of a local variable.
+ * @param desc
+ * the type descriptor of this local variable.
+ * @param signature
+ * the signature of this local variable. May be <tt>null</tt>.
+ * @param start
+ * the first instruction corresponding to the scope of this local
+ * variable (inclusive).
+ * @param end
+ * the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index
+ * the local variable's index.
*/
- public LocalVariableNode(
- final String name,
- final String desc,
- final String signature,
- final LabelNode start,
- final LabelNode end,
- final int index)
- {
+ public LocalVariableNode(final String name, final String desc,
+ final String signature, final LabelNode start, final LabelNode end,
+ final int index) {
this.name = name;
this.desc = desc;
this.signature = signature;
@@ -101,15 +101,12 @@ public class LocalVariableNode {
/**
* Makes the given visitor visit this local variable declaration.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- mv.visitLocalVariable(name,
- desc,
- signature,
- start.getLabel(),
- end.getLabel(),
- index);
+ mv.visitLocalVariable(name, desc, signature, start.getLabel(),
+ end.getLabel(), index);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
index 5beca30..af635d7 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
@@ -29,18 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a LOOKUPSWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LookupSwitchInsnNode extends AbstractInsnNode {
@@ -63,21 +63,22 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link LookupSwitchInsnNode}.
- *
- * @param dflt beginning of the default handler block.
- * @param keys the values of the keys.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ *
+ * @param dflt
+ * beginning of the default handler block.
+ * @param keys
+ * the values of the keys.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>keys[i]</tt> key.
*/
- public LookupSwitchInsnNode(
- final LabelNode dflt,
- final int[] keys,
- final LabelNode[] labels)
- {
+ public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
+ final LabelNode[] labels) {
super(Opcodes.LOOKUPSWITCH);
this.dflt = dflt;
this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
- this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length);
+ this.labels = new ArrayList<LabelNode>(labels == null ? 0
+ : labels.length);
if (keys != null) {
for (int i = 0; i < keys.length; ++i) {
this.keys.add(new Integer(keys[i]));
@@ -104,6 +105,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+ acceptAnnotations(mv);
}
@Override
@@ -111,6 +113,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
labels), null, clone(this.labels, labels));
clone.keys.addAll(keys);
- return clone;
+ return clone.cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
index f87234c..5d0c730 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
@@ -29,14 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a method instruction. A method instruction is an
* instruction that invokes a method.
- *
+ *
* @author Eric Bruneton
*/
public class MethodInsnNode extends AbstractInsnNode {
@@ -58,33 +59,65 @@ public class MethodInsnNode extends AbstractInsnNode {
public String desc;
/**
+ * If the method's owner class if an interface.
+ */
+ public boolean itf;
+
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ @Deprecated
+ public MethodInsnNode(final int opcode, final String owner,
+ final String name, final String desc) {
+ this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ /**
* Constructs a new {@link MethodInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner the internal name of the method's owner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param itf
+ * if the method's owner class is an interface.
*/
- public MethodInsnNode(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public MethodInsnNode(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
super(opcode);
this.owner = owner;
this.name = name;
this.desc = desc;
+ this.itf = itf;
}
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be
- * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be INVOKEVIRTUAL,
+ * INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -97,11 +130,11 @@ public class MethodInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
- mv.visitMethodInsn(opcode, owner, name, desc);
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MethodInsnNode(opcode, owner, name, desc);
+ return new MethodInsnNode(opcode, owner, name, desc, itf);
}
}
\ No newline at end of file
[20/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
index fce84e9..5aa3aff 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* Information about the input and output stack map frames of a basic block.
- *
+ *
* @author Eric Bruneton
*/
final class Frame {
@@ -46,14 +46,14 @@ final class Frame {
* of the first basic block (which is computed from the method descriptor),
* and by using the previously computed output frames to compute the input
* state of the other blocks.
- *
+ *
* All output and input frames are stored as arrays of integers. Reference
* and array types are represented by an index into a type table (which is
* not the same as the constant pool of the class, in order to avoid adding
* unnecessary constants in the pool - not all computed frames will end up
* being stored in the stack map table). This allows very fast type
* comparisons.
- *
+ *
* Output stack map frames are computed relatively to the input frame of the
* basic block, which is not yet known when output frames are computed. It
* is therefore necessary to be able to represent abstract types such as
@@ -61,7 +61,7 @@ final class Frame {
* position x from the top of the input frame stack" or even "the type at
* position x in the input frame, with y more (or less) array dimensions".
* This explains the rather complicated type format used in output frames.
- *
+ *
* This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
* signed number of array dimensions (from -8 to 7). KIND is either BASE,
* LOCAL or STACK. BASE is used for types that are not relative to the input
@@ -70,23 +70,23 @@ final class Frame {
* stack types. VALUE depends on KIND. For LOCAL types, it is an index in
* the input local variable types. For STACK types, it is a position
* relatively to the top of input frame stack. For BASE types, it is either
- * one of the constants defined in FrameVisitor, or for OBJECT and
- * UNINITIALIZED types, a tag and an index in the type table.
- *
+ * one of the constants defined below, or for OBJECT and UNINITIALIZED
+ * types, a tag and an index in the type table.
+ *
* Output frames can contain types of any kind and with a positive or
* negative dimension (and even unassigned types, represented by 0 - which
* does not correspond to any valid type value). Input frames can only
* contain BASE types of positive or null dimension. In all cases the type
* table contains only internal type names (array type descriptors are
* forbidden - dimensions must be represented through the DIM field).
- *
- * The LONG and DOUBLE types are always represented by using two slots (LONG +
- * TOP or DOUBLE + TOP), for local variable types as well as in the operand
- * stack. This is necessary to be able to simulate DUPx_y instructions,
- * whose effect would be dependent on the actual type values if types were
- * always represented by a single slot in the stack (and this is not
- * possible, since actual type values are not always known - cf LOCAL and
- * STACK type kinds).
+ *
+ * The LONG and DOUBLE types are always represented by using two slots (LONG
+ * + TOP or DOUBLE + TOP), for local variable types as well as in the
+ * operand stack. This is necessary to be able to simulate DUPx_y
+ * instructions, whose effect would be dependent on the actual type values
+ * if types were always represented by a single slot in the stack (and this
+ * is not possible, since actual type values are not always known - cf LOCAL
+ * and STACK type kinds).
*/
/**
@@ -107,7 +107,7 @@ final class Frame {
/**
* Mask to get the kind of a frame type.
- *
+ *
* @see #BASE
* @see #LOCAL
* @see #STACK
@@ -117,9 +117,9 @@ final class Frame {
/**
* Flag used for LOCAL and STACK types. Indicates that if this type happens
* to be a long or double type (during the computations of input frames),
- * then it must be set to TOP because the second word of this value has
- * been reused to store other data in the basic block. Hence the first word
- * no longer stores a valid long or double value.
+ * then it must be set to TOP because the second word of this value has been
+ * reused to store other data in the basic block. Hence the first word no
+ * longer stores a valid long or double value.
*/
static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
@@ -489,10 +489,10 @@ final class Frame {
/**
* Relative size of the output stack. The exact semantics of this field
* depends on the algorithm that is used.
- *
+ *
* When only the maximum stack size is computed, this field is the size of
* the output stack relatively to the top of the input stack.
- *
+ *
* When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}.
*/
@@ -500,7 +500,7 @@ final class Frame {
/**
* Number of types that are initialized in the basic block.
- *
+ *
* @see #initializations
*/
private int initializationCount;
@@ -522,8 +522,9 @@ final class Frame {
/**
* Returns the output frame local variable type at the given index.
- *
- * @param local the index of the local that must be returned.
+ *
+ * @param local
+ * the index of the local that must be returned.
* @return the output frame local variable type at the given index.
*/
private int get(final int local) {
@@ -544,9 +545,11 @@ final class Frame {
/**
* Sets the output frame local variable type at the given index.
- *
- * @param local the index of the local that must be set.
- * @param type the value of the local that must be set.
+ *
+ * @param local
+ * the index of the local that must be set.
+ * @param type
+ * the value of the local that must be set.
*/
private void set(final int local, final int type) {
// creates and/or resizes the output local variables array if necessary
@@ -565,8 +568,9 @@ final class Frame {
/**
* Pushes a new type onto the output frame stack.
- *
- * @param type the type that must be pushed.
+ *
+ * @param type
+ * the type that must be pushed.
*/
private void push(final int type) {
// creates and/or resizes the output stack array if necessary
@@ -590,11 +594,13 @@ final class Frame {
/**
* Pushes a new type onto the output frame stack.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param desc the descriptor of the type to be pushed. Can also be a method
- * descriptor (in this case this method pushes its return type onto
- * the output frame stack).
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * the descriptor of the type to be pushed. Can also be a method
+ * descriptor (in this case this method pushes its return type
+ * onto the output frame stack).
*/
private void push(final ClassWriter cw, final String desc) {
int type = type(cw, desc);
@@ -608,79 +614,81 @@ final class Frame {
/**
* Returns the int encoding of the given type.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param desc a type descriptor.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * a type descriptor.
* @return the int encoding of the given type.
*/
private static int type(final ClassWriter cw, final String desc) {
String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) {
- case 'V':
- return 0;
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ // stores the internal name, not the descriptor!
+ t = desc.substring(index + 1, desc.length() - 1);
+ return OBJECT | cw.addType(t);
+ // case '[':
+ default:
+ // extracts the dimensions and the element type
+ int data;
+ int dims = index + 1;
+ while (desc.charAt(dims) == '[') {
+ ++dims;
+ }
+ switch (desc.charAt(dims)) {
case 'Z':
+ data = BOOLEAN;
+ break;
case 'C':
+ data = CHAR;
+ break;
case 'B':
+ data = BYTE;
+ break;
case 'S':
+ data = SHORT;
+ break;
case 'I':
- return INTEGER;
+ data = INTEGER;
+ break;
case 'F':
- return FLOAT;
+ data = FLOAT;
+ break;
case 'J':
- return LONG;
+ data = LONG;
+ break;
case 'D':
- return DOUBLE;
- case 'L':
- // stores the internal name, not the descriptor!
- t = desc.substring(index + 1, desc.length() - 1);
- return OBJECT | cw.addType(t);
- // case '[':
+ data = DOUBLE;
+ break;
+ // case 'L':
default:
- // extracts the dimensions and the element type
- int data;
- int dims = index + 1;
- while (desc.charAt(dims) == '[') {
- ++dims;
- }
- switch (desc.charAt(dims)) {
- case 'Z':
- data = BOOLEAN;
- break;
- case 'C':
- data = CHAR;
- break;
- case 'B':
- data = BYTE;
- break;
- case 'S':
- data = SHORT;
- break;
- case 'I':
- data = INTEGER;
- break;
- case 'F':
- data = FLOAT;
- break;
- case 'J':
- data = LONG;
- break;
- case 'D':
- data = DOUBLE;
- break;
- // case 'L':
- default:
- // stores the internal name, not the descriptor
- t = desc.substring(dims + 1, desc.length() - 1);
- data = OBJECT | cw.addType(t);
- }
- return (dims - index) << 28 | data;
+ // stores the internal name, not the descriptor
+ t = desc.substring(dims + 1, desc.length() - 1);
+ data = OBJECT | cw.addType(t);
+ }
+ return (dims - index) << 28 | data;
}
}
/**
* Pops a type from the output frame stack and returns its value.
- *
+ *
* @return the type that has been popped from the output frame stack.
*/
private int pop() {
@@ -694,8 +702,9 @@ final class Frame {
/**
* Pops the given number of types from the output frame stack.
- *
- * @param elements the number of types that must be popped.
+ *
+ * @param elements
+ * the number of types that must be popped.
*/
private void pop(final int elements) {
if (outputStackTop >= elements) {
@@ -711,10 +720,11 @@ final class Frame {
/**
* Pops a type from the output frame stack.
- *
- * @param desc the descriptor of the type to be popped. Can also be a method
- * descriptor (in this case this method pops the types corresponding
- * to the method arguments).
+ *
+ * @param desc
+ * the descriptor of the type to be popped. Can also be a method
+ * descriptor (in this case this method pops the types
+ * corresponding to the method arguments).
*/
private void pop(final String desc) {
char c = desc.charAt(0);
@@ -730,8 +740,9 @@ final class Frame {
/**
* Adds a new type to the list of types on which a constructor is invoked in
* the basic block.
- *
- * @param var a type on a which a constructor is invoked.
+ *
+ * @param var
+ * a type on a which a constructor is invoked.
*/
private void init(final int var) {
// creates and/or resizes the initializations array if necessary
@@ -751,9 +762,11 @@ final class Frame {
/**
* Replaces the given type with the appropriate type if it is one of the
* types on which a constructor is invoked in the basic block.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param t a type
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * a type
* @return t or, if t is one of the types on which a constructor is invoked
* in the basic block, the type corresponding to this constructor.
*/
@@ -786,18 +799,18 @@ final class Frame {
/**
* Initializes the input frame of the first basic block from the method
* descriptor.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param access the access flags of the method to which this label belongs.
- * @param args the formal parameter types of this method.
- * @param maxLocals the maximum number of local variables of this method.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param access
+ * the access flags of the method to which this label belongs.
+ * @param args
+ * the formal parameter types of this method.
+ * @param maxLocals
+ * the maximum number of local variables of this method.
*/
- void initInputFrame(
- final ClassWriter cw,
- final int access,
- final Type[] args,
- final int maxLocals)
- {
+ void initInputFrame(final ClassWriter cw, final int access,
+ final Type[] args, final int maxLocals) {
inputLocals = new int[maxLocals];
inputStack = new int[0];
int i = 0;
@@ -822,436 +835,436 @@ final class Frame {
/**
* Simulates the action of the given instruction on the output stack frame.
- *
- * @param opcode the opcode of the instruction.
- * @param arg the operand of the instruction, if any.
- * @param cw the class writer to which this label belongs.
- * @param item the operand of the instructions, if any.
+ *
+ * @param opcode
+ * the opcode of the instruction.
+ * @param arg
+ * the operand of the instruction, if any.
+ * @param cw
+ * the class writer to which this label belongs.
+ * @param item
+ * the operand of the instructions, if any.
*/
- void execute(
- final int opcode,
- final int arg,
- final ClassWriter cw,
- final Item item)
- {
+ void execute(final int opcode, final int arg, final ClassWriter cw,
+ final Item item) {
int t1, t2, t3, t4;
switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- case Opcodes.ILOAD:
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (item.type) {
+ case ClassWriter.INT:
push(INTEGER);
break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- case Opcodes.LLOAD:
+ case ClassWriter.LONG:
push(LONG);
push(TOP);
break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- case Opcodes.FLOAD:
+ case ClassWriter.FLOAT:
push(FLOAT);
break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- case Opcodes.DLOAD:
+ case ClassWriter.DOUBLE:
push(DOUBLE);
push(TOP);
break;
- case Opcodes.LDC:
- switch (item.type) {
- case ClassWriter.INT:
- push(INTEGER);
- break;
- case ClassWriter.LONG:
- push(LONG);
- push(TOP);
- break;
- case ClassWriter.FLOAT:
- push(FLOAT);
- break;
- case ClassWriter.DOUBLE:
- push(DOUBLE);
- push(TOP);
- break;
- case ClassWriter.CLASS:
- push(OBJECT | cw.addType("java/lang/Class"));
- break;
- case ClassWriter.STR:
- push(OBJECT | cw.addType("java/lang/String"));
- break;
- case ClassWriter.MTYPE:
- push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
- break;
- // case ClassWriter.HANDLE_BASE + [1..9]:
- default:
- push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
- }
- break;
- case Opcodes.ALOAD:
- push(get(arg));
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(FLOAT);
+ case ClassWriter.CLASS:
+ push(OBJECT | cw.addType("java/lang/Class"));
break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(DOUBLE);
- push(TOP);
+ case ClassWriter.STR:
+ push(OBJECT | cw.addType("java/lang/String"));
break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- push(ELEMENT_OF + t1);
+ case ClassWriter.MTYPE:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(arg, t1);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
+ // case ClassWriter.HANDLE_BASE + [1..9]:
+ default:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(get(arg));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ push(ELEMENT_OF + t1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(arg, t1);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
}
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(arg, t1);
- set(arg + 1, TOP);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(arg, t1);
+ set(arg + 1, TOP);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
}
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ set(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException(
+ "JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(item.strVal3);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(item.strVal3);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(item.strVal3);
+ if (opcode != Opcodes.INVOKESTATIC) {
t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.IINC:
- set(arg, INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException("JSR/RET are not supported with computeFrames option");
- case Opcodes.GETSTATIC:
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTSTATIC:
- pop(item.strVal3);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTFIELD:
- pop(item.strVal3);
- pop();
- break;
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE:
- pop(item.strVal3);
- if (opcode != Opcodes.INVOKESTATIC) {
- t1 = pop();
- if (opcode == Opcodes.INVOKESPECIAL
- && item.strVal2.charAt(0) == '<')
- {
- init(t1);
- }
+ if (opcode == Opcodes.INVOKESPECIAL
+ && item.strVal2.charAt(0) == '<') {
+ init(t1);
}
- push(cw, item.strVal3);
+ }
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.INVOKEDYNAMIC:
+ pop(item.strVal2);
+ push(cw, item.strVal2);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
break;
- case Opcodes.INVOKEDYNAMIC:
- pop(item.strVal2);
- push(cw, item.strVal2);
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
break;
- case Opcodes.NEW:
- push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
break;
- case Opcodes.NEWARRAY:
- pop();
- switch (arg) {
- case Opcodes.T_BOOLEAN:
- push(ARRAY_OF | BOOLEAN);
- break;
- case Opcodes.T_CHAR:
- push(ARRAY_OF | CHAR);
- break;
- case Opcodes.T_BYTE:
- push(ARRAY_OF | BYTE);
- break;
- case Opcodes.T_SHORT:
- push(ARRAY_OF | SHORT);
- break;
- case Opcodes.T_INT:
- push(ARRAY_OF | INTEGER);
- break;
- case Opcodes.T_FLOAT:
- push(ARRAY_OF | FLOAT);
- break;
- case Opcodes.T_DOUBLE:
- push(ARRAY_OF | DOUBLE);
- break;
- // case Opcodes.T_LONG:
- default:
- push(ARRAY_OF | LONG);
- break;
- }
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
break;
- case Opcodes.ANEWARRAY:
- String s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, '[' + s);
- } else {
- push(ARRAY_OF | OBJECT | cw.addType(s));
- }
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
break;
- case Opcodes.CHECKCAST:
- s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, s);
- } else {
- push(OBJECT | cw.addType(s));
- }
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
+ break;
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
break;
- // case Opcodes.MULTIANEWARRAY:
+ // case Opcodes.T_LONG:
default:
- pop(arg);
- push(cw, item.strVal1);
+ push(ARRAY_OF | LONG);
break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, '[' + s);
+ } else {
+ push(ARRAY_OF | OBJECT | cw.addType(s));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, s);
+ } else {
+ push(OBJECT | cw.addType(s));
+ }
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(arg);
+ push(cw, item.strVal1);
+ break;
}
}
@@ -1259,11 +1272,14 @@ final class Frame {
* Merges the input frame of the given basic block with the input and output
* frames of this basic block. Returns <tt>true</tt> if the input frame of
* the given label has been changed by this operation.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param frame the basic block whose input frame must be updated.
- * @param edge the kind of the {@link Edge} between this label and 'label'.
- * See {@link Edge#info}.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param frame
+ * the basic block whose input frame must be updated.
+ * @param edge
+ * the kind of the {@link Edge} between this label and 'label'.
+ * See {@link Edge#info}.
* @return <tt>true</tt> if the input frame of the given label has been
* changed by this operation.
*/
@@ -1294,7 +1310,8 @@ final class Frame {
} else {
t = dim + inputStack[nStack - (s & VALUE)];
}
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
t = TOP;
}
}
@@ -1346,7 +1363,8 @@ final class Frame {
} else {
t = dim + inputStack[nStack - (s & VALUE)];
}
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
t = TOP;
}
}
@@ -1362,20 +1380,20 @@ final class Frame {
* Merges the type at the given index in the given type array with the given
* type. Returns <tt>true</tt> if the type array has been modified by this
* operation.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param t the type with which the type array element must be merged.
- * @param types an array of types.
- * @param index the index of the type that must be merged in 'types'.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * the type with which the type array element must be merged.
+ * @param types
+ * an array of types.
+ * @param index
+ * the index of the type that must be merged in 'types'.
* @return <tt>true</tt> if the type array has been modified by this
* operation.
*/
- private static boolean merge(
- final ClassWriter cw,
- int t,
- final int[] types,
- final int index)
- {
+ private static boolean merge(final ClassWriter cw, int t,
+ final int[] types, final int index) {
int u = types[index];
if (u == t) {
// if the types are equal, merge(u,t)=u, so there is no change
@@ -1399,6 +1417,7 @@ final class Frame {
// if t is the NULL type, merge(u,t)=u, so there is no change
return false;
} else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ // if t and u have the same dimension and same base kind
if ((u & BASE_KIND) == OBJECT) {
// if t is also a reference type, and if u and t have the
// same dimension merge(u,t) = dim(t) | common parent of the
@@ -1411,9 +1430,13 @@ final class Frame {
v = OBJECT | cw.addType("java/lang/Object");
}
} else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
- // if t is any other reference or array type,
- // merge(u,t)=java/lang/Object
- v = OBJECT | cw.addType("java/lang/Object");
+ // if t is any other reference or array type, the merged type
+ // is Object, or min(dim(u), dim(t)) | java/lang/Object is u
+ // and t have different array dimensions
+ int tdim = t & DIM;
+ int udim = u & DIM;
+ v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
+ | cw.addType("java/lang/Object");
} else {
// if t is any other type, merge(u,t)=TOP
v = TOP;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
index e8906fe..e01fd40 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A reference to a field or a method.
- *
+ *
* @author Remi Forax
* @author Eric Bruneton
*/
@@ -49,7 +49,8 @@ public final class Handle {
final int tag;
/**
- * The internal name of the field or method designed by this handle.
+ * The internal name of the class that owns the field or method designated
+ * by this handle.
*/
final String owner;
@@ -65,19 +66,24 @@ public final class Handle {
/**
* Constructs a new field or method handle.
- *
- * @param tag the kind of field or method designated by this Handle. Must be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method designed by this
- * handle.
- * @param name the name of the field or method designated by this handle.
- * @param desc the descriptor of the field or method designated by this
- * handle.
+ *
+ * @param tag
+ * the kind of field or method designated by this Handle. Must be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the class that owns the field or method
+ * designated by this handle.
+ * @param name
+ * the name of the field or method designated by this handle.
+ * @param desc
+ * the descriptor of the field or method designated by this
+ * handle.
*/
public Handle(int tag, String owner, String name, String desc) {
this.tag = tag;
@@ -88,7 +94,7 @@ public final class Handle {
/**
* Returns the kind of field or method designated by this handle.
- *
+ *
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
@@ -101,11 +107,11 @@ public final class Handle {
}
/**
- * Returns the internal name of the field or method designed by this
- * handle.
- *
- * @return the internal name of the field or method designed by this
- * handle.
+ * Returns the internal name of the class that owns the field or method
+ * designated by this handle.
+ *
+ * @return the internal name of the class that owns the field or method
+ * designated by this handle.
*/
public String getOwner() {
return owner;
@@ -113,7 +119,7 @@ public final class Handle {
/**
* Returns the name of the field or method designated by this handle.
- *
+ *
* @return the name of the field or method designated by this handle.
*/
public String getName() {
@@ -122,7 +128,7 @@ public final class Handle {
/**
* Returns the descriptor of the field or method designated by this handle.
- *
+ *
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
@@ -138,8 +144,8 @@ public final class Handle {
return false;
}
Handle h = (Handle) obj;
- return tag == h.tag && owner.equals(h.owner)
- && name.equals(h.name) && desc.equals(h.desc);
+ return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
+ && desc.equals(h.desc);
}
@Override
@@ -149,8 +155,13 @@ public final class Handle {
/**
* Returns the textual representation of this handle. The textual
- * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
- * this format is unambiguous, it can be parsed if necessary.
+ * representation is:
+ *
+ * <pre>
+ * owner '.' name desc ' ' '(' tag ')'
+ * </pre>
+ *
+ * . As this format is unambiguous, it can be parsed if necessary.
*/
@Override
public String toString() {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
index 94ac8e5..a387654 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* Information about an exception handler block.
- *
+ *
* @author Eric Bruneton
*/
class Handler {
@@ -71,10 +71,13 @@ class Handler {
/**
* Removes the range between start and end from the given exception
* handlers.
- *
- * @param h an exception handler list.
- * @param start the start of the range to be removed.
- * @param end the end of the range to be removed. Maybe null.
+ *
+ * @param h
+ * an exception handler list.
+ * @param start
+ * the start of the range to be removed.
+ * @param end
+ * the end of the range to be removed. Maybe null.
* @return the exception handler list with the start-end range removed.
*/
static Handler remove(Handler h, Label start, Label end) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
index 4fab86a..fa4f454 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link ClassWriter} class.
- *
+ *
* @author Eric Bruneton
*/
final class Item {
@@ -52,11 +52,11 @@ final class Item {
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
- *
- * MethodHandle constant 9 variations are stored using a range
- * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+ *
+ * MethodHandle constant 9 variations are stored using a range of 9 values
+ * from {@link ClassWriter#HANDLE_BASE} + 1 to
* {@link ClassWriter#HANDLE_BASE} + 9.
- *
+ *
* Special Item types are used for Items that are stored in the ClassWriter
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
* avoid clashes with normal constant pool items in the ClassWriter constant
@@ -114,8 +114,9 @@ final class Item {
/**
* Constructs an uninitialized {@link Item} for constant pool element at
* given position.
- *
- * @param index index of the item to be constructed.
+ *
+ * @param index
+ * index of the item to be constructed.
*/
Item(final int index) {
this.index = index;
@@ -123,9 +124,11 @@ final class Item {
/**
* Constructs a copy of the given item.
- *
- * @param index index of the item to be constructed.
- * @param i the item that must be copied into the item to be constructed.
+ *
+ * @param index
+ * index of the item to be constructed.
+ * @param i
+ * the item that must be copied into the item to be constructed.
*/
Item(final int index, final Item i) {
this.index = index;
@@ -140,8 +143,9 @@ final class Item {
/**
* Sets this item to an integer item.
- *
- * @param intVal the value of this item.
+ *
+ * @param intVal
+ * the value of this item.
*/
void set(final int intVal) {
this.type = ClassWriter.INT;
@@ -151,8 +155,9 @@ final class Item {
/**
* Sets this item to a long item.
- *
- * @param longVal the value of this item.
+ *
+ * @param longVal
+ * the value of this item.
*/
void set(final long longVal) {
this.type = ClassWriter.LONG;
@@ -162,8 +167,9 @@ final class Item {
/**
* Sets this item to a float item.
- *
- * @param floatVal the value of this item.
+ *
+ * @param floatVal
+ * the value of this item.
*/
void set(final float floatVal) {
this.type = ClassWriter.FLOAT;
@@ -173,8 +179,9 @@ final class Item {
/**
* Sets this item to a double item.
- *
- * @param doubleVal the value of this item.
+ *
+ * @param doubleVal
+ * the value of this item.
*/
void set(final double doubleVal) {
this.type = ClassWriter.DOUBLE;
@@ -184,50 +191,54 @@ final class Item {
/**
* Sets this item to an item that do not hold a primitive value.
- *
- * @param type the type of this item.
- * @param strVal1 first part of the value of this item.
- * @param strVal2 second part of the value of this item.
- * @param strVal3 third part of the value of this item.
+ *
+ * @param type
+ * the type of this item.
+ * @param strVal1
+ * first part of the value of this item.
+ * @param strVal2
+ * second part of the value of this item.
+ * @param strVal3
+ * third part of the value of this item.
*/
- void set(
- final int type,
- final String strVal1,
- final String strVal2,
- final String strVal3)
- {
+ void set(final int type, final String strVal1, final String strVal2,
+ final String strVal3) {
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
- return;
- case ClassWriter.NAME_TYPE:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode());
- return;
- // ClassWriter.FIELD:
- // ClassWriter.METH:
- // ClassWriter.IMETH:
- // ClassWriter.HANDLE_BASE + 1..9
- default:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode() * strVal3.hashCode());
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case ClassWriter.NAME_TYPE: {
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ }
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ // ClassWriter.HANDLE_BASE + 1..9
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
}
}
/**
* Sets the item to an InvokeDynamic item.
- *
- * @param name invokedynamic's name.
- * @param desc invokedynamic's desc.
- * @param bsmIndex zero based index into the class attribute BootrapMethods.
+ *
+ * @param name
+ * invokedynamic's name.
+ * @param desc
+ * invokedynamic's desc.
+ * @param bsmIndex
+ * zero based index into the class attribute BootrapMethods.
*/
void set(String name, String desc, int bsmIndex) {
this.type = ClassWriter.INDY;
@@ -240,11 +251,13 @@ final class Item {
/**
* Sets the item to a BootstrapMethod item.
- *
- * @param position position in byte in the class attribute BootrapMethods.
- * @param hashCode hashcode of the item. This hashcode is processed from
- * the hashcode of the bootstrap method and the hashcode of
- * all bootstrap arguments.
+ *
+ * @param position
+ * position in byte in the class attribute BootrapMethods.
+ * @param hashCode
+ * hashcode of the item. This hashcode is processed from the
+ * hashcode of the bootstrap method and the hashcode of all
+ * bootstrap arguments.
*/
void set(int position, int hashCode) {
this.type = ClassWriter.BSM;
@@ -255,42 +268,43 @@ final class Item {
/**
* Indicates if the given item is equal to this one. <i>This method assumes
* that the two items have the same {@link #type}</i>.
- *
- * @param i the item to be compared to this one. Both items must have the
- * same {@link #type}.
+ *
+ * @param i
+ * the item to be compared to this one. Both items must have the
+ * same {@link #type}.
* @return <tt>true</tt> if the given item if equal to this one,
* <tt>false</tt> otherwise.
*/
boolean isEqualTo(final Item i) {
switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- return i.strVal1.equals(strVal1);
- case ClassWriter.TYPE_MERGED:
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- return i.longVal == longVal;
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- return i.intVal == intVal;
- case ClassWriter.TYPE_UNINIT:
- return i.intVal == intVal && i.strVal1.equals(strVal1);
- case ClassWriter.NAME_TYPE:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
- case ClassWriter.INDY:
- return i.longVal == longVal && i.strVal1.equals(strVal1)
- && i.strVal2.equals(strVal2);
-
- // case ClassWriter.FIELD:
- // case ClassWriter.METH:
- // case ClassWriter.IMETH:
- // case ClassWriter.HANDLE_BASE + 1..9
- default:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
- && i.strVal3.equals(strVal3);
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ return i.strVal1.equals(strVal1);
+ case ClassWriter.TYPE_MERGED:
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ return i.longVal == longVal;
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ return i.intVal == intVal;
+ case ClassWriter.TYPE_UNINIT:
+ return i.intVal == intVal && i.strVal1.equals(strVal1);
+ case ClassWriter.NAME_TYPE:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+ case ClassWriter.INDY: {
+ return i.longVal == longVal && i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2);
+ }
+ // case ClassWriter.FIELD:
+ // case ClassWriter.METH:
+ // case ClassWriter.IMETH:
+ // case ClassWriter.HANDLE_BASE + 1..9
+ default:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+ && i.strVal3.equals(strVal3);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
index ef338c3..c0bbe7e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
@@ -32,10 +32,10 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A label represents a position in the bytecode of a method. Labels are used
* for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that
- * there can be other elements between a label and the instruction it
- * designates (such as other labels, stack map frames, line numbers, etc.).
- *
+ * designates the <i>instruction</i> that is just after. Note however that there
+ * can be other elements between a label and the instruction it designates (such
+ * as other labels, stack map frames, line numbers, etc.).
+ *
* @author Eric Bruneton
*/
public class Label {
@@ -110,14 +110,14 @@ public class Label {
/**
* Field used to associate user information to a label. Warning: this field
* is used by the ASM tree package. In order to use it with the ASM tree
- * package you must override the {@link
- * org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
+ * package you must override the
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
*/
public Object info;
/**
* Flags that indicate the status of this label.
- *
+ *
* @see #DEBUG
* @see #RESOLVED
* @see #RESIZED
@@ -154,7 +154,7 @@ public class Label {
* indicates if this reference uses 2 or 4 bytes, and its absolute value
* gives the position of the bytecode instruction. This array is also used
* as a bitset to store the subroutines to which a basic block belongs. This
- * information is needed in {@linked MethodWriter#visitMaxs}, after all
+ * information is needed in {@linked MethodWriter#visitMaxs}, after all
* forward references have been resolved. Hence the same array can be used
* for both purposes without problems.
*/
@@ -170,19 +170,19 @@ public class Label {
* represented by the Label object that corresponds to the first instruction
* of this basic block. Each node also stores the list of its successors in
* the graph, as a linked list of Edge objects.
- *
+ *
* The control flow analysis algorithms used to compute the maximum stack
* size or the stack map frames are similar and use two steps. The first
* step, during the visit of each instruction, builds information about the
* state of the local variables and the operand stack at the end of each
* basic block, called the "output frame", <i>relatively</i> to the frame
* state at the beginning of the basic block, which is called the "input
- * frame", and which is <i>unknown</i> during this step. The second step,
- * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
- * computes information about the input frame of each basic block, from the
- * input state of the first basic block (known from the method signature),
- * and by the using the previously computed relative output frames.
- *
+ * frame", and which is <i>unknown</i> during this step. The second step, in
+ * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
+ * information about the input frame of each basic block, from the input
+ * state of the first basic block (known from the method signature), and by
+ * the using the previously computed relative output frames.
+ *
* The algorithm used to compute the maximum stack size only computes the
* relative output and absolute input stack heights, while the algorithm
* used to compute stack map frames computes relative output frames and
@@ -192,10 +192,10 @@ public class Label {
/**
* Start of the output stack relatively to the input stack. The exact
* semantics of this field depends on the algorithm that is used.
- *
+ *
* When only the maximum stack size is computed, this field is the number of
* elements in the input stack.
- *
+ *
* When the stack map frames are completely computed, this field is the
* offset of the first output stack element relatively to the top of the
* input stack. This offset is always negative or null. A null offset means
@@ -240,7 +240,7 @@ public class Label {
* main loop of the fix point algorithm used in the second step of the
* control flow analysis algorithms. It is also used in
* {@link #visitSubroutine} to avoid using a recursive method.
- *
+ *
* @see MethodWriter#visitMaxs
*/
Label next;
@@ -264,13 +264,15 @@ public class Label {
* from the start of the method's bytecode. <i>This method is intended for
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
- *
+ *
* @return the offset corresponding to this label.
- * @throws IllegalStateException if this label is not resolved yet.
+ * @throws IllegalStateException
+ * if this label is not resolved yet.
*/
public int getOffset() {
if ((status & RESOLVED) == 0) {
- throw new IllegalStateException("Label offset position has not been resolved yet");
+ throw new IllegalStateException(
+ "Label offset position has not been resolved yet");
}
return position;
}
@@ -280,22 +282,22 @@ public class Label {
* position of the label is known, the offset is computed and written
* directly. Otherwise, a null offset is written and a new forward reference
* is declared for this label.
- *
- * @param owner the code writer that calls this method.
- * @param out the bytecode of the method.
- * @param source the position of first byte of the bytecode instruction that
- * contains this label.
- * @param wideOffset <tt>true</tt> if the reference must be stored in 4
- * bytes, or <tt>false</tt> if it must be stored with 2 bytes.
- * @throws IllegalArgumentException if this label has not been created by
- * the given code writer.
- */
- void put(
- final MethodWriter owner,
- final ByteVector out,
- final int source,
- final boolean wideOffset)
- {
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param out
+ * the bytecode of the method.
+ * @param source
+ * the position of first byte of the bytecode instruction that
+ * contains this label.
+ * @param wideOffset
+ * <tt>true</tt> if the reference must be stored in 4 bytes, or
+ * <tt>false</tt> if it must be stored with 2 bytes.
+ * @throws IllegalArgumentException
+ * if this label has not been created by the given code writer.
+ */
+ void put(final MethodWriter owner, final ByteVector out, final int source,
+ final boolean wideOffset) {
if ((status & RESOLVED) == 0) {
if (wideOffset) {
addReference(-1 - source, out.length);
@@ -318,26 +320,22 @@ public class Label {
* for a true forward reference, i.e. only if this label is not resolved
* yet. For backward references, the offset of the reference can be, and
* must be, computed and stored directly.
- *
- * @param sourcePosition the position of the referencing instruction. This
- * position will be used to compute the offset of this forward
- * reference.
- * @param referencePosition the position where the offset for this forward
- * reference must be stored.
- */
- private void addReference(
- final int sourcePosition,
- final int referencePosition)
- {
+ *
+ * @param sourcePosition
+ * the position of the referencing instruction. This position
+ * will be used to compute the offset of this forward reference.
+ * @param referencePosition
+ * the position where the offset for this forward reference must
+ * be stored.
+ */
+ private void addReference(final int sourcePosition,
+ final int referencePosition) {
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
- System.arraycopy(srcAndRefPositions,
- 0,
- a,
- 0,
+ System.arraycopy(srcAndRefPositions, 0, a, 0,
srcAndRefPositions.length);
srcAndRefPositions = a;
}
@@ -350,10 +348,13 @@ public class Label {
* when this label is added to the bytecode of the method, i.e. when its
* position becomes known. This method fills in the blanks that where left
* in the bytecode by each forward reference previously added to this label.
- *
- * @param owner the code writer that calls this method.
- * @param position the position of this label in the bytecode.
- * @param data the bytecode of the method.
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param position
+ * the position of this label in the bytecode.
+ * @param data
+ * the bytecode of the method.
* @return <tt>true</tt> if a blank that was left for this label was to
* small to store the offset. In such a case the corresponding jump
* instruction is replaced with a pseudo instruction (using unused
@@ -361,14 +362,12 @@ public class Label {
* instructions will need to be replaced with true instructions with
* wider offsets (4 bytes instead of 2). This is done in
* {@link MethodWriter#resizeInstructions}.
- * @throws IllegalArgumentException if this label has already been resolved,
- * or if it has not been created by the given code writer.
- */
- boolean resolve(
- final MethodWriter owner,
- final int position,
- final byte[] data)
- {
+ * @throws IllegalArgumentException
+ * if this label has already been resolved, or if it has not
+ * been created by the given code writer.
+ */
+ boolean resolve(final MethodWriter owner, final int position,
+ final byte[] data) {
boolean needUpdate = false;
this.status |= RESOLVED;
this.position = position;
@@ -417,7 +416,7 @@ public class Label {
* isolated label or for the first label in a series of successive labels,
* this method returns the label itself. For other labels it returns the
* first label of the series.
- *
+ *
* @return the first label of the series to which this label belongs.
*/
Label getFirst() {
@@ -430,8 +429,9 @@ public class Label {
/**
* Returns true is this basic block belongs to the given subroutine.
- *
- * @param id a subroutine id.
+ *
+ * @param id
+ * a subroutine id.
* @return true is this basic block belongs to the given subroutine.
*/
boolean inSubroutine(final long id) {
@@ -444,8 +444,9 @@ public class Label {
/**
* Returns true if this basic block and the given one belong to a common
* subroutine.
- *
- * @param block another basic block.
+ *
+ * @param block
+ * another basic block.
* @return true if this basic block and the given one belong to a common
* subroutine.
*/
@@ -463,9 +464,11 @@ public class Label {
/**
* Marks this basic block as belonging to the given subroutine.
- *
- * @param id a subroutine id.
- * @param nbSubroutines the total number of subroutines in the method.
+ *
+ * @param id
+ * a subroutine id.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
*/
void addToSubroutine(final long id, final int nbSubroutines) {
if ((status & VISITED) == 0) {
@@ -480,15 +483,17 @@ public class Label {
* blocks as belonging to this subroutine. This method follows the control
* flow graph to find all the blocks that are reachable from the current
* block WITHOUT following any JSR target.
- *
- * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
- * null it is added to the successor of the RET blocks found in the
- * subroutine.
- * @param id the id of this subroutine.
- * @param nbSubroutines the total number of subroutines in the method.
- */
- void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
- {
+ *
+ * @param JSR
+ * a JSR block that jumps to this subroutine. If this JSR is not
+ * null it is added to the successor of the RET blocks found in
+ * the subroutine.
+ * @param id
+ * the id of this subroutine.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
+ */
+ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
// user managed stack of labels, to avoid using a recursive method
// (recursivity can lead to stack overflow with very large methods)
Label stack = this;
@@ -545,7 +550,7 @@ public class Label {
/**
* Returns a string representation of this label.
- *
+ *
* @return a string representation of this label.
*/
@Override
[06/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..294fd46
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckClassAdapter.java
@@ -0,0 +1,1009 @@
+/***
+ * 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.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.ClassNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Frame;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link ClassVisitor} 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 ClassVisitor {
+
+ /**
+ * 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<Label, Integer> labels;
+
+ /**
+ * <tt>true</tt> if the method code must be checked with a BasicVerifier.
+ */
+ private boolean checkDataFlow;
+
+ /**
+ * Checks a given class.
+ * <p>
+ * Usage: CheckClassAdapter <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ if (args.length != 1) {
+ System.err.println("Verifies the given class.");
+ System.err.println("Usage: CheckClassAdapter "
+ + "<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<MethodNode> methods = cn.methods;
+
+ List<Type> interfaces = new ArrayList<Type>();
+ for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
+ interfaces.add(Type.getObjectType(i.next()));
+ }
+
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = methods.get(i);
+ SimpleVerifier verifier = new SimpleVerifier(
+ Type.getObjectType(cn.name), syperType, interfaces,
+ (cn.access & Opcodes.ACC_INTERFACE) != 0);
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(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<BasicValue> a,
+ final PrintWriter pw) {
+ Frame<BasicValue>[] frames = a.getFrames();
+ Textifier t = new Textifier();
+ TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+ pw.println(method.name + method.desc);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ method.instructions.get(j).accept(mv);
+
+ StringBuffer s = new StringBuffer();
+ Frame<BasicValue> f = frames[j];
+ if (f == null) {
+ s.append('?');
+ } else {
+ for (int k = 0; k < f.getLocals(); ++k) {
+ s.append(getShortName(f.getLocal(k).toString()))
+ .append(' ');
+ }
+ s.append(" : ");
+ for (int k = 0; k < f.getStackSize(); ++k) {
+ s.append(getShortName(f.getStack(k).toString()))
+ .append(' ');
+ }
+ }
+ while (s.length() < method.maxStack + method.maxLocals + 1) {
+ s.append(' ');
+ }
+ pw.print(Integer.toString(j + 100000).substring(1));
+ pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+ }
+ for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+ method.tryCatchBlocks.get(j).accept(mv);
+ pw.print(" " + t.text.get(t.text.size() - 1));
+ }
+ pw.println();
+ }
+
+ private static String getShortName(final String name) {
+ int n = name.lastIndexOf('/');
+ int k = name.length();
+ if (name.charAt(k - 1) == ';') {
+ k--;
+ }
+ return n == -1 ? name : name.substring(n + 1, k);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param cv
+ * the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor cv) {
+ this(cv, true);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @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.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) {
+ this(Opcodes.ASM5, cv, checkDataFlow);
+ if (getClass() != CheckClassAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @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.
+ */
+ protected CheckClassAdapter(final int api, final ClassVisitor cv,
+ final boolean checkDataFlow) {
+ super(api, cv);
+ this.labels = new HashMap<Label, Integer>();
+ this.checkDataFlow = checkDataFlow;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ if (start) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ start = true;
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+ + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (name == null || !name.endsWith("package-info")) {
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException(
+ "The super class name of the Object class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(superName, "super class name");
+ }
+ if (signature != null) {
+ checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException(
+ "The super class name of interfaces must be 'java/lang/Object'");
+ }
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(interfaces[i],
+ "interface name at index " + i);
+ }
+ }
+ this.version = version;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (source) {
+ throw new IllegalStateException(
+ "visitSource can be called only once.");
+ }
+ source = true;
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ checkState();
+ if (outer) {
+ throw new IllegalStateException(
+ "visitOuterClass can be called only once.");
+ }
+ outer = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
+ }
+ if (desc != null) {
+ CheckMethodAdapter.checkMethodDesc(desc);
+ }
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ checkState();
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+ }
+ if (innerName != null) {
+ int start = 0;
+ while (start < innerName.length()
+ && Character.isDigit(innerName.charAt(start))) {
+ start++;
+ }
+ if (start == 0 || start < innerName.length()) {
+ CheckMethodAdapter.checkIdentifier(innerName, start, -1,
+ "inner class name");
+ }
+ }
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+ + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (signature != null) {
+ checkFieldSignature(signature);
+ }
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ FieldVisitor av = super
+ .visitField(access, name, desc, signature, value);
+ return new CheckFieldAdapter(av);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+ + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+ + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (!"<init>".equals(name) && !"<clinit>".equals(name)) {
+ CheckMethodAdapter.checkMethodIdentifier(version, name,
+ "method name");
+ }
+ CheckMethodAdapter.checkMethodDesc(desc);
+ if (signature != null) {
+ checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(exceptions[i],
+ "exception name at index " + i);
+ }
+ }
+ CheckMethodAdapter cma;
+ if (checkDataFlow) {
+ cma = new CheckMethodAdapter(access, name, desc, super.visitMethod(
+ access, name, desc, signature, exceptions), labels);
+ } else {
+ cma = new CheckMethodAdapter(super.visitMethod(access, name, desc,
+ signature, exceptions), labels);
+ }
+ cma.version = version;
+ return cma;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkState();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkState();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.CLASS_TYPE_PARAMETER
+ && sort != TypeReference.CLASS_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.CLASS_EXTENDS) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkState();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkState();
+ end = true;
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that the visit method has been called and that visitEnd has not
+ * been called.
+ */
+ private void checkState() {
+ if (!start) {
+ throw new IllegalStateException(
+ "Cannot visit member before visit has been called.");
+ }
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot visit member after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This
+ * method also checks that mutually incompatible flags are not set
+ * simultaneously.
+ *
+ * @param access
+ * the access flags to be checked
+ * @param possibleAccess
+ * the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: "
+ + access);
+ }
+ int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+ int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+ int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+ if (pub + pri + pro > 1) {
+ throw new IllegalArgumentException(
+ "public private and protected are mutually exclusive: "
+ + access);
+ }
+ int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+ int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+ if (fin + abs > 1) {
+ throw new IllegalArgumentException(
+ "final and abstract are mutually exclusive: " + access);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkClassSignature(final String signature) {
+ // ClassSignature:
+ // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkMethodSignature(final String signature) {
+ // MethodTypeSignature:
+ // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+ // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ */
+ public static void checkFieldSignature(final String signature) {
+ int pos = checkFieldTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks the reference to a type in a type annotation.
+ *
+ * @param typeRef
+ * a reference to an annotated type.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ */
+ static void checkTypeRefAndPath(int typeRef, TypePath typePath) {
+ int mask = 0;
+ switch (typeRef >>> 24) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ mask = 0xFFFF0000;
+ break;
+ case TypeReference.FIELD:
+ case TypeReference.METHOD_RETURN:
+ case TypeReference.METHOD_RECEIVER:
+ case TypeReference.LOCAL_VARIABLE:
+ case TypeReference.RESOURCE_VARIABLE:
+ case TypeReference.INSTANCEOF:
+ case TypeReference.NEW:
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ case TypeReference.METHOD_REFERENCE:
+ mask = 0xFF000000;
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ case TypeReference.THROWS:
+ case TypeReference.EXCEPTION_PARAMETER:
+ mask = 0xFFFFFF00;
+ break;
+ case TypeReference.CAST:
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ mask = 0xFF0000FF;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(typeRef >>> 24));
+ }
+ if ((typeRef & ~mask) != 0) {
+ throw new IllegalArgumentException("Invalid type reference 0x"
+ + Integer.toHexString(typeRef));
+ }
+ if (typePath != null) {
+ for (int i = 0; i < typePath.getLength(); ++i) {
+ int step = typePath.getStep(i);
+ if (step != TypePath.ARRAY_ELEMENT
+ && step != TypePath.INNER_TYPE
+ && step != TypePath.TYPE_ARGUMENT
+ && step != TypePath.WILDCARD_BOUND) {
+ throw new IllegalArgumentException(
+ "Invalid type path step " + i + " in " + typePath);
+ }
+ if (step != TypePath.TYPE_ARGUMENT
+ && typePath.getStepArgument(i) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid type path step argument for step " + i
+ + " in " + typePath);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks the formal type parameters of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameters(final String signature, int pos) {
+ // FormalTypeParameters:
+ // < FormalTypeParameter+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkFormalTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkFormalTypeParameter(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a formal type parameter of a class or method signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameter(final String signature, int pos) {
+ // FormalTypeParameter:
+ // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+ pos = checkIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkFieldTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkFieldTypeSignature(signature, pos + 1);
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a field type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFieldTypeSignature(final String signature, int pos) {
+ // FieldTypeSignature:
+ // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+ //
+ // ArrayTypeSignature:
+ // [ TypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, int pos) {
+ // ClassTypeSignature:
+ // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+ // TypeArguments? )* ;
+
+ pos = checkChar('L', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkIdentifier(signature, pos + 1);
+ }
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, int pos) {
+ // TypeArguments:
+ // < TypeArgument+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, int pos) {
+ // TypeArgument:
+ // * | ( ( + | - )? FieldTypeSignature )
+
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkFieldTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(final String signature,
+ int pos) {
+ // TypeVariableSignature:
+ // T Identifier ;
+
+ pos = checkChar('T', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks a type signature.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeSignature(final String signature, int pos) {
+ // TypeSignature:
+ // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return pos + 1;
+ default:
+ return checkFieldTypeSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks an identifier.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkIdentifier(final String signature, int pos) {
+ if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+ throw new IllegalArgumentException(signature
+ + ": identifier expected at index " + pos);
+ }
+ ++pos;
+ while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+ ++pos;
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a single character.
+ *
+ * @param signature
+ * a string containing the signature that must be checked.
+ * @param pos
+ * index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, int pos) {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c
+ + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the signature car at the given index.
+ *
+ * @param signature
+ * a signature.
+ * @param pos
+ * an index in signature.
+ * @return the character at the given index, or 0 if there is no such
+ * character.
+ */
+ private static char getChar(final String signature, int pos) {
+ return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..753025b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,122 @@
+/***
+ * 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.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+ private boolean end;
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+ *
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckFieldAdapter(final FieldVisitor fv) {
+ this(Opcodes.ASM5, fv);
+ if (getClass() != CheckFieldAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param fv
+ * the field visitor to which this adapter must delegate calls.
+ */
+ protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+ super(api, fv);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEnd();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkEnd();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.FIELD) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEnd();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ super.visitEnd();
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException(
+ "Cannot call a visit method after visitEnd has been called");
+ }
+ }
+}
[14/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
new file mode 100644
index 0000000..fe8400a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -0,0 +1,1170 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and
+ * transform instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+ public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+ /**
+ * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #InstructionAdapter(int, MethodVisitor)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public InstructionAdapter(final MethodVisitor mv) {
+ this(Opcodes.ASM5, mv);
+ if (getClass() != InstructionAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link InstructionAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ protected InstructionAdapter(final int api, final MethodVisitor mv) {
+ super(api, mv);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ switch (opcode) {
+ case Opcodes.NOP:
+ nop();
+ break;
+ case Opcodes.ACONST_NULL:
+ aconst(null);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ iconst(opcode - Opcodes.ICONST_0);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ lconst(opcode - Opcodes.LCONST_0);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ fconst(opcode - Opcodes.FCONST_0);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ dconst(opcode - Opcodes.DCONST_0);
+ break;
+ case Opcodes.IALOAD:
+ aload(Type.INT_TYPE);
+ break;
+ case Opcodes.LALOAD:
+ aload(Type.LONG_TYPE);
+ break;
+ case Opcodes.FALOAD:
+ aload(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DALOAD:
+ aload(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AALOAD:
+ aload(OBJECT_TYPE);
+ break;
+ case Opcodes.BALOAD:
+ aload(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CALOAD:
+ aload(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SALOAD:
+ aload(Type.SHORT_TYPE);
+ break;
+ case Opcodes.IASTORE:
+ astore(Type.INT_TYPE);
+ break;
+ case Opcodes.LASTORE:
+ astore(Type.LONG_TYPE);
+ break;
+ case Opcodes.FASTORE:
+ astore(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DASTORE:
+ astore(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AASTORE:
+ astore(OBJECT_TYPE);
+ break;
+ case Opcodes.BASTORE:
+ astore(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CASTORE:
+ astore(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SASTORE:
+ astore(Type.SHORT_TYPE);
+ break;
+ case Opcodes.POP:
+ pop();
+ break;
+ case Opcodes.POP2:
+ pop2();
+ break;
+ case Opcodes.DUP:
+ dup();
+ break;
+ case Opcodes.DUP_X1:
+ dupX1();
+ break;
+ case Opcodes.DUP_X2:
+ dupX2();
+ break;
+ case Opcodes.DUP2:
+ dup2();
+ break;
+ case Opcodes.DUP2_X1:
+ dup2X1();
+ break;
+ case Opcodes.DUP2_X2:
+ dup2X2();
+ break;
+ case Opcodes.SWAP:
+ swap();
+ break;
+ case Opcodes.IADD:
+ add(Type.INT_TYPE);
+ break;
+ case Opcodes.LADD:
+ add(Type.LONG_TYPE);
+ break;
+ case Opcodes.FADD:
+ add(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DADD:
+ add(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISUB:
+ sub(Type.INT_TYPE);
+ break;
+ case Opcodes.LSUB:
+ sub(Type.LONG_TYPE);
+ break;
+ case Opcodes.FSUB:
+ sub(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSUB:
+ sub(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IMUL:
+ mul(Type.INT_TYPE);
+ break;
+ case Opcodes.LMUL:
+ mul(Type.LONG_TYPE);
+ break;
+ case Opcodes.FMUL:
+ mul(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DMUL:
+ mul(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IDIV:
+ div(Type.INT_TYPE);
+ break;
+ case Opcodes.LDIV:
+ div(Type.LONG_TYPE);
+ break;
+ case Opcodes.FDIV:
+ div(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DDIV:
+ div(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IREM:
+ rem(Type.INT_TYPE);
+ break;
+ case Opcodes.LREM:
+ rem(Type.LONG_TYPE);
+ break;
+ case Opcodes.FREM:
+ rem(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DREM:
+ rem(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.INEG:
+ neg(Type.INT_TYPE);
+ break;
+ case Opcodes.LNEG:
+ neg(Type.LONG_TYPE);
+ break;
+ case Opcodes.FNEG:
+ neg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DNEG:
+ neg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISHL:
+ shl(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHL:
+ shl(Type.LONG_TYPE);
+ break;
+ case Opcodes.ISHR:
+ shr(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHR:
+ shr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IUSHR:
+ ushr(Type.INT_TYPE);
+ break;
+ case Opcodes.LUSHR:
+ ushr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IAND:
+ and(Type.INT_TYPE);
+ break;
+ case Opcodes.LAND:
+ and(Type.LONG_TYPE);
+ break;
+ case Opcodes.IOR:
+ or(Type.INT_TYPE);
+ break;
+ case Opcodes.LOR:
+ or(Type.LONG_TYPE);
+ break;
+ case Opcodes.IXOR:
+ xor(Type.INT_TYPE);
+ break;
+ case Opcodes.LXOR:
+ xor(Type.LONG_TYPE);
+ break;
+ case Opcodes.I2L:
+ cast(Type.INT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.I2F:
+ cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2D:
+ cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.L2I:
+ cast(Type.LONG_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.L2F:
+ cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.L2D:
+ cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.F2I:
+ cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.F2L:
+ cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.F2D:
+ cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.D2I:
+ cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.D2L:
+ cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.D2F:
+ cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2B:
+ cast(Type.INT_TYPE, Type.BYTE_TYPE);
+ break;
+ case Opcodes.I2C:
+ cast(Type.INT_TYPE, Type.CHAR_TYPE);
+ break;
+ case Opcodes.I2S:
+ cast(Type.INT_TYPE, Type.SHORT_TYPE);
+ break;
+ case Opcodes.LCMP:
+ lcmp();
+ break;
+ case Opcodes.FCMPL:
+ cmpl(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.FCMPG:
+ cmpg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DCMPL:
+ cmpl(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.DCMPG:
+ cmpg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IRETURN:
+ areturn(Type.INT_TYPE);
+ break;
+ case Opcodes.LRETURN:
+ areturn(Type.LONG_TYPE);
+ break;
+ case Opcodes.FRETURN:
+ areturn(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DRETURN:
+ areturn(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ARETURN:
+ areturn(OBJECT_TYPE);
+ break;
+ case Opcodes.RETURN:
+ areturn(Type.VOID_TYPE);
+ break;
+ case Opcodes.ARRAYLENGTH:
+ arraylength();
+ break;
+ case Opcodes.ATHROW:
+ athrow();
+ break;
+ case Opcodes.MONITORENTER:
+ monitorenter();
+ break;
+ case Opcodes.MONITOREXIT:
+ monitorexit();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.SIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.NEWARRAY:
+ switch (operand) {
+ case Opcodes.T_BOOLEAN:
+ newarray(Type.BOOLEAN_TYPE);
+ break;
+ case Opcodes.T_CHAR:
+ newarray(Type.CHAR_TYPE);
+ break;
+ case Opcodes.T_BYTE:
+ newarray(Type.BYTE_TYPE);
+ break;
+ case Opcodes.T_SHORT:
+ newarray(Type.SHORT_TYPE);
+ break;
+ case Opcodes.T_INT:
+ newarray(Type.INT_TYPE);
+ break;
+ case Opcodes.T_FLOAT:
+ newarray(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.T_LONG:
+ newarray(Type.LONG_TYPE);
+ break;
+ case Opcodes.T_DOUBLE:
+ newarray(Type.DOUBLE_TYPE);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ switch (opcode) {
+ case Opcodes.ILOAD:
+ load(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LLOAD:
+ load(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FLOAD:
+ load(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DLOAD:
+ load(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ALOAD:
+ load(var, OBJECT_TYPE);
+ break;
+ case Opcodes.ISTORE:
+ store(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LSTORE:
+ store(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FSTORE:
+ store(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSTORE:
+ store(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ASTORE:
+ store(var, OBJECT_TYPE);
+ break;
+ case Opcodes.RET:
+ ret(var);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ Type t = Type.getObjectType(type);
+ switch (opcode) {
+ case Opcodes.NEW:
+ anew(t);
+ break;
+ case Opcodes.ANEWARRAY:
+ newarray(t);
+ break;
+ case Opcodes.CHECKCAST:
+ checkcast(t);
+ break;
+ case Opcodes.INSTANCEOF:
+ instanceOf(t);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ getstatic(owner, name, desc);
+ break;
+ case Opcodes.PUTSTATIC:
+ putstatic(owner, name, desc);
+ break;
+ case Opcodes.GETFIELD:
+ getfield(owner, name, desc);
+ break;
+ case Opcodes.PUTFIELD:
+ putfield(owner, name, desc);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ switch (opcode) {
+ case Opcodes.INVOKESPECIAL:
+ invokespecial(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ invokevirtual(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKESTATIC:
+ invokestatic(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKEINTERFACE:
+ invokeinterface(owner, name, desc);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ invokedynamic(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ switch (opcode) {
+ case Opcodes.IFEQ:
+ ifeq(label);
+ break;
+ case Opcodes.IFNE:
+ ifne(label);
+ break;
+ case Opcodes.IFLT:
+ iflt(label);
+ break;
+ case Opcodes.IFGE:
+ ifge(label);
+ break;
+ case Opcodes.IFGT:
+ ifgt(label);
+ break;
+ case Opcodes.IFLE:
+ ifle(label);
+ break;
+ case Opcodes.IF_ICMPEQ:
+ ificmpeq(label);
+ break;
+ case Opcodes.IF_ICMPNE:
+ ificmpne(label);
+ break;
+ case Opcodes.IF_ICMPLT:
+ ificmplt(label);
+ break;
+ case Opcodes.IF_ICMPGE:
+ ificmpge(label);
+ break;
+ case Opcodes.IF_ICMPGT:
+ ificmpgt(label);
+ break;
+ case Opcodes.IF_ICMPLE:
+ ificmple(label);
+ break;
+ case Opcodes.IF_ACMPEQ:
+ ifacmpeq(label);
+ break;
+ case Opcodes.IF_ACMPNE:
+ ifacmpne(label);
+ break;
+ case Opcodes.GOTO:
+ goTo(label);
+ break;
+ case Opcodes.JSR:
+ jsr(label);
+ break;
+ case Opcodes.IFNULL:
+ ifnull(label);
+ break;
+ case Opcodes.IFNONNULL:
+ ifnonnull(label);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ mark(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Byte) {
+ int val = ((Byte) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Character) {
+ int val = ((Character) cst).charValue();
+ iconst(val);
+ } else if (cst instanceof Short) {
+ int val = ((Short) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Boolean) {
+ int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+ iconst(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ fconst(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ lconst(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ dconst(val);
+ } else if (cst instanceof String) {
+ aconst(cst);
+ } else if (cst instanceof Type) {
+ tconst((Type) cst);
+ } else if (cst instanceof Handle) {
+ hconst((Handle) cst);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ iinc(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ tableswitch(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ lookupswitch(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ multianewarray(desc, dims);
+ }
+
+ // -----------------------------------------------------------------------
+
+ public void nop() {
+ mv.visitInsn(Opcodes.NOP);
+ }
+
+ public void aconst(final Object cst) {
+ if (cst == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ public void iconst(final int cst) {
+ if (cst >= -1 && cst <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + cst);
+ } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, cst);
+ } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, cst);
+ } else {
+ mv.visitLdcInsn(new Integer(cst));
+ }
+ }
+
+ public void lconst(final long cst) {
+ if (cst == 0L || cst == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Long(cst));
+ }
+ }
+
+ public void fconst(final float cst) {
+ int bits = Float.floatToIntBits(cst);
+ if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Float(cst));
+ }
+ }
+
+ public void dconst(final double cst) {
+ long bits = Double.doubleToLongBits(cst);
+ if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Double(cst));
+ }
+ }
+
+ public void tconst(final Type type) {
+ mv.visitLdcInsn(type);
+ }
+
+ public void hconst(final Handle handle) {
+ mv.visitLdcInsn(handle);
+ }
+
+ public void load(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+ }
+
+ public void aload(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ public void store(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+ }
+
+ public void astore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ public void add(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IADD));
+ }
+
+ public void sub(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+ }
+
+ public void mul(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+ }
+
+ public void div(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+ }
+
+ public void rem(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IREM));
+ }
+
+ public void neg(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.INEG));
+ }
+
+ public void shl(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+ }
+
+ public void shr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+ }
+
+ public void ushr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+ }
+
+ public void and(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IAND));
+ }
+
+ public void or(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IOR));
+ }
+
+ public void xor(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+ }
+
+ public void iinc(final int var, final int increment) {
+ mv.visitIincInsn(var, increment);
+ }
+
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
+ } else {
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
+ } else {
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
+ }
+ }
+ }
+ }
+
+ public void lcmp() {
+ mv.visitInsn(Opcodes.LCMP);
+ }
+
+ public void cmpl(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+ }
+
+ public void cmpg(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+ }
+
+ public void ifeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFEQ, label);
+ }
+
+ public void ifne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNE, label);
+ }
+
+ public void iflt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLT, label);
+ }
+
+ public void ifge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGE, label);
+ }
+
+ public void ifgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGT, label);
+ }
+
+ public void ifle(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLE, label);
+ }
+
+ public void ificmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+ }
+
+ public void ificmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+ }
+
+ public void ificmplt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+ }
+
+ public void ificmpge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+ }
+
+ public void ificmpgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+ }
+
+ public void ificmple(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+ }
+
+ public void ifacmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ }
+
+ public void ifacmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ }
+
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ public void jsr(final Label label) {
+ mv.visitJumpInsn(Opcodes.JSR, label);
+ }
+
+ public void ret(final int var) {
+ mv.visitVarInsn(Opcodes.RET, var);
+ }
+
+ public void tableswitch(final int min, final int max, final Label dflt,
+ final Label... labels) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void lookupswitch(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void areturn(final Type t) {
+ mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
+ }
+
+ public void getstatic(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
+ }
+
+ public void putstatic(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
+ }
+
+ public void getfield(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
+ }
+
+ public void putfield(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
+ }
+
+ @Deprecated
+ public void invokevirtual(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokevirtual(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
+ }
+
+ public void invokevirtual(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKEVIRTUAL on interfaces require ASM 5");
+ }
+ invokevirtual(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
+ }
+
+ @Deprecated
+ public void invokespecial(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokespecial(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
+ }
+
+ public void invokespecial(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL on interfaces require ASM 5");
+ }
+ invokespecial(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
+ }
+
+ @Deprecated
+ public void invokestatic(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokestatic(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
+ }
+
+ public void invokestatic(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKESTATIC on interfaces require ASM 5");
+ }
+ invokestatic(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
+ }
+
+ public void invokeinterface(final String owner, final String name,
+ final String desc) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
+ }
+
+ public void invokedynamic(String name, String desc, Handle bsm,
+ Object[] bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ public void anew(final Type type) {
+ mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+ }
+
+ public void newarray(final Type type) {
+ int typ;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ typ = Opcodes.T_BOOLEAN;
+ break;
+ case Type.CHAR:
+ typ = Opcodes.T_CHAR;
+ break;
+ case Type.BYTE:
+ typ = Opcodes.T_BYTE;
+ break;
+ case Type.SHORT:
+ typ = Opcodes.T_SHORT;
+ break;
+ case Type.INT:
+ typ = Opcodes.T_INT;
+ break;
+ case Type.FLOAT:
+ typ = Opcodes.T_FLOAT;
+ break;
+ case Type.LONG:
+ typ = Opcodes.T_LONG;
+ break;
+ case Type.DOUBLE:
+ typ = Opcodes.T_DOUBLE;
+ break;
+ default:
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+ return;
+ }
+ mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+ }
+
+ public void arraylength() {
+ mv.visitInsn(Opcodes.ARRAYLENGTH);
+ }
+
+ public void athrow() {
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+
+ public void checkcast(final Type type) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+ }
+
+ public void instanceOf(final Type type) {
+ mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+ }
+
+ public void monitorenter() {
+ mv.visitInsn(Opcodes.MONITORENTER);
+ }
+
+ public void monitorexit() {
+ mv.visitInsn(Opcodes.MONITOREXIT);
+ }
+
+ public void multianewarray(final String desc, final int dims) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public void ifnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ public void ifnonnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
index 21f1d68..08e1f3c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
@@ -29,32 +29,47 @@
*/
package org.apache.tapestry5.internal.plastic.asm.commons;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.tree.*;
-
-import java.util.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LocalVariableNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
/**
* A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} that removes JSR instructions and
* inlines the referenced subroutines.
- *
+ *
* <b>Explanation of how it works</b> TODO
- *
+ *
* @author Niko Matsakis
*/
-public class JSRInlinerAdapter extends MethodNode implements Opcodes
-{
+public class JSRInlinerAdapter extends MethodNode implements Opcodes {
private static final boolean LOGGING = false;
/**
- * For each label that is jumped to by a JSR, we create a BitSet
- * instance.
+ * For each label that is jumped to by a JSR, we create a BitSet instance.
*/
- private final Map<LabelNode,BitSet> subroutineHeads = new HashMap<LabelNode,BitSet>();
+ private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>();
/**
* This subroutine instance denotes the line of execution that is not
@@ -72,58 +87,65 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Creates a new JSRInliner. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
- * {@link #JSRInlinerAdapter(int, org.apache.tapestry5.internal.plastic.asm.MethodVisitor, int, String, String, String, String[])}
+ * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])}
* version.
- *
- * @param mv the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param mv
+ * the <code>MethodVisitor</code> to send the resulting inlined
+ * method code to (use <code>null</code> for none).
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public JSRInlinerAdapter(
- final MethodVisitor mv,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions);
+ public JSRInlinerAdapter(final MethodVisitor mv, final int access,
+ final String name, final String desc, final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+ if (getClass() != JSRInlinerAdapter.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Creates a new JSRInliner.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the <code>MethodVisitor</code> to send the resulting inlined
+ * method code to (use <code>null</code> for none).
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- protected JSRInlinerAdapter(
- final int api,
- final MethodVisitor mv,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ protected JSRInlinerAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
super(api, access, name, desc, signature, exceptions);
this.mv = mv;
}
@@ -179,9 +201,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
// Go through the head of each subroutine and find any nodes reachable
// to that subroutine without following any JSR links.
- for (Iterator<Map.Entry<LabelNode,BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext();)
- {
- Map.Entry<LabelNode,BitSet> entry = it.next();
+ for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads
+ .entrySet().iterator(); it.hasNext();) {
+ Map.Entry<LabelNode, BitSet> entry = it.next();
LabelNode lab = entry.getKey();
BitSet sub = entry.getValue();
int index = instructions.indexOf(lab);
@@ -191,24 +213,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Performs a depth first search walking the normal byte code path starting
- * at <code>index</code>, and adding each instruction encountered into
- * the subroutine <code>sub</code>. After this walk is complete, iterates
- * over the exception handlers to ensure that we also include those byte
- * codes which are reachable through an exception that may be thrown during
- * the execution of the subroutine. Invoked from
- * <code>markSubroutines()</code>.
- *
- * @param sub the subroutine whose instructions must be computed.
- * @param index an instruction of this subroutine.
- * @param anyvisited indexes of the already visited instructions, i.e.
- * marked as part of this subroutine or any previously computed
- * subroutine.
+ * at <code>index</code>, and adding each instruction encountered into the
+ * subroutine <code>sub</code>. After this walk is complete, iterates over
+ * the exception handlers to ensure that we also include those byte codes
+ * which are reachable through an exception that may be thrown during the
+ * execution of the subroutine. Invoked from <code>markSubroutines()</code>.
+ *
+ * @param sub
+ * the subroutine whose instructions must be computed.
+ * @param index
+ * an instruction of this subroutine.
+ * @param anyvisited
+ * indexes of the already visited instructions, i.e. marked as
+ * part of this subroutine or any previously computed subroutine.
*/
- private void markSubroutineWalk(
- final BitSet sub,
- final int index,
- final BitSet anyvisited)
- {
+ private void markSubroutineWalk(final BitSet sub, final int index,
+ final BitSet anyvisited) {
if (LOGGING) {
log("markSubroutineWalk: sub=" + sub + " index=" + index);
}
@@ -220,7 +240,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
boolean loop = true;
while (loop) {
loop = false;
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+ for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+ .hasNext();) {
TryCatchBlockNode trycatch = it.next();
if (LOGGING) {
@@ -252,20 +273,19 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Performs a simple DFS of the instructions, assigning each to the
- * subroutine <code>sub</code>. Starts from <code>index</code>.
- * Invoked only by <code>markSubroutineWalk()</code>.
- *
- * @param sub the subroutine whose instructions must be computed.
- * @param index an instruction of this subroutine.
- * @param anyvisited indexes of the already visited instructions, i.e.
- * marked as part of this subroutine or any previously computed
- * subroutine.
+ * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only
+ * by <code>markSubroutineWalk()</code>.
+ *
+ * @param sub
+ * the subroutine whose instructions must be computed.
+ * @param index
+ * an instruction of this subroutine.
+ * @param anyvisited
+ * indexes of the already visited instructions, i.e. marked as
+ * part of this subroutine or any previously computed subroutine.
*/
- private void markSubroutineWalkDFS(
- final BitSet sub,
- int index,
- final BitSet anyvisited)
- {
+ private void markSubroutineWalkDFS(final BitSet sub, int index,
+ final BitSet anyvisited) {
while (true) {
AbstractInsnNode node = instructions.get(index);
@@ -285,8 +305,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
anyvisited.set(index);
if (node.getType() == AbstractInsnNode.JUMP_INSN
- && node.getOpcode() != JSR)
- {
+ && node.getOpcode() != JSR) {
// we do not follow recursively called subroutines here; but any
// other sort of branch we do follow
JumpInsnNode jnode = (JumpInsnNode) node;
@@ -317,27 +336,38 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
// check to see if this opcode falls through to the next instruction
// or not; if not, return.
switch (instructions.get(index).getOpcode()) {
- case GOTO:
- case RET:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case LRETURN:
- case FRETURN:
- case DRETURN:
- case ARETURN:
- case RETURN:
- case ATHROW:
- /*
- * note: this either returns from this subroutine, or a
- * parent subroutine which invoked it
- */
- return;
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ /*
+ * note: this either returns from this subroutine, or a parent
+ * subroutine which invoked it
+ */
+ return;
}
// Use tail recursion here in the form of an outer while loop to
// avoid our stack growing needlessly:
index++;
+
+ // We implicitly assumed above that execution can always fall
+ // through to the next instruction after a JSR. But a subroutine may
+ // never return, in which case the code after the JSR is unreachable
+ // and can be anything. In particular, it can seem to fall off the
+ // end of the method, so we must handle this case here (we could
+ // instead detect whether execution can return or not from a JSR,
+ // but this is more complicated).
+ if (index >= instructions.size()) {
+ return;
+ }
}
}
@@ -358,10 +388,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
while (!worklist.isEmpty()) {
Instantiation inst = worklist.removeFirst();
- emitSubroutine(inst,
- worklist,
- newInstructions,
- newTryCatchBlocks,
+ emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks,
newLocalVariables);
}
instructions = newInstructions;
@@ -371,24 +398,25 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Emits one instantiation of one subroutine, specified by
- * <code>instant</code>. May add new instantiations that are invoked by
- * this one to the <code>worklist</code> parameter, and new try/catch
- * blocks to <code>newTryCatchBlocks</code>.
- *
- * @param instant the instantiation that must be performed.
- * @param worklist list of the instantiations that remain to be done.
- * @param newInstructions the instruction list to which the instantiated
- * code must be appended.
- * @param newTryCatchBlocks the exception handler list to which the
- * instantiated handlers must be appended.
+ * <code>instant</code>. May add new instantiations that are invoked by this
+ * one to the <code>worklist</code> parameter, and new try/catch blocks to
+ * <code>newTryCatchBlocks</code>.
+ *
+ * @param instant
+ * the instantiation that must be performed.
+ * @param worklist
+ * list of the instantiations that remain to be done.
+ * @param newInstructions
+ * the instruction list to which the instantiated code must be
+ * appended.
+ * @param newTryCatchBlocks
+ * the exception handler list to which the instantiated handlers
+ * must be appended.
*/
- private void emitSubroutine(
- final Instantiation instant,
- final List<Instantiation> worklist,
- final InsnList newInstructions,
- final List<TryCatchBlockNode> newTryCatchBlocks,
- final List<LocalVariableNode> newLocalVariables)
- {
+ private void emitSubroutine(final Instantiation instant,
+ final List<Instantiation> worklist, final InsnList newInstructions,
+ final List<TryCatchBlockNode> newTryCatchBlocks,
+ final List<LocalVariableNode> newLocalVariables) {
LabelNode duplbl = null;
if (LOGGING) {
@@ -485,7 +513,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
}
// Emit try/catch blocks that are relevant to this method.
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+ for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+ .hasNext();) {
TryCatchBlockNode trycatch = it.next();
if (LOGGING) {
@@ -517,13 +546,12 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
throw new RuntimeException("Internal error!");
}
- newTryCatchBlocks.add(new TryCatchBlockNode(start,
- end,
- handler,
+ newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler,
trycatch.type));
}
- for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext();) {
+ for (Iterator<LocalVariableNode> it = localVariables.iterator(); it
+ .hasNext();) {
LocalVariableNode lvnode = it.next();
if (LOGGING) {
log("local var " + lvnode.name);
@@ -537,11 +565,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
continue;
}
newLocalVariables.add(new LocalVariableNode(lvnode.name,
- lvnode.desc,
- lvnode.signature,
- start,
- end,
- lvnode.index));
+ lvnode.desc, lvnode.signature, start, end, lvnode.index));
}
}
@@ -574,14 +598,14 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* This table maps Labels from the original source to Labels pointing at
* code specific to this instantiation, for use in remapping try/catch
* blocks,as well as gotos.
- *
+ *
* Note that in the presence of dual citizens instructions, that is,
* instructions which belong to more than one subroutine due to the
* merging of control flow without a RET instruction, we will map the
* target label of a GOTO to the label used by the instantiation lowest
* on the stack. This avoids code duplication during inlining in most
* cases.
- *
+ *
* @see #findOwner(int)
*/
public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>();
@@ -644,21 +668,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* Returns the "owner" of a particular instruction relative to this
* instantiation: the owner referes to the Instantiation which will emit
* the version of this instruction that we will execute.
- *
+ *
* Typically, the return value is either <code>this</code> or
* <code>null</code>. <code>this</code> indicates that this
* instantiation will generate the version of this instruction that we
- * will execute, and <code>null</code> indicates that this
- * instantiation never executes the given instruction.
- *
+ * will execute, and <code>null</code> indicates that this instantiation
+ * never executes the given instruction.
+ *
* Sometimes, however, an instruction can belong to multiple
* subroutines; this is called a "dual citizen" instruction (though it
* may belong to more than 2 subroutines), and occurs when multiple
* subroutines branch to common points of control. In this case, the
* owner is the subroutine that appears lowest on the stack, and which
* also owns the instruction in question.
- *
- * @param i the index of the instruction in the original code
+ *
+ * @param i
+ * the index of the instruction in the original code
* @return the "owner" of a particular instruction relative to this
* instantiation.
*/
@@ -679,12 +704,13 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
}
/**
- * Looks up the label <code>l</code> in the <code>gotoTable</code>,
- * thus translating it from a Label in the original code, to a Label in
- * the inlined code that is appropriate for use by an instruction that
+ * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus
+ * translating it from a Label in the original code, to a Label in the
+ * inlined code that is appropriate for use by an instruction that
* branched to the original label.
- *
- * @param l The label we will be translating
+ *
+ * @param l
+ * The label we will be translating
* @return a label for use by a branch instruction in the inlined code
* @see #rangeLabel
*/
@@ -700,8 +726,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* thus translating it from a Label in the original code, to a Label in
* the inlined code that is appropriate for use by an try/catch or
* variable use annotation.
- *
- * @param l The label we will be translating
+ *
+ * @param l
+ * The label we will be translating
* @return a label for use by a try/catch or variable annotation in the
* original code
* @see #rangeTable
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
new file mode 100644
index 0000000..3a21047
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
@@ -0,0 +1,381 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+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 MethodVisitor} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ *
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodVisitor {
+
+ private static final Type OBJECT_TYPE = Type
+ .getObjectType("java/lang/Object");
+
+ /**
+ * Mapping from old to new local variable indexes. A local variable at index
+ * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+ * index i of size 2 is remapped to 'mapping[2*i+1]'.
+ */
+ private int[] mapping = new int[40];
+
+ /**
+ * Array used to store stack map local variable types after remapping.
+ */
+ private Object[] newLocals = new Object[20];
+
+ /**
+ * Index of the first local variable, after formal parameters.
+ */
+ protected final int firstLocal;
+
+ /**
+ * Index of the next local variable to be created by {@link #newLocal}.
+ */
+ protected int nextLocal;
+
+ /**
+ * Indicates if at least one local variable has moved due to remapping.
+ */
+ private boolean changed;
+
+ /**
+ * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public LocalVariablesSorter(final int access, final String desc,
+ final MethodVisitor mv) {
+ this(Opcodes.ASM5, access, desc, mv);
+ if (getClass() != LocalVariablesSorter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link LocalVariablesSorter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * access flags of the adapted method.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ protected LocalVariablesSorter(final int api, final int access,
+ final String desc, final MethodVisitor mv) {
+ super(api, mv);
+ Type[] args = Type.getArgumentTypes(desc);
+ nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+ for (int i = 0; i < args.length; i++) {
+ nextLocal += args[i].getSize();
+ }
+ firstLocal = nextLocal;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ Type type;
+ switch (opcode) {
+ case Opcodes.LLOAD:
+ case Opcodes.LSTORE:
+ type = Type.LONG_TYPE;
+ break;
+
+ case Opcodes.DLOAD:
+ case Opcodes.DSTORE:
+ type = Type.DOUBLE_TYPE;
+ break;
+
+ case Opcodes.FLOAD:
+ case Opcodes.FSTORE:
+ type = Type.FLOAT_TYPE;
+ break;
+
+ case Opcodes.ILOAD:
+ case Opcodes.ISTORE:
+ type = Type.INT_TYPE;
+ break;
+
+ default:
+ // case Opcodes.ALOAD:
+ // case Opcodes.ASTORE:
+ // case RET:
+ type = OBJECT_TYPE;
+ break;
+ }
+ mv.visitVarInsn(opcode, remap(var, type));
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ mv.visitMaxs(maxStack, nextLocal);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ int newIndex = remap(index, Type.getType(desc));
+ mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ Type t = Type.getType(desc);
+ int[] newIndex = new int[index.length];
+ for (int i = 0; i < newIndex.length; ++i) {
+ newIndex[i] = remap(index[i], t);
+ }
+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ newIndex, desc, visible);
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // uncompressed frame
+ throw new IllegalStateException(
+ "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+ }
+
+ if (!changed) { // optimization for the case where mapping = identity
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ return;
+ }
+
+ // creates a copy of newLocals
+ Object[] oldLocals = new Object[newLocals.length];
+ System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+ updateNewLocals(newLocals);
+
+ // copies types from 'local' to 'newLocals'
+ // 'newLocals' already contains the variables added with 'newLocal'
+
+ int index = 0; // old local variable index
+ int number = 0; // old local variable number
+ for (; number < nLocal; ++number) {
+ Object t = local[number];
+ int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+ if (t != Opcodes.TOP) {
+ Type typ = OBJECT_TYPE;
+ if (t == Opcodes.INTEGER) {
+ typ = Type.INT_TYPE;
+ } else if (t == Opcodes.FLOAT) {
+ typ = Type.FLOAT_TYPE;
+ } else if (t == Opcodes.LONG) {
+ typ = Type.LONG_TYPE;
+ } else if (t == Opcodes.DOUBLE) {
+ typ = Type.DOUBLE_TYPE;
+ } else if (t instanceof String) {
+ typ = Type.getObjectType((String) t);
+ }
+ setFrameLocal(remap(index, typ), t);
+ }
+ index += size;
+ }
+
+ // removes TOP after long and double types as well as trailing TOPs
+
+ index = 0;
+ number = 0;
+ for (int i = 0; index < newLocals.length; ++i) {
+ Object t = newLocals[index++];
+ if (t != null && t != Opcodes.TOP) {
+ newLocals[i] = t;
+ number = i + 1;
+ if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+ index += 1;
+ }
+ } else {
+ newLocals[i] = Opcodes.TOP;
+ }
+ }
+
+ // visits remapped frame
+ mv.visitFrame(type, number, newLocals, nStack, stack);
+
+ // restores original value of 'newLocals'
+ newLocals = oldLocals;
+ }
+
+ // -------------
+
+ /**
+ * Creates a new local variable of the given type.
+ *
+ * @param type
+ * the type of the local variable to be created.
+ * @return the identifier of the newly created local variable.
+ */
+ public int newLocal(final Type type) {
+ Object t;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ t = Opcodes.INTEGER;
+ break;
+ case Type.FLOAT:
+ t = Opcodes.FLOAT;
+ break;
+ case Type.LONG:
+ t = Opcodes.LONG;
+ break;
+ case Type.DOUBLE:
+ t = Opcodes.DOUBLE;
+ break;
+ case Type.ARRAY:
+ t = type.getDescriptor();
+ break;
+ // case Type.OBJECT:
+ default:
+ t = type.getInternalName();
+ break;
+ }
+ int local = newLocalMapping(type);
+ setLocalType(local, type);
+ setFrameLocal(local, t);
+ changed = true;
+ return local;
+ }
+
+ /**
+ * Notifies subclasses that a new stack map frame is being visited. The
+ * array argument contains the stack map frame types corresponding to the
+ * local variables added with {@link #newLocal}. This method can update
+ * these types in place for the stack map frame being visited. The default
+ * implementation of this method does nothing, i.e. a local variable added
+ * with {@link #newLocal} will have the same type in all stack map frames.
+ * But this behavior is not always the desired one, for instance if a local
+ * variable is added in the middle of a try/catch block: the frame for the
+ * exception handler should have a TOP type for this new local.
+ *
+ * @param newLocals
+ * the stack map frame types corresponding to the local variables
+ * added with {@link #newLocal} (and null for the others). The
+ * format of this array is the same as in
+ * {@link MethodVisitor#visitFrame}, except that long and double
+ * types use two slots. The types for the current stack map frame
+ * must be updated in place in this array.
+ */
+ protected void updateNewLocals(Object[] newLocals) {
+ }
+
+ /**
+ * Notifies subclasses that a local variable has been added or remapped. The
+ * default implementation of this method does nothing.
+ *
+ * @param local
+ * a local variable identifier, as returned by {@link #newLocal
+ * newLocal()}.
+ * @param type
+ * the type of the value being stored in the local variable.
+ */
+ protected void setLocalType(final int local, final Type type) {
+ }
+
+ private void setFrameLocal(final int local, final Object type) {
+ int l = newLocals.length;
+ if (local >= l) {
+ Object[] a = new Object[Math.max(2 * l, local + 1)];
+ System.arraycopy(newLocals, 0, a, 0, l);
+ newLocals = a;
+ }
+ newLocals[local] = type;
+ }
+
+ private int remap(final int var, final Type type) {
+ if (var + type.getSize() <= firstLocal) {
+ return var;
+ }
+ int key = 2 * var + type.getSize() - 1;
+ int size = mapping.length;
+ if (key >= size) {
+ int[] newMapping = new int[Math.max(2 * size, key + 1)];
+ System.arraycopy(mapping, 0, newMapping, 0, size);
+ mapping = newMapping;
+ }
+ int value = mapping[key];
+ if (value == 0) {
+ value = newLocalMapping(type);
+ setLocalType(value, type);
+ mapping[key] = value + 1;
+ } else {
+ value--;
+ }
+ if (value != var) {
+ changed = true;
+ }
+ return value;
+ }
+
+ protected int newLocalMapping(final Type type) {
+ int local = nextLocal;
+ nextLocal += type.getSize();
+ return local;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
new file mode 100644
index 0000000..73c3e96
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
@@ -0,0 +1,282 @@
+/***
+ * 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.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A named method descriptor.
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+ /**
+ * The method name.
+ */
+ private final String name;
+
+ /**
+ * The method descriptor.
+ */
+ private final String desc;
+
+ /**
+ * Maps primitive Java type names to their descriptors.
+ */
+ private static final Map<String, String> DESCRIPTORS;
+
+ static {
+ DESCRIPTORS = new HashMap<String, String>();
+ DESCRIPTORS.put("void", "V");
+ DESCRIPTORS.put("byte", "B");
+ DESCRIPTORS.put("char", "C");
+ DESCRIPTORS.put("double", "D");
+ DESCRIPTORS.put("float", "F");
+ DESCRIPTORS.put("int", "I");
+ DESCRIPTORS.put("long", "J");
+ DESCRIPTORS.put("short", "S");
+ DESCRIPTORS.put("boolean", "Z");
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ */
+ public Method(final String name, final String desc) {
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param name
+ * the method's name.
+ * @param returnType
+ * the method's return type.
+ * @param argumentTypes
+ * the method's argument types.
+ */
+ public Method(final String name, final Type returnType,
+ final Type[] argumentTypes) {
+ this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param m
+ * a java.lang.reflect method descriptor
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ */
+ public static Method getMethod(java.lang.reflect.Method m) {
+ return new Method(m.getName(), Type.getMethodDescriptor(m));
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param c
+ * a java.lang.reflect constructor descriptor
+ * @return a {@link Method} corresponding to the given Java constructor
+ * declaration.
+ */
+ public static Method getMethod(java.lang.reflect.Constructor<?> c) {
+ return new Method("<init>", Type.getConstructorDescriptor(c));
+ }
+
+ /**
+ * Returns a {@link Method} corresponding to the given Java method
+ * declaration.
+ *
+ * @param method
+ * a Java method declaration, without argument names, of the form
+ * "returnType name (argumentType1, ... argumentTypeN)", where
+ * the types are in plain Java (e.g. "int", "float",
+ * "java.util.List", ...). Classes of the java.lang package can
+ * be specified by their unqualified name; all other classes
+ * names must be fully qualified.
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ * @throws IllegalArgumentException
+ * if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method)
+ throws IllegalArgumentException {
+ return getMethod(method, false);
+ }
+
+ /**
+ * Returns a {@link Method} corresponding to the given Java method
+ * declaration.
+ *
+ * @param method
+ * a Java method declaration, without argument names, of the form
+ * "returnType name (argumentType1, ... argumentTypeN)", where
+ * the types are in plain Java (e.g. "int", "float",
+ * "java.util.List", ...). Classes of the java.lang package may
+ * be specified by their unqualified name, depending on the
+ * defaultPackage argument; all other classes names must be fully
+ * qualified.
+ * @param defaultPackage
+ * true if unqualified class names belong to the default package,
+ * or false if they correspond to java.lang classes. For instance
+ * "Object" means "Object" if this option is true, or
+ * "java.lang.Object" otherwise.
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ * @throws IllegalArgumentException
+ * if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method,
+ final boolean defaultPackage) throws IllegalArgumentException {
+ int space = method.indexOf(' ');
+ int start = method.indexOf('(', space) + 1;
+ int end = method.indexOf(')', start);
+ if (space == -1 || start == -1 || end == -1) {
+ throw new IllegalArgumentException();
+ }
+ String returnType = method.substring(0, space);
+ String methodName = method.substring(space + 1, start - 1).trim();
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ int p;
+ do {
+ String s;
+ p = method.indexOf(',', start);
+ if (p == -1) {
+ s = map(method.substring(start, end).trim(), defaultPackage);
+ } else {
+ s = map(method.substring(start, p).trim(), defaultPackage);
+ start = p + 1;
+ }
+ sb.append(s);
+ } while (p != -1);
+ sb.append(')');
+ sb.append(map(returnType, defaultPackage));
+ return new Method(methodName, sb.toString());
+ }
+
+ private static String map(final String type, final boolean defaultPackage) {
+ if ("".equals(type)) {
+ return type;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ int index = 0;
+ while ((index = type.indexOf("[]", index) + 1) > 0) {
+ sb.append('[');
+ }
+
+ String t = type.substring(0, type.length() - sb.length() * 2);
+ String desc = DESCRIPTORS.get(t);
+ if (desc != null) {
+ sb.append(desc);
+ } else {
+ sb.append('L');
+ if (t.indexOf('.') < 0) {
+ if (!defaultPackage) {
+ sb.append("java/lang/");
+ }
+ sb.append(t);
+ } else {
+ sb.append(t.replace('.', '/'));
+ }
+ sb.append(';');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns the name of the method described by this object.
+ *
+ * @return the name of the method described by this object.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the descriptor of the method described by this object.
+ *
+ * @return the descriptor of the method described by this object.
+ */
+ public String getDescriptor() {
+ return desc;
+ }
+
+ /**
+ * Returns the return type of the method described by this object.
+ *
+ * @return the return type of the method described by this object.
+ */
+ public Type getReturnType() {
+ return Type.getReturnType(desc);
+ }
+
+ /**
+ * Returns the argument types of the method described by this object.
+ *
+ * @return the argument types of the method described by this object.
+ */
+ public Type[] getArgumentTypes() {
+ return Type.getArgumentTypes(desc);
+ }
+
+ @Override
+ public String toString() {
+ return name + desc;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Method)) {
+ return false;
+ }
+ Method other = (Method) o;
+ return name.equals(other.name) && desc.equals(other.desc);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode() ^ desc.hashCode();
+ }
+}
\ No newline at end of file
[09/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
index d2d461c..ce959df 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,22 +29,29 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+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 node that represents a method.
- *
+ *
* @author Eric Bruneton
*/
-public class MethodNode extends MethodVisitor
-{
+public class MethodNode extends MethodVisitor {
/**
- * The method's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also
+ * The method's access flags (see {@link Opcodes}). This field also
* indicates if the method is synthetic and/or deprecated.
*/
public int access;
@@ -56,7 +62,7 @@ public class MethodNode extends MethodVisitor
public String name;
/**
- * The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * The method's descriptor (see {@link Type}).
*/
public String desc;
@@ -67,16 +73,21 @@ public class MethodNode extends MethodVisitor
/**
* The internal names of the method's exception classes (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). This list is a list of
+ * {@link Type#getInternalName() getInternalName}). This list is a list of
* {@link String} objects.
*/
public List<String> exceptions;
/**
+ * The method parameter info (access flags and name)
+ */
+ public List<ParameterNode> parameters;
+
+ /**
* The runtime visible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -84,17 +95,35 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this method. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this method. This list is a
+ * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this method. This list is a list of
- * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
@@ -102,7 +131,7 @@ public class MethodNode extends MethodVisitor
* The default value of this annotation interface method. This field must be
* a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer}, {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an two elements String array (for
+ * {@link String} or {@link Type}, or an two elements String array (for
* enumeration values), a {@link AnnotationNode}, or a {@link List} of
* values of one of the preceding types. May be <tt>null</tt>.
*/
@@ -111,8 +140,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime visible parameter annotations of this method. These lists are
* lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible parameters
*/
public List<AnnotationNode>[] visibleParameterAnnotations;
@@ -120,8 +149,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible parameter annotations of this method. These lists
* are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible parameters
*/
public List<AnnotationNode>[] invisibleParameterAnnotations;
@@ -129,8 +158,8 @@ public class MethodNode extends MethodVisitor
/**
* The instructions of this method. This list is a list of
* {@link AbstractInsnNode} objects.
- *
- * @associates AbstractInsnNode
+ *
+ * @associates org.objectweb.asm.tree.AbstractInsnNode
* @label instructions
*/
public InsnList instructions;
@@ -138,8 +167,8 @@ public class MethodNode extends MethodVisitor
/**
* The try catch blocks of this method. This list is a list of
* {@link TryCatchBlockNode} objects.
- *
- * @associates TryCatchBlockNode
+ *
+ * @associates org.objectweb.asm.tree.TryCatchBlockNode
*/
public List<TryCatchBlockNode> tryCatchBlocks;
@@ -156,30 +185,53 @@ public class MethodNode extends MethodVisitor
/**
* The local variables of this method. This list is a list of
* {@link LocalVariableNode} objects. May be <tt>null</tt>
- *
- * @associates LocalVariableNode
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableNode
*/
public List<LocalVariableNode> localVariables;
/**
+ * The visible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
+
+ /**
+ * The invisible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
+
+ /**
* If the accept method has been called on this object.
*/
private boolean visited;
-
+
/**
* Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
* use this constructor</i>. Instead, they must use the
* {@link #MethodNode(int)} version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public MethodNode() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs an uninitialized {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodNode(final int api) {
super(api);
@@ -190,57 +242,61 @@ public class MethodNode extends MethodVisitor
* Constructs a new {@link MethodNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #MethodNode(int, int, String, String, String, String[])} version.
- *
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public MethodNode(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- this(Opcodes.ASM4, access, name, desc, signature, exceptions);
+ public MethodNode(final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ this(Opcodes.ASM5, access, name, desc, signature, exceptions);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- public MethodNode(
- final int api,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ public MethodNode(final int api, final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
super(api);
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
- this.exceptions = new ArrayList<String>(exceptions == null
- ? 0
+ this.exceptions = new ArrayList<String>(exceptions == null ? 0
: exceptions.length);
boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
if (!isAbstract) {
@@ -258,6 +314,14 @@ public class MethodNode extends MethodVisitor
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(String name, int access) {
+ if (parameters == null) {
+ parameters = new ArrayList<ParameterNode>(5);
+ }
+ parameters.add(new ParameterNode(name, access));
+ }
+
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
return new AnnotationNode(new ArrayList<Object>(0) {
@Override
@@ -269,10 +333,8 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -289,28 +351,45 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (visibleParameterAnnotations[parameter] == null) {
- visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
visibleParameterAnnotations[parameter].add(an);
} else {
if (invisibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (invisibleParameterAnnotations[parameter] == null) {
- invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
invisibleParameterAnnotations[parameter].add(an);
}
@@ -330,17 +409,10 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
- instructions.add(new FrameNode(type, nLocal, local == null
- ? null
- : getLabelNodes(local), nStack, stack == null
- ? null
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ instructions.add(new FrameNode(type, nLocal, local == null ? null
+ : getLabelNodes(local), nStack, stack == null ? null
: getLabelNodes(stack)));
}
@@ -365,32 +437,35 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
instructions.add(new FieldInsnNode(opcode, owner, name, desc));
}
+ @Deprecated
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
instructions.add(new MethodInsnNode(opcode, owner, name, desc));
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
}
@@ -415,26 +490,16 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
- instructions.add(new TableSwitchInsnNode(min,
- max,
- getLabelNode(dflt),
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
getLabelNodes(labels)));
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
- instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
- keys,
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
getLabelNodes(labels)));
}
@@ -444,33 +509,89 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ // Finds the last real instruction, i.e. the instruction targeted by
+ // this annotation.
+ AbstractInsnNode insn = instructions.getLast();
+ while (insn.getOpcode() == -1) {
+ insn = insn.getPrevious();
+ }
+ // Adds the annotation to this instruction.
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (insn.visibleTypeAnnotations == null) {
+ insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.visibleTypeAnnotations.add(an);
+ } else {
+ if (insn.invisibleTypeAnnotations == null) {
+ insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
- getLabelNode(end),
- getLabelNode(handler),
- type));
+ getLabelNode(end), getLabelNode(handler), type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (tcb.visibleTypeAnnotations == null) {
+ tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.visibleTypeAnnotations.add(an);
+ } else {
+ if (tcb.invisibleTypeAnnotations == null) {
+ tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.invisibleTypeAnnotations.add(an);
+ }
+ return an;
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
- localVariables.add(new LocalVariableNode(name,
- desc,
- signature,
- getLabelNode(start),
- getLabelNode(end),
- index));
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ localVariables.add(new LocalVariableNode(name, desc, signature,
+ getLabelNode(start), getLabelNode(end), index));
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
+ typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
+ index, desc);
+ if (visible) {
+ if (visibleLocalVariableAnnotations == null) {
+ visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ visibleLocalVariableAnnotations.add(an);
+ } else {
+ if (invisibleLocalVariableAnnotations == null) {
+ invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ invisibleLocalVariableAnnotations.add(an);
+ }
+ return an;
}
@Override
@@ -493,13 +614,14 @@ public class MethodNode extends MethodVisitor
* LabelNode if necessary. The default implementation of this method uses
* the {@link Label#info} field to store associations between labels and
* label nodes.
- *
- * @param l a Label.
+ *
+ * @param l
+ * a Label.
* @return the LabelNode corresponding to l.
*/
protected LabelNode getLabelNode(final Label l) {
if (!(l.info instanceof LabelNode)) {
- l.info = new LabelNode(l);
+ l.info = new LabelNode();
}
return (LabelNode) l.info;
}
@@ -533,25 +655,71 @@ public class MethodNode extends MethodVisitor
* version. This methods checks that this node, and all its nodes
* recursively, do not contain elements that were introduced in more recent
* versions of the ASM API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
+ for (int i = 0; i < n; ++i) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get(i);
+ if (tcb.visibleTypeAnnotations != null
+ && tcb.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (tcb.invisibleTypeAnnotations != null
+ && tcb.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
+ for (int i = 0; i < instructions.size(); ++i) {
+ AbstractInsnNode insn = instructions.get(i);
+ if (insn.visibleTypeAnnotations != null
+ && insn.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn.invisibleTypeAnnotations != null
+ && insn.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn instanceof MethodInsnNode) {
+ boolean itf = ((MethodInsnNode) insn).itf;
+ if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new RuntimeException();
+ }
+ }
+ }
+ if (visibleLocalVariableAnnotations != null
+ && visibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleLocalVariableAnnotations != null
+ && invisibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
}
/**
* Makes the given class visitor visit this method.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
String[] exceptions = new String[this.exceptions.size()];
this.exceptions.toArray(exceptions);
- MethodVisitor mv = cv.visitMethod(access,
- name,
- desc,
- signature,
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
exceptions);
if (mv != null) {
accept(mv);
@@ -560,12 +728,19 @@ public class MethodNode extends MethodVisitor
/**
* Makes the given method visitor visit this method.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- // visits the method attributes
+ // visits the method parameters
int i, j, n;
+ n = parameters == null ? 0 : parameters.size();
+ for (i = 0; i < n; i++) {
+ ParameterNode parameter = parameters.get(i);
+ mv.visitParameter(parameter.name, parameter.access);
+ }
+ // visits the method attributes
if (annotationDefault != null) {
AnnotationVisitor av = mv.visitAnnotationDefault();
AnnotationNode.accept(av, null, annotationDefault);
@@ -583,8 +758,20 @@ public class MethodNode extends MethodVisitor
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(mv.visitAnnotation(an.desc, false));
}
- n = visibleParameterAnnotations == null
- ? 0
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
+ n = visibleParameterAnnotations == null ? 0
: visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = visibleParameterAnnotations[i];
@@ -596,8 +783,7 @@ public class MethodNode extends MethodVisitor
an.accept(mv.visitParameterAnnotation(i, an.desc, true));
}
}
- n = invisibleParameterAnnotations == null
- ? 0
+ n = invisibleParameterAnnotations == null ? 0
: invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = invisibleParameterAnnotations[i];
@@ -622,6 +808,7 @@ public class MethodNode extends MethodVisitor
// visits try catch blocks
n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
for (i = 0; i < n; ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
tryCatchBlocks.get(i).accept(mv);
}
// visits instructions
@@ -631,6 +818,17 @@ public class MethodNode extends MethodVisitor
for (i = 0; i < n; ++i) {
localVariables.get(i).accept(mv);
}
+ // visits local variable annotations
+ n = visibleLocalVariableAnnotations == null ? 0
+ : visibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ visibleLocalVariableAnnotations.get(i).accept(mv, true);
+ }
+ n = invisibleLocalVariableAnnotations == null ? 0
+ : invisibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ invisibleLocalVariableAnnotations.get(i).accept(mv, false);
+ }
// visits maxs
mv.visitMaxs(maxStack, maxLocals);
visited = true;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
index d27837d..f0d2b6b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents a MULTIANEWARRAY instruction.
- *
+ *
* @author Eric Bruneton
*/
public class MultiANewArrayInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link MultiANewArrayInsnNode}.
- *
- * @param desc an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param dims number of dimensions of the array to allocate.
+ *
+ * @param desc
+ * an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
*/
public MultiANewArrayInsnNode(final String desc, final int dims) {
super(Opcodes.MULTIANEWARRAY);
@@ -71,11 +73,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitMultiANewArrayInsn(desc, dims);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MultiANewArrayInsnNode(desc, dims);
+ return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
}
}
\ 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/ParameterNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
new file mode 100644
index 0000000..d5435de
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
+/**
+ * A node that represents a parameter access and name.
+ *
+ * @author Remi Forax
+ */
+public class ParameterNode {
+ /**
+ * The parameter's name.
+ */
+ public String name;
+
+ /**
+ * The parameter's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
+ * <tt>ACC_MANDATED</tt>.
+ */
+ public int access;
+
+ /**
+ * Constructs a new {@link ParameterNode}.
+ *
+ * @param access
+ * The parameter's access flags. Valid values are
+ * <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
+ * <tt>ACC_MANDATED</tt> (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * @param name
+ * the parameter's name.
+ */
+ public ParameterNode(final String name, final int access) {
+ this.name = name;
+ this.access = access;
+ }
+
+ /**
+ * Makes the given visitor visit this parameter declaration.
+ *
+ * @param mv
+ * a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitParameter(name, access);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
index 17ad4ec..e9ef6f2 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
@@ -29,18 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a TABLESWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class TableSwitchInsnNode extends AbstractInsnNode {
@@ -68,19 +68,19 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TableSwitchInsnNode}.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>min + i</tt> key.
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
*/
- public TableSwitchInsnNode(
- final int min,
- final int max,
- final LabelNode dflt,
- final LabelNode... labels)
- {
+ public TableSwitchInsnNode(final int min, final int max,
+ final LabelNode dflt, final LabelNode... labels) {
super(Opcodes.TABLESWITCH);
this.min = min;
this.max = max;
@@ -103,13 +103,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TableSwitchInsnNode(min,
- max,
- clone(dflt, labels),
- clone(this.labels, labels));
+ return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
+ this.labels, labels)).cloneAnnotations(this);
}
}
\ 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/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
index 52ea45f..a4c8dde 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
@@ -29,11 +29,13 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a try catch block.
- *
+ *
* @author Eric Bruneton
*/
public class TryCatchBlockNode {
@@ -60,21 +62,41 @@ public class TryCatchBlockNode {
public String type;
/**
+ * The runtime visible type annotations on the exception handler type. This
+ * list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations on the exception handler type.
+ * This list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* Constructs a new {@link TryCatchBlockNode}.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for "finally"
- * blocks).
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
*/
- public TryCatchBlockNode(
- final LabelNode start,
- final LabelNode end,
- final LabelNode handler,
- final String type)
- {
+ public TryCatchBlockNode(final LabelNode start, final LabelNode end,
+ final LabelNode handler, final String type) {
this.start = start;
this.end = end;
this.handler = handler;
@@ -82,13 +104,50 @@ public class TryCatchBlockNode {
}
/**
+ * Updates the index of this try catch block in the method's list of try
+ * catch block nodes. This index maybe stored in the 'target' field of the
+ * type annotations of this block.
+ *
+ * @param index
+ * the new index of this try catch block in the method's list of
+ * try catch block nodes.
+ */
+ public void updateIndex(final int index) {
+ int newTypeRef = 0x42000000 | (index << 8);
+ if (visibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : visibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ }
+
+ /**
* Makes the given visitor visit this try catch block.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
- ? null
- : handler.getLabel(), type);
+ mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
+ handler == null ? null : handler.getLabel(), type);
+ int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, false));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
new file mode 100644
index 0000000..66ec2d3
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotationn.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeAnnotationNode extends AnnotationNode {
+
+ /**
+ * A reference to the annotated type. See {@link TypeReference}.
+ */
+ public int typeRef;
+
+ /**
+ * The path to the annotated type argument, wildcard bound, array element
+ * type, or static outer type within the referenced type. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ */
+ public TypePath typePath;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public TypeAnnotationNode(final int typeRef, final TypePath typePath,
+ final String desc) {
+ this(Opcodes.ASM5, typeRef, typePath, desc);
+ if (getClass() != TypeAnnotationNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public TypeAnnotationNode(final int api, final int typeRef,
+ final TypePath typePath, final String desc) {
+ super(api, desc);
+ this.typeRef = typeRef;
+ this.typePath = typePath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
index e5bc30e..b4572e5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a type instruction. A type instruction is an
* instruction that takes a type descriptor as parameter.
- *
+ *
* @author Eric Bruneton
*/
public class TypeInsnNode extends AbstractInsnNode {
@@ -49,11 +49,13 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TypeInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param desc the operand of the instruction to be constructed. This
- * operand is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param desc
+ * the operand of the instruction to be constructed. This operand
+ * is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
*/
public TypeInsnNode(final int opcode, final String desc) {
super(opcode);
@@ -62,9 +64,10 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be NEW,
- * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -78,10 +81,11 @@ public class TypeInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitTypeInsn(opcode, desc);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TypeInsnNode(opcode, desc);
+ return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
}
}
\ 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/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
index 3819d31..58552de 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
@@ -1,6 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
-` * Copyright (c) 2000-2011 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,15 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a local variable instruction. A local variable
* instruction is an instruction that loads or stores the value of a local
* variable.
- *
+ *
* @author Eric Bruneton
*/
public class VarInsnNode extends AbstractInsnNode {
@@ -50,12 +50,14 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link VarInsnNode}.
- *
- * @param opcode the opcode of the local variable instruction to be
- * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
- * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be constructed. This operand
- * is the index of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be
+ * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be constructed. This operand
+ * is the index of a local variable.
*/
public VarInsnNode(final int opcode, final int var) {
super(opcode);
@@ -64,10 +66,11 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be ILOAD,
- * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
- * or RET.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be ILOAD, LLOAD,
+ * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
+ * RET.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -81,10 +84,11 @@ public class VarInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitVarInsn(opcode, var);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new VarInsnNode(opcode, var);
+ return new VarInsnNode(opcode, var).cloneAnnotations(this);
}
}
\ 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/Analyzer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..a78fff4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+ private final Interpreter<V> interpreter;
+
+ private int n;
+
+ private InsnList insns;
+
+ private List<TryCatchBlockNode>[] handlers;
+
+ private Frame<V>[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter
+ * the interpreter to be used to symbolically interpret the
+ * bytecode instructions.
+ */
+ public Analyzer(final Interpreter<V> interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException
+ * if a problem occurs during the analysis.
+ */
+ public Frame<V>[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException {
+ if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = (Frame<V>[]) new Frame<?>[0];
+ return frames;
+ }
+ n = m.instructions.size();
+ insns = m.instructions;
+ handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
+ frames = (Frame<V>[]) new Frame<?>[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+ int begin = insns.indexOf(tcb.start);
+ int end = insns.indexOf(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List<TryCatchBlockNode> insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList<TryCatchBlockNode>();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // computes the subroutine for each instruction:
+ Subroutine main = new Subroutine(null, m.maxLocals, null);
+ List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+ Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+ findSubroutine(0, main, subroutineCalls);
+ while (!subroutineCalls.isEmpty()) {
+ JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+ Subroutine sub = subroutineHeads.get(jsr.label);
+ if (sub == null) {
+ sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+ subroutineHeads.put(jsr.label, sub);
+ findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ } else {
+ sub.callers.add(jsr);
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+ Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+ current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getObjectType(owner);
+ current.setLocal(local++, interpreter.newValue(ctype));
+ }
+ for (int i = 0; i < args.length; ++i) {
+ current.setLocal(local++, interpreter.newValue(args[i]));
+ if (args[i].getSize() == 2) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ }
+ while (local < m.maxLocals) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ merge(0, current, null);
+
+ init(owner, m);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame<V> f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ AbstractInsnNode insnNode = null;
+ try {
+ insnNode = m.instructions.get(insn);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME) {
+ merge(insn + 1, f, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ } else {
+ current.init(f).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : subroutine.copy();
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode j = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ int jump = insns.indexOf(j.label);
+ if (insnOpcode == JSR) {
+ merge(jump, current, new Subroutine(j.label,
+ m.maxLocals, j));
+ } else {
+ merge(jump, current, subroutine);
+ }
+ newControlFlowEdge(insn, jump);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(lsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ LabelNode label = lsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(tsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ LabelNode label = tsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException(insnNode,
+ "RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ int call = insns.indexOf(caller);
+ if (frames[call] != null) {
+ merge(call + 1, frames[call], current,
+ subroutines[call], subroutine.access);
+ newControlFlowEdge(insn, call + 1);
+ }
+ }
+ } else if (insnOpcode != ATHROW
+ && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ if (insnOpcode == LLOAD || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE) {
+ subroutine.access[var + 1] = true;
+ }
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ }
+ }
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ }
+
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getObjectType("java/lang/Throwable");
+ } else {
+ type = Type.getObjectType(tcb.type);
+ }
+ int jump = insns.indexOf(tcb.handler);
+ if (newControlFlowExceptionEdge(insn, tcb)) {
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(jump, handler, subroutine);
+ }
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException(e.node, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw new AnalyzerException(insnNode, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ private void findSubroutine(int insn, final Subroutine sub,
+ final List<AbstractInsnNode> calls) throws AnalyzerException {
+ while (true) {
+ if (insn < 0 || insn >= n) {
+ throw new AnalyzerException(null,
+ "Execution can fall off end of the code");
+ }
+ if (subroutines[insn] != null) {
+ return;
+ }
+ subroutines[insn] = sub.copy();
+ AbstractInsnNode node = insns.get(insn);
+
+ // calls findSubroutine recursively on normal successors
+ if (node instanceof JumpInsnNode) {
+ if (node.getOpcode() == JSR) {
+ // do not follow a JSR, it leads to another subroutine!
+ calls.add(node);
+ } else {
+ JumpInsnNode jnode = (JumpInsnNode) node;
+ findSubroutine(insns.indexOf(jnode.label), sub, calls);
+ }
+ } else if (node instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+ for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = tsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ } else if (node instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+ for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = lsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ }
+
+ // calls findSubroutine recursively on exception handler successors
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+ }
+ }
+
+ // if insn does not falls through to the next instruction, return.
+ switch (node.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ return;
+ }
+ insn++;
+ }
+ }
+
+ /**
+ * Returns the symbolic stack frame for each instruction of the last
+ * recently analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if the corresponding instruction
+ * cannot be reached, or if an error occured during the analysis of
+ * the method.
+ */
+ public Frame<V>[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insn
+ * the index of an instruction of the last recently analyzed
+ * method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List<TryCatchBlockNode> getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * Initializes this analyzer. This method is called just before the
+ * execution of control flow analysis loop in #analyze. The default
+ * implementation of this method does nothing.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @throws AnalyzerException
+ * if a problem occurs.
+ */
+ protected void init(String owner, MethodNode m) throws AnalyzerException {
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals
+ * the maximum number of local variables of the frame.
+ * @param nStack
+ * the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final int nLocals, final int nStack) {
+ return new Frame<V>(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src
+ * a frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final Frame<? extends V> src) {
+ return new Frame<V>(src);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this
+ * method does nothing. It can be overriden in order to construct the
+ * control flow graph of a method (this method is called by the
+ * {@link #analyze analyze} method during its visit of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insn, final int successor) {
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method does nothing. It can be
+ * overridden in order to construct the control flow graph of a method (this
+ * method is called by the {@link #analyze analyze} method during its visit
+ * of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method always returns true.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final int successor) {
+ return true;
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+ * construct the control flow graph of a method (this method is called by
+ * the {@link #analyze analyze} method during its visit of the method's
+ * code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param tcb
+ * TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final TryCatchBlockNode tcb) {
+ return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(final int insn, final Frame<V> frame,
+ final Subroutine subroutine) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(frame, interpreter);
+ }
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(final int insn, final Frame<V> beforeJSR,
+ final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(afterRET, interpreter);
+ }
+
+ if (oldSubroutine != null && subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR);
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..66c9df9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,61 @@
+/***
+ * 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 org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public final AbstractInsnNode node;
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg) {
+ super(msg);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Throwable exception) {
+ super(msg, exception);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Object expected, final Value encountered) {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ this.node = node;
+ }
+}
[23/23] git commit: 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?"
Posted by ka...@apache.org.
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?"
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/a0ac605d
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/a0ac605d
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/a0ac605d
Branch: refs/heads/5.3
Commit: a0ac605dbd89f543b0396d747f5909e1ba38205b
Parents: 1a03c56
Author: kaosko <ka...@apache.org>
Authored: Tue Mar 25 11:29:43 2014 -0700
Committer: kaosko <ka...@apache.org>
Committed: Tue Mar 25 11:29:43 2014 -0700
----------------------------------------------------------------------
plastic/LICENSE-ASM-3_3_1.txt | 29 -
plastic/LICENSE-ASM-5_0.txt | 29 +
plastic/NOTICE.txt | 4 +-
.../internal/plastic/asm/AnnotationVisitor.java | 82 +-
.../internal/plastic/asm/AnnotationWriter.java | 123 +-
.../internal/plastic/asm/Attribute.java | 213 +-
.../internal/plastic/asm/ByteVector.java | 168 +-
.../internal/plastic/asm/ClassReader.java | 3350 ++++++++++--------
.../internal/plastic/asm/ClassVisitor.java | 291 +-
.../internal/plastic/asm/ClassWriter.java | 694 ++--
.../tapestry5/internal/plastic/asm/Context.java | 145 +
.../tapestry5/internal/plastic/asm/Edge.java | 2 +-
.../internal/plastic/asm/FieldVisitor.java | 75 +-
.../internal/plastic/asm/FieldWriter.java | 138 +-
.../tapestry5/internal/plastic/asm/Frame.java | 1087 +++---
.../tapestry5/internal/plastic/asm/Handle.java | 65 +-
.../tapestry5/internal/plastic/asm/Handler.java | 13 +-
.../tapestry5/internal/plastic/asm/Item.java | 188 +-
.../tapestry5/internal/plastic/asm/Label.java | 169 +-
.../internal/plastic/asm/MethodVisitor.java | 808 +++--
.../internal/plastic/asm/MethodWriter.java | 1535 ++++----
.../tapestry5/internal/plastic/asm/Opcodes.java | 9 +-
.../tapestry5/internal/plastic/asm/Type.java | 333 +-
.../internal/plastic/asm/TypePath.java | 193 +
.../internal/plastic/asm/TypeReference.java | 452 +++
.../plastic/asm/commons/AdviceAdapter.java | 646 ++++
.../plastic/asm/commons/AnalyzerAdapter.java | 947 +++++
.../plastic/asm/commons/CodeSizeEvaluator.java | 238 ++
.../plastic/asm/commons/GeneratorAdapter.java | 1628 +++++++++
.../plastic/asm/commons/InstructionAdapter.java | 1170 ++++++
.../plastic/asm/commons/JSRInlinerAdapter.java | 333 +-
.../asm/commons/LocalVariablesSorter.java | 381 ++
.../internal/plastic/asm/commons/Method.java | 282 ++
.../internal/plastic/asm/commons/Remapper.java | 223 ++
.../asm/commons/RemappingAnnotationAdapter.java | 79 +
.../asm/commons/RemappingClassAdapter.java | 135 +
.../asm/commons/RemappingFieldAdapter.java | 71 +
.../asm/commons/RemappingMethodAdapter.java | 224 ++
.../asm/commons/RemappingSignatureAdapter.java | 155 +
.../asm/commons/SerialVersionUIDAdder.java | 540 +++
.../plastic/asm/commons/SimpleRemapper.java | 69 +
.../plastic/asm/commons/StaticInitMerger.java | 97 +
.../asm/commons/TableSwitchGenerator.java | 57 +
.../asm/commons/TryCatchBlockSorter.java | 96 +
.../internal/plastic/asm/commons/package.html | 48 +
.../optimizer/AnnotationConstantsCollector.java | 147 +
.../asm/optimizer/ClassConstantsCollector.java | 198 ++
.../plastic/asm/optimizer/ClassOptimizer.java | 260 ++
.../plastic/asm/optimizer/Constant.java | 323 ++
.../plastic/asm/optimizer/ConstantPool.java | 249 ++
.../asm/optimizer/FieldConstantsCollector.java | 89 +
.../plastic/asm/optimizer/JarOptimizer.java | 235 ++
.../asm/optimizer/MethodConstantsCollector.java | 224 ++
.../plastic/asm/optimizer/MethodOptimizer.java | 136 +
.../plastic/asm/optimizer/NameMapping.java | 114 +
.../plastic/asm/optimizer/Shrinker.java | 283 ++
.../plastic/asm/optimizer/jdk1.2.2_017.txt.gz | Bin 0 -> 113814 bytes
.../plastic/asm/optimizer/jdk1.3.1_19.txt.gz | Bin 0 -> 128067 bytes
.../asm/optimizer/shrink-annotations.properties | 53 +
.../asm/optimizer/shrink-frames.properties | 62 +
.../asm/optimizer/shrink-resize.properties | 37 +
.../asm/optimizer/shrink-signatures.properties | 43 +
.../asm/optimizer/shrink-writer.properties | 66 +
.../plastic/asm/optimizer/shrink.properties | 380 ++
.../plastic/asm/signature/SignatureReader.java | 191 +-
.../plastic/asm/signature/SignatureVisitor.java | 88 +-
.../plastic/asm/signature/SignatureWriter.java | 6 +-
.../plastic/asm/tree/AbstractInsnNode.java | 132 +-
.../plastic/asm/tree/AnnotationNode.java | 72 +-
.../internal/plastic/asm/tree/ClassNode.java | 199 +-
.../plastic/asm/tree/FieldInsnNode.java | 48 +-
.../internal/plastic/asm/tree/FieldNode.java | 198 +-
.../internal/plastic/asm/tree/FrameNode.java | 141 +-
.../internal/plastic/asm/tree/IincInsnNode.java | 17 +-
.../plastic/asm/tree/InnerClassNode.java | 46 +-
.../internal/plastic/asm/tree/InsnList.java | 184 +-
.../internal/plastic/asm/tree/InsnNode.java | 46 +-
.../internal/plastic/asm/tree/IntInsnNode.java | 26 +-
.../plastic/asm/tree/InvokeDynamicInsnNode.java | 32 +-
.../internal/plastic/asm/tree/JumpInsnNode.java | 39 +-
.../internal/plastic/asm/tree/LabelNode.java | 4 +-
.../internal/plastic/asm/tree/LdcInsnNode.java | 18 +-
.../plastic/asm/tree/LineNumberNode.java | 16 +-
.../asm/tree/LocalVariableAnnotationNode.java | 157 +
.../plastic/asm/tree/LocalVariableNode.java | 51 +-
.../plastic/asm/tree/LookupSwitchInsnNode.java | 36 +-
.../plastic/asm/tree/MethodInsnNode.java | 77 +-
.../internal/plastic/asm/tree/MethodNode.java | 542 ++-
.../asm/tree/MultiANewArrayInsnNode.java | 17 +-
.../plastic/asm/tree/ParameterNode.java | 76 +
.../plastic/asm/tree/TableSwitchInsnNode.java | 41 +-
.../plastic/asm/tree/TryCatchBlockNode.java | 97 +-
.../plastic/asm/tree/TypeAnnotationNode.java | 100 +
.../internal/plastic/asm/tree/TypeInsnNode.java | 28 +-
.../internal/plastic/asm/tree/VarInsnNode.java | 34 +-
.../plastic/asm/tree/analysis/Analyzer.java | 549 +++
.../asm/tree/analysis/AnalyzerException.java | 61 +
.../asm/tree/analysis/BasicInterpreter.java | 358 ++
.../plastic/asm/tree/analysis/BasicValue.java | 111 +
.../asm/tree/analysis/BasicVerifier.java | 433 +++
.../plastic/asm/tree/analysis/Frame.java | 738 ++++
.../plastic/asm/tree/analysis/Interpreter.java | 226 ++
.../asm/tree/analysis/SimpleVerifier.java | 320 ++
.../plastic/asm/tree/analysis/SmallSet.java | 134 +
.../asm/tree/analysis/SourceInterpreter.java | 198 ++
.../plastic/asm/tree/analysis/SourceValue.java | 97 +
.../plastic/asm/tree/analysis/Subroutine.java | 90 +
.../plastic/asm/tree/analysis/Value.java | 45 +
.../plastic/asm/tree/analysis/package.html | 67 +
.../internal/plastic/asm/util/ASMifiable.java | 19 +-
.../internal/plastic/asm/util/ASMifier.java | 1285 +++++++
.../asm/util/CheckAnnotationAdapter.java | 136 +
.../plastic/asm/util/CheckClassAdapter.java | 1009 ++++++
.../plastic/asm/util/CheckFieldAdapter.java | 122 +
.../plastic/asm/util/CheckMethodAdapter.java | 1542 ++++++++
.../plastic/asm/util/CheckSignatureAdapter.java | 330 ++
.../internal/plastic/asm/util/Printer.java | 421 ++-
.../internal/plastic/asm/util/Textifiable.java | 16 +-
.../internal/plastic/asm/util/Textifier.java | 732 ++--
.../asm/util/TraceAnnotationVisitor.java | 32 +-
.../plastic/asm/util/TraceClassVisitor.java | 158 +-
.../plastic/asm/util/TraceFieldVisitor.java | 27 +-
.../plastic/asm/util/TraceMethodVisitor.java | 172 +-
.../plastic/asm/util/TraceSignatureVisitor.java | 70 +-
.../plastic/asm/xml/ASMContentHandler.java | 1453 ++++++++
.../internal/plastic/asm/xml/Processor.java | 1044 ++++++
.../internal/plastic/asm/xml/SAXAdapter.java | 89 +
.../plastic/asm/xml/SAXAnnotationAdapter.java | 242 ++
.../plastic/asm/xml/SAXClassAdapter.java | 335 ++
.../plastic/asm/xml/SAXCodeAdapter.java | 415 +++
.../plastic/asm/xml/SAXFieldAdapter.java | 71 +
.../internal/plastic/asm/xml/asm-xml.dtd | 349 ++
.../internal/plastic/asm/xml/package.html | 96 +
133 files changed, 31009 insertions(+), 5855 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-3_3_1.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-3_3_1.txt b/plastic/LICENSE-ASM-3_3_1.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-3_3_1.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
new file mode 100644
index 0000000..c5aba7b
--- /dev/null
+++ b/plastic/LICENSE-ASM-5_0.txt
@@ -0,0 +1,29 @@
+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.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plastic/NOTICE.txt b/plastic/NOTICE.txt
index 96158f5..beec8e0 100644
--- a/plastic/NOTICE.txt
+++ b/plastic/NOTICE.txt
@@ -1,6 +1,6 @@
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
-This product imports and repackages ASM 3.3.1 code which is
-released under the BSD License
+This product imports and repackages ASM 5.0.1 code which is
+released under a BSD style License
http://asm.ow2.org/license.html
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
index 693b355..1102d54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* A visitor to visit a Java annotation. The methods of this class must be
* called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
* <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -53,9 +53,10 @@ public abstract class AnnotationVisitor {
/**
* Constructs a new {@link AnnotationVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
@@ -63,31 +64,36 @@ public abstract class AnnotationVisitor {
/**
* Constructs a new {@link AnnotationVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param av the annotation visitor to which this visitor must delegate
- * method calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param av
+ * the annotation visitor to which this visitor must delegate
+ * method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.av = av;
}
/**
* Visits a primitive value of the annotation.
- *
- * @param name the value name.
- * @param value the actual value, whose type must be {@link Byte},
- * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
- * , {@link Long}, {@link Float}, {@link Double}, {@link String} or
- * {@link Type} or OBJECT or ARRAY sort. This value can also be an
- * array of byte, boolean, short, char, int, long, float or double
- * values (this is equivalent to using {@link #visitArray visitArray}
- * and visiting each array element in turn, but is more convenient).
+ *
+ * @param name
+ * the value name.
+ * @param value
+ * the actual value, whose type must be {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+ * value can also be an array of byte, boolean, short, char, int,
+ * long, float or double values (this is equivalent to using
+ * {@link #visitArray visitArray} and visiting each array element
+ * in turn, but is more convenient).
*/
public void visit(String name, Object value) {
if (av != null) {
@@ -97,10 +103,13 @@ public abstract class AnnotationVisitor {
/**
* Visits an enumeration value of the annotation.
- *
- * @param name the value name.
- * @param desc the class descriptor of the enumeration class.
- * @param value the actual enumeration value.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the enumeration class.
+ * @param value
+ * the actual enumeration value.
*/
public void visitEnum(String name, String desc, String value) {
if (av != null) {
@@ -110,13 +119,15 @@ public abstract class AnnotationVisitor {
/**
* Visits a nested annotation value of the annotation.
- *
- * @param name the value name.
- * @param desc the class descriptor of the nested annotation class.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the nested annotation class.
* @return a visitor to visit the actual nested annotation value, or
- * <tt>null</tt> if this visitor is not interested in visiting
- * this nested annotation. <i>The nested annotation value must be
- * fully visited before calling other methods on this annotation
+ * <tt>null</tt> if this visitor is not interested in visiting this
+ * nested annotation. <i>The nested annotation value must be fully
+ * visited before calling other methods on this annotation
* visitor</i>.
*/
public AnnotationVisitor visitAnnotation(String name, String desc) {
@@ -131,11 +142,12 @@ public abstract class AnnotationVisitor {
* types (such as byte, boolean, short, char, int, long, float or double)
* can be passed as value to {@link #visit visit}. This is what
* {@link ClassReader} does.
- *
- * @param name the value name.
+ *
+ * @param name
+ * the value name.
* @return a visitor to visit the actual array value elements, or
- * <tt>null</tt> if this visitor is not interested in visiting
- * these values. The 'name' parameters passed to the methods of this
+ * <tt>null</tt> if this visitor is not interested in visiting these
+ * values. The 'name' parameters passed to the methods of this
* visitor are ignored. <i>All the array values must be visited
* before calling other methods on this annotation visitor</i>.
*/
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
index a26f5ca..679aa66 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -89,22 +89,22 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Constructs a new {@link AnnotationWriter}.
- *
- * @param cw the class writer to which this annotation must be added.
- * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
- * @param bv where the annotation values must be stored.
- * @param parent where the number of annotation values must be stored.
- * @param offset where in <tt>parent</tt> the number of annotation values must
- * be stored.
+ *
+ * @param cw
+ * the class writer to which this annotation must be added.
+ * @param named
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+ * @param bv
+ * where the annotation values must be stored.
+ * @param parent
+ * where the number of annotation values must be stored.
+ * @param offset
+ * where in <tt>parent</tt> the number of annotation values must
+ * be stored.
*/
- AnnotationWriter(
- final ClassWriter cw,
- final boolean named,
- final ByteVector bv,
- final ByteVector parent,
- final int offset)
- {
- super(Opcodes.ASM4);
+ AnnotationWriter(final ClassWriter cw, final boolean named,
+ final ByteVector bv, final ByteVector parent, final int offset) {
+ super(Opcodes.ASM5);
this.cw = cw;
this.named = named;
this.bv = bv;
@@ -190,11 +190,8 @@ final class AnnotationWriter extends AnnotationVisitor {
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
@@ -203,10 +200,8 @@ final class AnnotationWriter extends AnnotationVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
@@ -242,7 +237,7 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Returns the size of this annotation writer list.
- *
+ *
* @return the size of this annotation writer list.
*/
int getSize() {
@@ -258,8 +253,9 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Puts the annotations of this annotation writer list into the given byte
* vector.
- *
- * @param out where the annotations must be put.
+ *
+ * @param out
+ * where the annotations must be put.
*/
void put(final ByteVector out) {
int n = 0;
@@ -285,16 +281,16 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Puts the given annotation lists into the given byte vector.
- *
- * @param panns an array of annotation writer lists.
- * @param off index of the first annotation to be written.
- * @param out where the annotations must be put.
+ *
+ * @param panns
+ * an array of annotation writer lists.
+ * @param off
+ * index of the first annotation to be written.
+ * @param out
+ * where the annotations must be put.
*/
- static void put(
- final AnnotationWriter[] panns,
- final int off,
- final ByteVector out)
- {
+ static void put(final AnnotationWriter[] panns, final int off,
+ final ByteVector out) {
int size = 1 + 2 * (panns.length - off);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
@@ -319,4 +315,57 @@ final class AnnotationWriter extends AnnotationVisitor {
}
}
}
+
+ /**
+ * Puts the given type reference and type path into the given bytevector.
+ * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param out
+ * where the type reference and type path must be put.
+ */
+ static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
+ switch (typeRef >>> 24) {
+ case 0x00: // CLASS_TYPE_PARAMETER
+ case 0x01: // METHOD_TYPE_PARAMETER
+ case 0x16: // METHOD_FORMAL_PARAMETER
+ out.putShort(typeRef >>> 16);
+ break;
+ case 0x13: // FIELD
+ case 0x14: // METHOD_RETURN
+ case 0x15: // METHOD_RECEIVER
+ out.putByte(typeRef >>> 24);
+ break;
+ case 0x47: // CAST
+ case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+ case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+ out.putInt(typeRef);
+ break;
+ // case 0x10: // CLASS_EXTENDS
+ // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+ // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+ // case 0x17: // THROWS
+ // case 0x42: // EXCEPTION_PARAMETER
+ // case 0x43: // INSTANCEOF
+ // case 0x44: // NEW
+ // case 0x45: // CONSTRUCTOR_REFERENCE
+ // case 0x46: // METHOD_REFERENCE
+ default:
+ out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
+ break;
+ }
+ if (typePath == null) {
+ out.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ out.putByteArray(typePath.b, typePath.offset, length);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
index 8f29872..fae580f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A non standard class, field, method or code attribute.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -54,8 +54,9 @@ public class Attribute {
/**
* Constructs a new empty attribute.
- *
- * @param type the type of the attribute.
+ *
+ * @param type
+ * the type of the attribute.
*/
protected Attribute(final String type) {
this.type = type;
@@ -64,7 +65,7 @@ public class Attribute {
/**
* Returns <tt>true</tt> if this type of attribute is unknown. The default
* implementation of this method always returns <tt>true</tt>.
- *
+ *
* @return <tt>true</tt> if this type of attribute is unknown.
*/
public boolean isUnknown() {
@@ -73,7 +74,7 @@ public class Attribute {
/**
* Returns <tt>true</tt> if this type of attribute is a code attribute.
- *
+ *
* @return <tt>true</tt> if this type of attribute is a code attribute.
*/
public boolean isCodeAttribute() {
@@ -82,7 +83,7 @@ public class Attribute {
/**
* Returns the labels corresponding to this attribute.
- *
+ *
* @return the labels corresponding to this attribute, or <tt>null</tt> if
* this attribute is not a code attribute that contains labels.
*/
@@ -91,39 +92,39 @@ public class Attribute {
}
/**
- * Reads a {@link #type type} attribute. This method must return a <i>new</i>
- * {@link Attribute} object, of type {@link #type type}, corresponding to
- * the <tt>len</tt> bytes starting at the given offset, in the given class
- * reader.
- *
- * @param cr the class that contains the attribute to be read.
- * @param off index of the first byte of the attribute's content in {@link
- * ClassReader#b cr.b}. The 6 attribute header bytes, containing the
- * type and the length of the attribute, are not taken into account
- * here.
- * @param len the length of the attribute's content.
- * @param buf buffer to be used to call
- * {@link ClassReader#readUTF8 readUTF8},
- * {@link ClassReader#readClass(int,char[]) readClass} or
- * {@link ClassReader#readConst readConst}.
- * @param codeOff index of the first byte of code's attribute content in
- * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
- * not a code attribute. The 6 attribute header bytes, containing the
- * type and the length of the attribute, are not taken into account
- * here.
- * @param labels the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
+ * Reads a {@link #type type} attribute. This method must return a
+ * <i>new</i> {@link Attribute} object, of type {@link #type type},
+ * corresponding to the <tt>len</tt> bytes starting at the given offset, in
+ * the given class reader.
+ *
+ * @param cr
+ * the class that contains the attribute to be read.
+ * @param off
+ * index of the first byte of the attribute's content in
+ * {@link ClassReader#b cr.b}. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param len
+ * the length of the attribute's content.
+ * @param buf
+ * buffer to be used to call {@link ClassReader#readUTF8
+ * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
+ * or {@link ClassReader#readConst readConst}.
+ * @param codeOff
+ * index of the first byte of code's attribute content in
+ * {@link ClassReader#b cr.b}, or -1 if the attribute to be read
+ * is not a code attribute. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param labels
+ * the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
- protected Attribute read(
- final ClassReader cr,
- final int off,
- final int len,
- final char[] buf,
- final int codeOff,
- final Label[] labels)
- {
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
Attribute attr = new Attribute(type);
attr.value = new byte[len];
System.arraycopy(cr.b, off, attr.value, 0, len);
@@ -132,31 +133,31 @@ public class Attribute {
/**
* Returns the byte array form of this attribute.
- *
- * @param cw the class to which this attribute must be added. This parameter
- * can be used to add to the constant pool of this class the items
- * that corresponds to this attribute.
- * @param code the bytecode of the method corresponding to this code
- * attribute, or <tt>null</tt> if this attribute is not a code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to this
- * code attribute, or <tt>null</tt> if this attribute is not a code
- * attribute.
- * @param maxStack the maximum stack size of the method corresponding to
- * this code attribute, or -1 if this attribute is not a code
- * attribute.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to this code attribute, or -1 if this attribute is
- * not a code attribute.
+ *
+ * @param cw
+ * the class to which this attribute must be added. This
+ * parameter can be used to add to the constant pool of this
+ * class the items that corresponds to this attribute.
+ * @param code
+ * the bytecode of the method corresponding to this code
+ * attribute, or <tt>null</tt> if this attribute is not a code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to this
+ * code attribute, or <tt>null</tt> if this attribute is not a
+ * code attribute.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to this
+ * code attribute, or -1 if this attribute is not a code
+ * attribute.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to this code attribute, or -1 if this attribute
+ * is not a code attribute.
* @return the byte array form of this attribute.
*/
- protected ByteVector write(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals)
- {
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
ByteVector v = new ByteVector();
v.data = value;
v.length = value.length;
@@ -165,7 +166,7 @@ public class Attribute {
/**
* Returns the length of the attribute list that begins with this attribute.
- *
+ *
* @return the length of the attribute list that begins with this attribute.
*/
final int getCount() {
@@ -180,31 +181,31 @@ public class Attribute {
/**
* Returns the size of all the attributes in this attribute list.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes are
- * not code attributes.
- * @param maxStack the maximum stack size of the method corresponding to
- * these code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes
- * are not code attributes.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
* @return the size of all the attributes in this attribute list. This size
* includes the size of the attribute headers.
*/
- final int getSize(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals)
- {
+ final int getSize(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals) {
Attribute attr = this;
int size = 0;
while (attr != null) {
@@ -218,31 +219,31 @@ public class Attribute {
/**
* Writes all the attributes of this attribute list in the given byte
* vector.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes are
- * not code attributes.
- * @param maxStack the maximum stack size of the method corresponding to
- * these code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes
- * are not code attributes.
- * @param out where the attributes must be written.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
+ * @param out
+ * where the attributes must be written.
*/
- final void put(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals,
- final ByteVector out)
- {
+ final void put(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals, final ByteVector out) {
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
index e689d87..24506f9 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A dynamically extensible vector of bytes. This class is roughly equivalent to
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
+ *
* @author Eric Bruneton
*/
public class ByteVector {
@@ -58,8 +58,9 @@ public class ByteVector {
/**
* Constructs a new {@link ByteVector ByteVector} with the given initial
* size.
- *
- * @param initialSize the initial size of the byte vector to be constructed.
+ *
+ * @param initialSize
+ * the initial size of the byte vector to be constructed.
*/
public ByteVector(final int initialSize) {
data = new byte[initialSize];
@@ -68,8 +69,9 @@ public class ByteVector {
/**
* Puts a byte into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param b a byte.
+ *
+ * @param b
+ * a byte.
* @return this byte vector.
*/
public ByteVector putByte(final int b) {
@@ -85,9 +87,11 @@ public class ByteVector {
/**
* Puts two bytes into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param b1 a byte.
- * @param b2 another byte.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
* @return this byte vector.
*/
ByteVector put11(final int b1, final int b2) {
@@ -105,8 +109,9 @@ public class ByteVector {
/**
* Puts a short into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param s a short.
+ *
+ * @param s
+ * a short.
* @return this byte vector.
*/
public ByteVector putShort(final int s) {
@@ -124,9 +129,11 @@ public class ByteVector {
/**
* Puts a byte and a short into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param b a byte.
- * @param s a short.
+ *
+ * @param b
+ * a byte.
+ * @param s
+ * a short.
* @return this byte vector.
*/
ByteVector put12(final int b, final int s) {
@@ -145,8 +152,9 @@ public class ByteVector {
/**
* Puts an int into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param i an int.
+ *
+ * @param i
+ * an int.
* @return this byte vector.
*/
public ByteVector putInt(final int i) {
@@ -166,8 +174,9 @@ public class ByteVector {
/**
* Puts a long into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param l a long.
+ *
+ * @param l
+ * a long.
* @return this byte vector.
*/
public ByteVector putLong(final long l) {
@@ -193,12 +202,16 @@ public class ByteVector {
/**
* Puts an UTF8 string into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param s a String.
+ *
+ * @param s
+ * a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
+ if (charLength > 65535) {
+ throw new IllegalArgumentException();
+ }
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
@@ -217,38 +230,68 @@ public class ByteVector {
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
- int byteLength = i;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- data[length] = (byte) (byteLength >>> 8);
- data[length + 1] = (byte) byteLength;
- if (length + 2 + byteLength > data.length) {
- length = len;
- enlarge(2 + byteLength);
- data = this.data;
- }
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else if (c > '\u07FF') {
- data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
- data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- } else {
- data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- }
- }
- break;
+ length = len;
+ return encodeUTF8(s, i, 65535);
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary. The string length is encoded in two
+ * bytes before the encoded characters, if there is space for that (i.e. if
+ * this.length - i - 2 >= 0).
+ *
+ * @param s
+ * the String to encode.
+ * @param i
+ * the index of the first character to encode. The previous
+ * characters are supposed to have already been encoded, using
+ * only one byte per character.
+ * @param maxByteLength
+ * the maximum byte length of the encoded string, including the
+ * already encoded characters.
+ * @return this byte vector.
+ */
+ ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+ int charLength = s.length();
+ int byteLength = i;
+ char c;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ if (byteLength > maxByteLength) {
+ throw new IllegalArgumentException();
+ }
+ int start = length - i - 2;
+ if (start >= 0) {
+ data[start] = (byte) (byteLength >>> 8);
+ data[start + 1] = (byte) byteLength;
+ }
+ if (length + byteLength - i > data.length) {
+ enlarge(byteLength - i);
+ }
+ int len = length;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
@@ -258,15 +301,17 @@ public class ByteVector {
/**
* Puts an array of bytes into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
- * null bytes into this byte vector.
- * @param off index of the fist byte of b that must be copied.
- * @param len number of bytes of b that must be copied.
+ *
+ * @param b
+ * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+ * null bytes into this byte vector.
+ * @param off
+ * index of the fist byte of b that must be copied.
+ * @param len
+ * number of bytes of b that must be copied.
* @return this byte vector.
*/
- public ByteVector putByteArray(final byte[] b, final int off, final int len)
- {
+ public ByteVector putByteArray(final byte[] b, final int off, final int len) {
if (length + len > data.length) {
enlarge(len);
}
@@ -279,9 +324,10 @@ public class ByteVector {
/**
* Enlarge this byte vector so that it can receive n more bytes.
- *
- * @param size number of additional bytes that this byte vector should be
- * able to receive.
+ *
+ * @param size
+ * number of additional bytes that this byte vector should be
+ * able to receive.
*/
private void enlarge(final int size) {
int length1 = 2 * data.length;
[08/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..0656c65
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,358 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+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.IntInsnNode;
+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;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+ Opcodes {
+
+ public BasicInterpreter() {
+ super(ASM5);
+ }
+
+ protected BasicInterpreter(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue newOperation(final AbstractInsnNode insn)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(Type.getObjectType("null"));
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ if (cst instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (cst instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (cst instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (cst instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (cst instanceof String) {
+ return newValue(Type.getObjectType("java/lang/String"));
+ } else if (cst instanceof Type) {
+ int sort = ((Type) cst).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ return newValue(Type.getObjectType("java/lang/Class"));
+ } else if (sort == Type.METHOD) {
+ return newValue(Type
+ .getObjectType("java/lang/invoke/MethodType"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant "
+ + cst);
+ }
+ } else if (cst instanceof Handle) {
+ return newValue(Type
+ .getObjectType("java/lang/invoke/MethodHandle"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant "
+ + cst);
+ }
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ throw new AnalyzerException(insn, "Invalid array type");
+ }
+ case ANEWARRAY:
+ String desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getType("[" + Type.getObjectType(desc)));
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getObjectType(desc));
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue binaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ return BasicValue.REFERENCE_VALUE;
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException {
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn,
+ final List<? extends BasicValue> values) throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else if (opcode == INVOKEDYNAMIC) {
+ return newValue(Type
+ .getReturnType(((InvokeDynamicInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+ }
+ }
+
+ @Override
+ public void returnOperation(final AbstractInsnNode insn,
+ final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..44b0704
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,111 @@
+/***
+ * 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 org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ *
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+ public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+ public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ public static final BasicValue DOUBLE_VALUE = new BasicValue(
+ Type.DOUBLE_TYPE);
+
+ public static final BasicValue REFERENCE_VALUE = new BasicValue(
+ Type.getObjectType("java/lang/Object"));
+
+ public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
+ Type.VOID_TYPE);
+
+ private final Type type;
+
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ public boolean isReference() {
+ return type != null
+ && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..50f4a84
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,433 @@
+/***
+ * 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.List;
+
+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.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+ public BasicVerifier() {
+ super(ASM5);
+ }
+
+ protected BasicVerifier(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return value;
+ case ASTORE:
+ if (!value.isReference()
+ && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+ throw new AnalyzerException(insn, null,
+ "an object reference or a return address", value);
+ }
+ return value;
+ default:
+ return value;
+ }
+ if (!expected.equals(value)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ BasicValue expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type
+ .getObjectType(((FieldInsnNode) insn).owner));
+ break;
+ case CHECKCAST:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(insn, null, "an array reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return super.unaryOperation(insn, value);
+ }
+
+ @Override
+ public BasicValue binaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fin = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getObjectType(fin.owner));
+ expected2 = newValue(Type.getType(fin.desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", expected1,
+ value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException(insn, "Second argument", expected2,
+ value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", "a "
+ + expected1 + " array reference", value1);
+ } else if (!BasicValue.INT_VALUE.equals(value2)) {
+ throw new AnalyzerException(insn, "Second argument",
+ BasicValue.INT_VALUE, value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException(insn, "Third argument", expected3,
+ value3);
+ }
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn,
+ final List<? extends BasicValue> values) throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (int i = 0; i < values.size(); ++i) {
+ if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+ throw new AnalyzerException(insn, null,
+ BasicValue.INT_VALUE, values.get(i));
+ }
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+ Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+ if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+ throw new AnalyzerException(insn, "Method owner",
+ newValue(owner), values.get(0));
+ }
+ }
+ String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+ : ((MethodInsnNode) insn).desc;
+ Type[] args = Type.getArgumentTypes(desc);
+ while (i < values.size()) {
+ BasicValue expected = newValue(args[j++]);
+ BasicValue encountered = values.get(i++);
+ if (!isSubTypeOf(encountered, expected)) {
+ throw new AnalyzerException(insn, "Argument " + j,
+ expected, encountered);
+ }
+ }
+ }
+ return super.naryOperation(insn, values);
+ }
+
+ @Override
+ public void returnOperation(final AbstractInsnNode insn,
+ final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, "Incompatible return type",
+ expected, value);
+ }
+ }
+
+ protected boolean isArrayValue(final BasicValue value) {
+ return value.isReference();
+ }
+
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ protected boolean isSubTypeOf(final BasicValue value,
+ final BasicValue expected) {
+ return value.equals(expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000..fdbb0a9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
@@ -0,0 +1,738 @@
+/***
+ * 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.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.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in
+ * the operand stack.
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Frame<V extends Value> {
+
+ /**
+ * The expected return type of the analyzed method, or <tt>null</tt> if the
+ * method returns void.
+ */
+ private V returnValue;
+
+ /**
+ * The local variables and operand stack of this frame.
+ */
+ private V[] values;
+
+ /**
+ * The number of local variables of this frame.
+ */
+ private int locals;
+
+ /**
+ * The number of elements in the operand stack.
+ */
+ private int top;
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals
+ * the maximum number of local variables of the frame.
+ * @param nStack
+ * the maximum stack size of the frame.
+ */
+ public Frame(final int nLocals, final int nStack) {
+ this.values = (V[]) new Value[nLocals + nStack];
+ this.locals = nLocals;
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src
+ * a frame.
+ */
+ public Frame(final Frame<? extends V> src) {
+ this(src.locals, src.values.length - src.locals);
+ init(src);
+ }
+
+ /**
+ * Copies the state of the given frame into this frame.
+ *
+ * @param src
+ * a frame.
+ * @return this frame.
+ */
+ public Frame<V> init(final Frame<? extends V> src) {
+ returnValue = src.returnValue;
+ System.arraycopy(src.values, 0, values, 0, values.length);
+ top = src.top;
+ return this;
+ }
+
+ /**
+ * Sets the expected return type of the analyzed method.
+ *
+ * @param v
+ * the expected return type of the analyzed method, or
+ * <tt>null</tt> if the method returns void.
+ */
+ public void setReturn(final V v) {
+ returnValue = v;
+ }
+
+ /**
+ * Returns the maximum number of local variables of this frame.
+ *
+ * @return the maximum number of local variables of this frame.
+ */
+ public int getLocals() {
+ return locals;
+ }
+
+ /**
+ * Returns the maximum stack size of this frame.
+ *
+ * @return the maximum stack size of this frame.
+ */
+ public int getMaxStackSize() {
+ return values.length - locals;
+ }
+
+ /**
+ * Returns the value of the given local variable.
+ *
+ * @param i
+ * a local variable index.
+ * @return the value of the given local variable.
+ * @throws IndexOutOfBoundsException
+ * if the variable does not exist.
+ */
+ public V getLocal(final int i) throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException(
+ "Trying to access an inexistant local variable");
+ }
+ return values[i];
+ }
+
+ /**
+ * Sets the value of the given local variable.
+ *
+ * @param i
+ * a local variable index.
+ * @param value
+ * the new value of this local variable.
+ * @throws IndexOutOfBoundsException
+ * if the variable does not exist.
+ */
+ public void setLocal(final int i, final V value)
+ throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException(
+ "Trying to access an inexistant local variable " + i);
+ }
+ values[i] = value;
+ }
+
+ /**
+ * Returns the number of values in the operand stack of this frame. Long and
+ * double values are treated as single values.
+ *
+ * @return the number of values in the operand stack of this frame.
+ */
+ public int getStackSize() {
+ return top;
+ }
+
+ /**
+ * Returns the value of the given operand stack slot.
+ *
+ * @param i
+ * the index of an operand stack slot.
+ * @return the value of the given operand stack slot.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack slot does not exist.
+ */
+ public V getStack(final int i) throws IndexOutOfBoundsException {
+ return values[i + locals];
+ }
+
+ /**
+ * Clears the operand stack of this frame.
+ */
+ public void clearStack() {
+ top = 0;
+ }
+
+ /**
+ * Pops a value from the operand stack of this frame.
+ *
+ * @return the value that has been popped from the stack.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack is empty.
+ */
+ public V pop() throws IndexOutOfBoundsException {
+ if (top == 0) {
+ throw new IndexOutOfBoundsException(
+ "Cannot pop operand off an empty stack.");
+ }
+ return values[--top + locals];
+ }
+
+ /**
+ * Pushes a value into the operand stack of this frame.
+ *
+ * @param value
+ * the value that must be pushed into the stack.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack is full.
+ */
+ public void push(final V value) throws IndexOutOfBoundsException {
+ if (top + locals >= values.length) {
+ throw new IndexOutOfBoundsException(
+ "Insufficient maximum stack size.");
+ }
+ values[top++ + locals] = value;
+ }
+
+ public void execute(final AbstractInsnNode insn,
+ final Interpreter<V> interpreter) throws AnalyzerException {
+ V value1, value2, value3, value4;
+ List<V> values;
+ int var;
+
+ switch (insn.getOpcode()) {
+ case Opcodes.NOP:
+ break;
+ case Opcodes.ACONST_NULL:
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.LDC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.LLOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.DLOAD:
+ case Opcodes.ALOAD:
+ push(interpreter.copyOperation(insn,
+ getLocal(((VarInsnNode) insn).var)));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.LALOAD:
+ case Opcodes.FALOAD:
+ case Opcodes.DALOAD:
+ case Opcodes.AALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.LSTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.DSTORE:
+ case Opcodes.ASTORE:
+ value1 = interpreter.copyOperation(insn, pop());
+ var = ((VarInsnNode) insn).var;
+ setLocal(var, value1);
+ if (value1.getSize() == 2) {
+ setLocal(var + 1, interpreter.newValue(null));
+ }
+ if (var > 0) {
+ Value local = getLocal(var - 1);
+ if (local != null && local.getSize() == 2) {
+ setLocal(var - 1, interpreter.newValue(null));
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.LASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.DASTORE:
+ case Opcodes.AASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ value3 = pop();
+ value2 = pop();
+ value1 = pop();
+ interpreter.ternaryOperation(insn, value1, value2, value3);
+ break;
+ case Opcodes.POP:
+ if (pop().getSize() == 2) {
+ throw new AnalyzerException(insn, "Illegal use of POP");
+ }
+ break;
+ case Opcodes.POP2:
+ if (pop().getSize() == 1) {
+ if (pop().getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of POP2");
+ }
+ }
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ if (value1.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP");
+ }
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+ case Opcodes.DUP2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(value2);
+ push(value1);
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2");
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ value4 = pop();
+ if (value4.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value4);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+ case Opcodes.SWAP:
+ value2 = pop();
+ value1 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of SWAP");
+ }
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.IADD:
+ case Opcodes.LADD:
+ case Opcodes.FADD:
+ case Opcodes.DADD:
+ case Opcodes.ISUB:
+ case Opcodes.LSUB:
+ case Opcodes.FSUB:
+ case Opcodes.DSUB:
+ case Opcodes.IMUL:
+ case Opcodes.LMUL:
+ case Opcodes.FMUL:
+ case Opcodes.DMUL:
+ case Opcodes.IDIV:
+ case Opcodes.LDIV:
+ case Opcodes.FDIV:
+ case Opcodes.DDIV:
+ case Opcodes.IREM:
+ case Opcodes.LREM:
+ case Opcodes.FREM:
+ case Opcodes.DREM:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ISHL:
+ case Opcodes.LSHL:
+ case Opcodes.ISHR:
+ case Opcodes.LSHR:
+ case Opcodes.IUSHR:
+ case Opcodes.LUSHR:
+ case Opcodes.IAND:
+ case Opcodes.LAND:
+ case Opcodes.IOR:
+ case Opcodes.LOR:
+ case Opcodes.IXOR:
+ case Opcodes.LXOR:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IINC:
+ var = ((IincInsnNode) insn).var;
+ setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+ break;
+ case Opcodes.I2L:
+ case Opcodes.I2F:
+ case Opcodes.I2D:
+ case Opcodes.L2I:
+ case Opcodes.L2F:
+ case Opcodes.L2D:
+ case Opcodes.F2I:
+ case Opcodes.F2L:
+ case Opcodes.F2D:
+ case Opcodes.D2I:
+ case Opcodes.D2L:
+ case Opcodes.D2F:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.GOTO:
+ break;
+ case Opcodes.JSR:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.RET:
+ break;
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ value1 = pop();
+ interpreter.unaryOperation(insn, value1);
+ interpreter.returnOperation(insn, value1, returnValue);
+ break;
+ case Opcodes.RETURN:
+ if (returnValue != null) {
+ throw new AnalyzerException(insn, "Incompatible return type");
+ }
+ break;
+ case Opcodes.GETSTATIC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.PUTSTATIC:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.GETFIELD:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.PUTFIELD:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE: {
+ values = new ArrayList<V>();
+ String desc = ((MethodInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.INVOKEDYNAMIC: {
+ values = new ArrayList<V>();
+ String desc = ((InvokeDynamicInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.NEW:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.NEWARRAY:
+ case Opcodes.ANEWARRAY:
+ case Opcodes.ARRAYLENGTH:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ATHROW:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.CHECKCAST:
+ case Opcodes.INSTANCEOF:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ values = new ArrayList<V>();
+ for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+ values.add(0, pop());
+ }
+ push(interpreter.naryOperation(insn, values));
+ break;
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ default:
+ throw new RuntimeException("Illegal opcode " + insn.getOpcode());
+ }
+ }
+
+ /**
+ * Merges this frame with the given frame.
+ *
+ * @param frame
+ * a frame.
+ * @param interpreter
+ * the interpreter used to merge values.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ * @throws AnalyzerException
+ * if the frames have incompatible sizes.
+ */
+ public boolean merge(final Frame<? extends V> frame,
+ final Interpreter<V> interpreter) throws AnalyzerException {
+ if (top != frame.top) {
+ throw new AnalyzerException(null, "Incompatible stack heights");
+ }
+ boolean changes = false;
+ for (int i = 0; i < locals + top; ++i) {
+ V v = interpreter.merge(values[i], frame.values[i]);
+ if (!v.equals(values[i])) {
+ values[i] = v;
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Merges this frame with the given frame (case of a RET instruction).
+ *
+ * @param frame
+ * a frame
+ * @param access
+ * the local variables that have been accessed by the subroutine
+ * to which the RET instruction corresponds.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ */
+ public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
+ boolean changes = false;
+ for (int i = 0; i < locals; ++i) {
+ if (!access[i] && !values[i].equals(frame.values[i])) {
+ values[i] = frame.values[i];
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Returns a string representation of this frame.
+ *
+ * @return a string representation of this frame.
+ */
+ @Override
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < getLocals(); ++i) {
+ b.append(getLocal(i));
+ }
+ b.append(' ');
+ for (int i = 0; i < getStackSize(); ++i) {
+ b.append(getStack(i).toString());
+ }
+ return b.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000..b7c94c8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,226 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class Interpreter<V extends Value> {
+
+ protected final int api;
+
+ protected Interpreter(final int api) {
+ this.api = api;
+ }
+
+ /**
+ * Creates a new value that represents the given type.
+ *
+ * Called for method parameters (including <code>this</code>), exception
+ * handler variable and with <code>null</code> type for variables reserved
+ * by long and double types.
+ *
+ * @param type
+ * a primitive or reference type, or <tt>null</tt> to represent
+ * an uninitialized value.
+ * @return a value that represents the given type. The size of the returned
+ * value must be equal to the size of the given type.
+ */
+ public abstract V newValue(Type type);
+
+ /**
+ * Interprets a bytecode instruction without arguments. This method is
+ * called for the following opcodes:
+ *
+ * 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, JSR, GETSTATIC, NEW
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V newOperation(AbstractInsnNode insn)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction that moves a value on the stack or to
+ * or from local variables. This method is called for the following opcodes:
+ *
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+ * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the value that must be moved by the instruction.
+ * @return the result of the interpretation of the given instruction. The
+ * returned value must be <tt>equal</tt> to the given value.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V copyOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a single argument. This method is
+ * called for the following opcodes:
+ *
+ * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+ * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+ * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+ * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+ * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V unaryOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with two arguments. This method is
+ * called for the following opcodes:
+ *
+ * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+ * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+ * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value1
+ * the first argument of the instruction to be interpreted.
+ * @param value2
+ * the second argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with three arguments. This method is
+ * called for the following opcodes:
+ *
+ * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value1
+ * the first argument of the instruction to be interpreted.
+ * @param value2
+ * the second argument of the instruction to be interpreted.
+ * @param value3
+ * the third argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
+ V value2, V value3) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a variable number of arguments.
+ * This method is called for the following opcodes:
+ *
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+ * MULTIANEWARRAY and INVOKEDYNAMIC
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param values
+ * the arguments of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V naryOperation(AbstractInsnNode insn,
+ List<? extends V> values) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode return instruction. This method is called for the
+ * following opcodes:
+ *
+ * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the argument of the instruction to be interpreted.
+ * @param expected
+ * the expected return type of the analyzed method.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract void returnOperation(AbstractInsnNode insn, V value,
+ V expected) throws AnalyzerException;
+
+ /**
+ * Merges two values. The merge operation must return a value that
+ * represents both values (for instance, if the two values are two types,
+ * the merged value must be a common super type of the two types. If the two
+ * values are integer intervals, the merged value must be an interval that
+ * contains the previous ones. Likewise for other types of values).
+ *
+ * @param v
+ * a value.
+ * @param w
+ * another value.
+ * @return the merged value. If the merged value is equal to <tt>v</tt>,
+ * this method <i>must</i> return <tt>v</tt>.
+ */
+ public abstract V merge(V v, V w);
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000..c53beb4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,320 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+ /**
+ * The class that is verified.
+ */
+ private final Type currentClass;
+
+ /**
+ * The super class of the class that is verified.
+ */
+ private final Type currentSuperClass;
+
+ /**
+ * The interfaces implemented by the class that is verified.
+ */
+ private final List<Type> currentClassInterfaces;
+
+ /**
+ * If the class that is verified is an interface.
+ */
+ private final boolean isInterface;
+
+ /**
+ * The loader to use for referenced classes.
+ */
+ private ClassLoader loader = getClass().getClassLoader();
+
+ /**
+ * Constructs a new {@link SimpleVerifier}.
+ */
+ public SimpleVerifier() {
+ this(null, null, false);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass
+ * the class that is verified.
+ * @param currentSuperClass
+ * the super class of the class that is verified.
+ * @param isInterface
+ * if the class that is verified is an interface.
+ */
+ public SimpleVerifier(final Type currentClass,
+ final Type currentSuperClass, final boolean isInterface) {
+ this(currentClass, currentSuperClass, null, isInterface);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass
+ * the class that is verified.
+ * @param currentSuperClass
+ * the super class of the class that is verified.
+ * @param currentClassInterfaces
+ * the interfaces implemented by the class that is verified.
+ * @param isInterface
+ * if the class that is verified is an interface.
+ */
+ public SimpleVerifier(final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces, final boolean isInterface) {
+ this(ASM5, currentClass, currentSuperClass, currentClassInterfaces,
+ isInterface);
+ }
+
+ protected SimpleVerifier(final int api, final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces, final boolean isInterface) {
+ super(api);
+ this.currentClass = currentClass;
+ this.currentSuperClass = currentSuperClass;
+ this.currentClassInterfaces = currentClassInterfaces;
+ this.isInterface = isInterface;
+ }
+
+ /**
+ * Set the <code>ClassLoader</code> which will be used to load referenced
+ * classes. This is useful if you are verifying multiple interdependent
+ * classes.
+ *
+ * @param loader
+ * a <code>ClassLoader</code> to use
+ */
+ public void setClassLoader(final ClassLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+
+ boolean isArray = type.getSort() == Type.ARRAY;
+ if (isArray) {
+ switch (type.getElementType().getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ return new BasicValue(type);
+ }
+ }
+
+ BasicValue v = super.newValue(type);
+ if (BasicValue.REFERENCE_VALUE.equals(v)) {
+ if (isArray) {
+ v = newValue(type.getElementType());
+ String desc = v.getType().getDescriptor();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ desc = '[' + desc;
+ }
+ v = new BasicValue(Type.getType(desc));
+ } else {
+ v = new BasicValue(type);
+ }
+ }
+ return v;
+ }
+
+ @Override
+ protected boolean isArrayValue(final BasicValue value) {
+ Type t = value.getType();
+ return t != null
+ && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException {
+ Type arrayType = objectArrayValue.getType();
+ if (arrayType != null) {
+ if (arrayType.getSort() == Type.ARRAY) {
+ return newValue(Type.getType(arrayType.getDescriptor()
+ .substring(1)));
+ } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+ return objectArrayValue;
+ }
+ }
+ throw new Error("Internal error");
+ }
+
+ @Override
+ protected boolean isSubTypeOf(final BasicValue value,
+ final BasicValue expected) {
+ Type expectedType = expected.getType();
+ Type type = value.getType();
+ switch (expectedType.getSort()) {
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return type.equals(expectedType);
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if ("Lnull;".equals(type.getDescriptor())) {
+ return true;
+ } else if (type.getSort() == Type.OBJECT
+ || type.getSort() == Type.ARRAY) {
+ return isAssignableFrom(expectedType, type);
+ } else {
+ return false;
+ }
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ Type t = v.getType();
+ Type u = w.getType();
+ if (t != null
+ && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
+ if (u != null
+ && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
+ if ("Lnull;".equals(t.getDescriptor())) {
+ return w;
+ }
+ if ("Lnull;".equals(u.getDescriptor())) {
+ return v;
+ }
+ if (isAssignableFrom(t, u)) {
+ return v;
+ }
+ if (isAssignableFrom(u, t)) {
+ return w;
+ }
+ // TODO case of array classes of the same dimension
+ // TODO should we look also for a common super interface?
+ // problem: there may be several possible common super
+ // interfaces
+ do {
+ if (t == null || isInterface(t)) {
+ return BasicValue.REFERENCE_VALUE;
+ }
+ t = getSuperClass(t);
+ if (isAssignableFrom(t, u)) {
+ return newValue(t);
+ }
+ } while (true);
+ }
+ }
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+
+ protected boolean isInterface(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return isInterface;
+ }
+ return getClass(t).isInterface();
+ }
+
+ protected Type getSuperClass(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return currentSuperClass;
+ }
+ Class<?> c = getClass(t).getSuperclass();
+ return c == null ? null : Type.getType(c);
+ }
+
+ protected boolean isAssignableFrom(final Type t, final Type u) {
+ if (t.equals(u)) {
+ return true;
+ }
+ if (currentClass != null && t.equals(currentClass)) {
+ if (getSuperClass(u) == null) {
+ return false;
+ } else {
+ if (isInterface) {
+ return u.getSort() == Type.OBJECT
+ || u.getSort() == Type.ARRAY;
+ }
+ return isAssignableFrom(t, getSuperClass(u));
+ }
+ }
+ if (currentClass != null && u.equals(currentClass)) {
+ if (isAssignableFrom(t, currentSuperClass)) {
+ return true;
+ }
+ if (currentClassInterfaces != null) {
+ for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+ Type v = currentClassInterfaces.get(i);
+ if (isAssignableFrom(t, v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ Class<?> tc = getClass(t);
+ if (tc.isInterface()) {
+ tc = Object.class;
+ }
+ return tc.isAssignableFrom(getClass(u));
+ }
+
+ protected Class<?> getClass(final Type t) {
+ try {
+ if (t.getSort() == Type.ARRAY) {
+ return Class.forName(t.getDescriptor().replace('/', '.'),
+ false, loader);
+ }
+ return Class.forName(t.getClassName(), false, loader);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000..2aacb42
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,134 @@
+/***
+ * 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.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ *
+ * @author Eric Bruneton
+ */
+class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+
+ // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+ E e1, e2;
+
+ static final <T> Set<T> emptySet() {
+ return new SmallSet<T>(null, null);
+ }
+
+ SmallSet(final E e1, final E e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of inherited abstract methods
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Iterator<E> iterator() {
+ return new SmallSet<E>(e1, e2);
+ }
+
+ @Override
+ public int size() {
+ return e1 == null ? 0 : (e2 == null ? 1 : 2);
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of the Iterator interface
+ // -------------------------------------------------------------------------
+
+ public boolean hasNext() {
+ return e1 != null;
+ }
+
+ public E next() {
+ if (e1 == null) {
+ throw new NoSuchElementException();
+ }
+ E e = e1;
+ e1 = e2;
+ e2 = null;
+ return e;
+ }
+
+ public void remove() {
+ }
+
+ // -------------------------------------------------------------------------
+ // Utility methods
+ // -------------------------------------------------------------------------
+
+ Set<E> union(final SmallSet<E> s) {
+ if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+ return this; // if the two sets are equal, return this
+ }
+ if (s.e1 == null) {
+ return this; // if s is empty, return this
+ }
+ if (e1 == null) {
+ return s; // if this is empty, return s
+ }
+ if (s.e2 == null) { // s contains exactly one element
+ if (e2 == null) {
+ return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
+ } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+ return this;
+ }
+ }
+ if (e2 == null) { // this contains exactly one element
+ // if (s.e2 == null) { // cannot happen
+ // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+ // } else
+ if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+ return s;
+ }
+ }
+ // here we know that there are at least 3 distinct elements
+ HashSet<E> r = new HashSet<E>(4);
+ r.add(e1);
+ if (e2 != null) {
+ r.add(e2);
+ }
+ r.add(s.e1);
+ if (s.e2 != null) {
+ r.add(s.e2);
+ }
+ return r;
+ }
+}
[20/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
index fce84e9..5aa3aff 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Frame.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* Information about the input and output stack map frames of a basic block.
- *
+ *
* @author Eric Bruneton
*/
final class Frame {
@@ -46,14 +46,14 @@ final class Frame {
* of the first basic block (which is computed from the method descriptor),
* and by using the previously computed output frames to compute the input
* state of the other blocks.
- *
+ *
* All output and input frames are stored as arrays of integers. Reference
* and array types are represented by an index into a type table (which is
* not the same as the constant pool of the class, in order to avoid adding
* unnecessary constants in the pool - not all computed frames will end up
* being stored in the stack map table). This allows very fast type
* comparisons.
- *
+ *
* Output stack map frames are computed relatively to the input frame of the
* basic block, which is not yet known when output frames are computed. It
* is therefore necessary to be able to represent abstract types such as
@@ -61,7 +61,7 @@ final class Frame {
* position x from the top of the input frame stack" or even "the type at
* position x in the input frame, with y more (or less) array dimensions".
* This explains the rather complicated type format used in output frames.
- *
+ *
* This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
* signed number of array dimensions (from -8 to 7). KIND is either BASE,
* LOCAL or STACK. BASE is used for types that are not relative to the input
@@ -70,23 +70,23 @@ final class Frame {
* stack types. VALUE depends on KIND. For LOCAL types, it is an index in
* the input local variable types. For STACK types, it is a position
* relatively to the top of input frame stack. For BASE types, it is either
- * one of the constants defined in FrameVisitor, or for OBJECT and
- * UNINITIALIZED types, a tag and an index in the type table.
- *
+ * one of the constants defined below, or for OBJECT and UNINITIALIZED
+ * types, a tag and an index in the type table.
+ *
* Output frames can contain types of any kind and with a positive or
* negative dimension (and even unassigned types, represented by 0 - which
* does not correspond to any valid type value). Input frames can only
* contain BASE types of positive or null dimension. In all cases the type
* table contains only internal type names (array type descriptors are
* forbidden - dimensions must be represented through the DIM field).
- *
- * The LONG and DOUBLE types are always represented by using two slots (LONG +
- * TOP or DOUBLE + TOP), for local variable types as well as in the operand
- * stack. This is necessary to be able to simulate DUPx_y instructions,
- * whose effect would be dependent on the actual type values if types were
- * always represented by a single slot in the stack (and this is not
- * possible, since actual type values are not always known - cf LOCAL and
- * STACK type kinds).
+ *
+ * The LONG and DOUBLE types are always represented by using two slots (LONG
+ * + TOP or DOUBLE + TOP), for local variable types as well as in the
+ * operand stack. This is necessary to be able to simulate DUPx_y
+ * instructions, whose effect would be dependent on the actual type values
+ * if types were always represented by a single slot in the stack (and this
+ * is not possible, since actual type values are not always known - cf LOCAL
+ * and STACK type kinds).
*/
/**
@@ -107,7 +107,7 @@ final class Frame {
/**
* Mask to get the kind of a frame type.
- *
+ *
* @see #BASE
* @see #LOCAL
* @see #STACK
@@ -117,9 +117,9 @@ final class Frame {
/**
* Flag used for LOCAL and STACK types. Indicates that if this type happens
* to be a long or double type (during the computations of input frames),
- * then it must be set to TOP because the second word of this value has
- * been reused to store other data in the basic block. Hence the first word
- * no longer stores a valid long or double value.
+ * then it must be set to TOP because the second word of this value has been
+ * reused to store other data in the basic block. Hence the first word no
+ * longer stores a valid long or double value.
*/
static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
@@ -489,10 +489,10 @@ final class Frame {
/**
* Relative size of the output stack. The exact semantics of this field
* depends on the algorithm that is used.
- *
+ *
* When only the maximum stack size is computed, this field is the size of
* the output stack relatively to the top of the input stack.
- *
+ *
* When the stack map frames are completely computed, this field is the
* actual number of types in {@link #outputStack}.
*/
@@ -500,7 +500,7 @@ final class Frame {
/**
* Number of types that are initialized in the basic block.
- *
+ *
* @see #initializations
*/
private int initializationCount;
@@ -522,8 +522,9 @@ final class Frame {
/**
* Returns the output frame local variable type at the given index.
- *
- * @param local the index of the local that must be returned.
+ *
+ * @param local
+ * the index of the local that must be returned.
* @return the output frame local variable type at the given index.
*/
private int get(final int local) {
@@ -544,9 +545,11 @@ final class Frame {
/**
* Sets the output frame local variable type at the given index.
- *
- * @param local the index of the local that must be set.
- * @param type the value of the local that must be set.
+ *
+ * @param local
+ * the index of the local that must be set.
+ * @param type
+ * the value of the local that must be set.
*/
private void set(final int local, final int type) {
// creates and/or resizes the output local variables array if necessary
@@ -565,8 +568,9 @@ final class Frame {
/**
* Pushes a new type onto the output frame stack.
- *
- * @param type the type that must be pushed.
+ *
+ * @param type
+ * the type that must be pushed.
*/
private void push(final int type) {
// creates and/or resizes the output stack array if necessary
@@ -590,11 +594,13 @@ final class Frame {
/**
* Pushes a new type onto the output frame stack.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param desc the descriptor of the type to be pushed. Can also be a method
- * descriptor (in this case this method pushes its return type onto
- * the output frame stack).
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * the descriptor of the type to be pushed. Can also be a method
+ * descriptor (in this case this method pushes its return type
+ * onto the output frame stack).
*/
private void push(final ClassWriter cw, final String desc) {
int type = type(cw, desc);
@@ -608,79 +614,81 @@ final class Frame {
/**
* Returns the int encoding of the given type.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param desc a type descriptor.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * a type descriptor.
* @return the int encoding of the given type.
*/
private static int type(final ClassWriter cw, final String desc) {
String t;
int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
switch (desc.charAt(index)) {
- case 'V':
- return 0;
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ // stores the internal name, not the descriptor!
+ t = desc.substring(index + 1, desc.length() - 1);
+ return OBJECT | cw.addType(t);
+ // case '[':
+ default:
+ // extracts the dimensions and the element type
+ int data;
+ int dims = index + 1;
+ while (desc.charAt(dims) == '[') {
+ ++dims;
+ }
+ switch (desc.charAt(dims)) {
case 'Z':
+ data = BOOLEAN;
+ break;
case 'C':
+ data = CHAR;
+ break;
case 'B':
+ data = BYTE;
+ break;
case 'S':
+ data = SHORT;
+ break;
case 'I':
- return INTEGER;
+ data = INTEGER;
+ break;
case 'F':
- return FLOAT;
+ data = FLOAT;
+ break;
case 'J':
- return LONG;
+ data = LONG;
+ break;
case 'D':
- return DOUBLE;
- case 'L':
- // stores the internal name, not the descriptor!
- t = desc.substring(index + 1, desc.length() - 1);
- return OBJECT | cw.addType(t);
- // case '[':
+ data = DOUBLE;
+ break;
+ // case 'L':
default:
- // extracts the dimensions and the element type
- int data;
- int dims = index + 1;
- while (desc.charAt(dims) == '[') {
- ++dims;
- }
- switch (desc.charAt(dims)) {
- case 'Z':
- data = BOOLEAN;
- break;
- case 'C':
- data = CHAR;
- break;
- case 'B':
- data = BYTE;
- break;
- case 'S':
- data = SHORT;
- break;
- case 'I':
- data = INTEGER;
- break;
- case 'F':
- data = FLOAT;
- break;
- case 'J':
- data = LONG;
- break;
- case 'D':
- data = DOUBLE;
- break;
- // case 'L':
- default:
- // stores the internal name, not the descriptor
- t = desc.substring(dims + 1, desc.length() - 1);
- data = OBJECT | cw.addType(t);
- }
- return (dims - index) << 28 | data;
+ // stores the internal name, not the descriptor
+ t = desc.substring(dims + 1, desc.length() - 1);
+ data = OBJECT | cw.addType(t);
+ }
+ return (dims - index) << 28 | data;
}
}
/**
* Pops a type from the output frame stack and returns its value.
- *
+ *
* @return the type that has been popped from the output frame stack.
*/
private int pop() {
@@ -694,8 +702,9 @@ final class Frame {
/**
* Pops the given number of types from the output frame stack.
- *
- * @param elements the number of types that must be popped.
+ *
+ * @param elements
+ * the number of types that must be popped.
*/
private void pop(final int elements) {
if (outputStackTop >= elements) {
@@ -711,10 +720,11 @@ final class Frame {
/**
* Pops a type from the output frame stack.
- *
- * @param desc the descriptor of the type to be popped. Can also be a method
- * descriptor (in this case this method pops the types corresponding
- * to the method arguments).
+ *
+ * @param desc
+ * the descriptor of the type to be popped. Can also be a method
+ * descriptor (in this case this method pops the types
+ * corresponding to the method arguments).
*/
private void pop(final String desc) {
char c = desc.charAt(0);
@@ -730,8 +740,9 @@ final class Frame {
/**
* Adds a new type to the list of types on which a constructor is invoked in
* the basic block.
- *
- * @param var a type on a which a constructor is invoked.
+ *
+ * @param var
+ * a type on a which a constructor is invoked.
*/
private void init(final int var) {
// creates and/or resizes the initializations array if necessary
@@ -751,9 +762,11 @@ final class Frame {
/**
* Replaces the given type with the appropriate type if it is one of the
* types on which a constructor is invoked in the basic block.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param t a type
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * a type
* @return t or, if t is one of the types on which a constructor is invoked
* in the basic block, the type corresponding to this constructor.
*/
@@ -786,18 +799,18 @@ final class Frame {
/**
* Initializes the input frame of the first basic block from the method
* descriptor.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param access the access flags of the method to which this label belongs.
- * @param args the formal parameter types of this method.
- * @param maxLocals the maximum number of local variables of this method.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param access
+ * the access flags of the method to which this label belongs.
+ * @param args
+ * the formal parameter types of this method.
+ * @param maxLocals
+ * the maximum number of local variables of this method.
*/
- void initInputFrame(
- final ClassWriter cw,
- final int access,
- final Type[] args,
- final int maxLocals)
- {
+ void initInputFrame(final ClassWriter cw, final int access,
+ final Type[] args, final int maxLocals) {
inputLocals = new int[maxLocals];
inputStack = new int[0];
int i = 0;
@@ -822,436 +835,436 @@ final class Frame {
/**
* Simulates the action of the given instruction on the output stack frame.
- *
- * @param opcode the opcode of the instruction.
- * @param arg the operand of the instruction, if any.
- * @param cw the class writer to which this label belongs.
- * @param item the operand of the instructions, if any.
+ *
+ * @param opcode
+ * the opcode of the instruction.
+ * @param arg
+ * the operand of the instruction, if any.
+ * @param cw
+ * the class writer to which this label belongs.
+ * @param item
+ * the operand of the instructions, if any.
*/
- void execute(
- final int opcode,
- final int arg,
- final ClassWriter cw,
- final Item item)
- {
+ void execute(final int opcode, final int arg, final ClassWriter cw,
+ final Item item) {
int t1, t2, t3, t4;
switch (opcode) {
- case Opcodes.NOP:
- case Opcodes.INEG:
- case Opcodes.LNEG:
- case Opcodes.FNEG:
- case Opcodes.DNEG:
- case Opcodes.I2B:
- case Opcodes.I2C:
- case Opcodes.I2S:
- case Opcodes.GOTO:
- case Opcodes.RETURN:
- break;
- case Opcodes.ACONST_NULL:
- push(NULL);
- break;
- case Opcodes.ICONST_M1:
- case Opcodes.ICONST_0:
- case Opcodes.ICONST_1:
- case Opcodes.ICONST_2:
- case Opcodes.ICONST_3:
- case Opcodes.ICONST_4:
- case Opcodes.ICONST_5:
- case Opcodes.BIPUSH:
- case Opcodes.SIPUSH:
- case Opcodes.ILOAD:
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (item.type) {
+ case ClassWriter.INT:
push(INTEGER);
break;
- case Opcodes.LCONST_0:
- case Opcodes.LCONST_1:
- case Opcodes.LLOAD:
+ case ClassWriter.LONG:
push(LONG);
push(TOP);
break;
- case Opcodes.FCONST_0:
- case Opcodes.FCONST_1:
- case Opcodes.FCONST_2:
- case Opcodes.FLOAD:
+ case ClassWriter.FLOAT:
push(FLOAT);
break;
- case Opcodes.DCONST_0:
- case Opcodes.DCONST_1:
- case Opcodes.DLOAD:
+ case ClassWriter.DOUBLE:
push(DOUBLE);
push(TOP);
break;
- case Opcodes.LDC:
- switch (item.type) {
- case ClassWriter.INT:
- push(INTEGER);
- break;
- case ClassWriter.LONG:
- push(LONG);
- push(TOP);
- break;
- case ClassWriter.FLOAT:
- push(FLOAT);
- break;
- case ClassWriter.DOUBLE:
- push(DOUBLE);
- push(TOP);
- break;
- case ClassWriter.CLASS:
- push(OBJECT | cw.addType("java/lang/Class"));
- break;
- case ClassWriter.STR:
- push(OBJECT | cw.addType("java/lang/String"));
- break;
- case ClassWriter.MTYPE:
- push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
- break;
- // case ClassWriter.HANDLE_BASE + [1..9]:
- default:
- push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
- }
- break;
- case Opcodes.ALOAD:
- push(get(arg));
- break;
- case Opcodes.IALOAD:
- case Opcodes.BALOAD:
- case Opcodes.CALOAD:
- case Opcodes.SALOAD:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LALOAD:
- case Opcodes.D2L:
- pop(2);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FALOAD:
- pop(2);
- push(FLOAT);
+ case ClassWriter.CLASS:
+ push(OBJECT | cw.addType("java/lang/Class"));
break;
- case Opcodes.DALOAD:
- case Opcodes.L2D:
- pop(2);
- push(DOUBLE);
- push(TOP);
+ case ClassWriter.STR:
+ push(OBJECT | cw.addType("java/lang/String"));
break;
- case Opcodes.AALOAD:
- pop(1);
- t1 = pop();
- push(ELEMENT_OF + t1);
+ case ClassWriter.MTYPE:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
break;
- case Opcodes.ISTORE:
- case Opcodes.FSTORE:
- case Opcodes.ASTORE:
- t1 = pop();
- set(arg, t1);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
+ // case ClassWriter.HANDLE_BASE + [1..9]:
+ default:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(get(arg));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ push(ELEMENT_OF + t1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(arg, t1);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
}
- break;
- case Opcodes.LSTORE:
- case Opcodes.DSTORE:
- pop(1);
- t1 = pop();
- set(arg, t1);
- set(arg + 1, TOP);
- if (arg > 0) {
- t2 = get(arg - 1);
- // if t2 is of kind STACK or LOCAL we cannot know its size!
- if (t2 == LONG || t2 == DOUBLE) {
- set(arg - 1, TOP);
- } else if ((t2 & KIND) != BASE) {
- set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
- }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(arg, t1);
+ set(arg + 1, TOP);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
}
- break;
- case Opcodes.IASTORE:
- case Opcodes.BASTORE:
- case Opcodes.CASTORE:
- case Opcodes.SASTORE:
- case Opcodes.FASTORE:
- case Opcodes.AASTORE:
- pop(3);
- break;
- case Opcodes.LASTORE:
- case Opcodes.DASTORE:
- pop(4);
- break;
- case Opcodes.POP:
- case Opcodes.IFEQ:
- case Opcodes.IFNE:
- case Opcodes.IFLT:
- case Opcodes.IFGE:
- case Opcodes.IFGT:
- case Opcodes.IFLE:
- case Opcodes.IRETURN:
- case Opcodes.FRETURN:
- case Opcodes.ARETURN:
- case Opcodes.TABLESWITCH:
- case Opcodes.LOOKUPSWITCH:
- case Opcodes.ATHROW:
- case Opcodes.MONITORENTER:
- case Opcodes.MONITOREXIT:
- case Opcodes.IFNULL:
- case Opcodes.IFNONNULL:
- pop(1);
- break;
- case Opcodes.POP2:
- case Opcodes.IF_ICMPEQ:
- case Opcodes.IF_ICMPNE:
- case Opcodes.IF_ICMPLT:
- case Opcodes.IF_ICMPGE:
- case Opcodes.IF_ICMPGT:
- case Opcodes.IF_ICMPLE:
- case Opcodes.IF_ACMPEQ:
- case Opcodes.IF_ACMPNE:
- case Opcodes.LRETURN:
- case Opcodes.DRETURN:
- pop(2);
- break;
- case Opcodes.DUP:
- t1 = pop();
- push(t1);
- push(t1);
- break;
- case Opcodes.DUP_X1:
- t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2:
- t1 = pop();
- t2 = pop();
- push(t2);
- push(t1);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X1:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- push(t2);
- push(t1);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.DUP2_X2:
- t1 = pop();
- t2 = pop();
- t3 = pop();
- t4 = pop();
- push(t2);
- push(t1);
- push(t4);
- push(t3);
- push(t2);
- push(t1);
- break;
- case Opcodes.SWAP:
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ set(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException(
+ "JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(item.strVal3);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(item.strVal3);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(item.strVal3);
+ if (opcode != Opcodes.INVOKESTATIC) {
t1 = pop();
- t2 = pop();
- push(t1);
- push(t2);
- break;
- case Opcodes.IADD:
- case Opcodes.ISUB:
- case Opcodes.IMUL:
- case Opcodes.IDIV:
- case Opcodes.IREM:
- case Opcodes.IAND:
- case Opcodes.IOR:
- case Opcodes.IXOR:
- case Opcodes.ISHL:
- case Opcodes.ISHR:
- case Opcodes.IUSHR:
- case Opcodes.L2I:
- case Opcodes.D2I:
- case Opcodes.FCMPL:
- case Opcodes.FCMPG:
- pop(2);
- push(INTEGER);
- break;
- case Opcodes.LADD:
- case Opcodes.LSUB:
- case Opcodes.LMUL:
- case Opcodes.LDIV:
- case Opcodes.LREM:
- case Opcodes.LAND:
- case Opcodes.LOR:
- case Opcodes.LXOR:
- pop(4);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.FADD:
- case Opcodes.FSUB:
- case Opcodes.FMUL:
- case Opcodes.FDIV:
- case Opcodes.FREM:
- case Opcodes.L2F:
- case Opcodes.D2F:
- pop(2);
- push(FLOAT);
- break;
- case Opcodes.DADD:
- case Opcodes.DSUB:
- case Opcodes.DMUL:
- case Opcodes.DDIV:
- case Opcodes.DREM:
- pop(4);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.LSHL:
- case Opcodes.LSHR:
- case Opcodes.LUSHR:
- pop(3);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.IINC:
- set(arg, INTEGER);
- break;
- case Opcodes.I2L:
- case Opcodes.F2L:
- pop(1);
- push(LONG);
- push(TOP);
- break;
- case Opcodes.I2F:
- pop(1);
- push(FLOAT);
- break;
- case Opcodes.I2D:
- case Opcodes.F2D:
- pop(1);
- push(DOUBLE);
- push(TOP);
- break;
- case Opcodes.F2I:
- case Opcodes.ARRAYLENGTH:
- case Opcodes.INSTANCEOF:
- pop(1);
- push(INTEGER);
- break;
- case Opcodes.LCMP:
- case Opcodes.DCMPL:
- case Opcodes.DCMPG:
- pop(4);
- push(INTEGER);
- break;
- case Opcodes.JSR:
- case Opcodes.RET:
- throw new RuntimeException("JSR/RET are not supported with computeFrames option");
- case Opcodes.GETSTATIC:
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTSTATIC:
- pop(item.strVal3);
- break;
- case Opcodes.GETFIELD:
- pop(1);
- push(cw, item.strVal3);
- break;
- case Opcodes.PUTFIELD:
- pop(item.strVal3);
- pop();
- break;
- case Opcodes.INVOKEVIRTUAL:
- case Opcodes.INVOKESPECIAL:
- case Opcodes.INVOKESTATIC:
- case Opcodes.INVOKEINTERFACE:
- pop(item.strVal3);
- if (opcode != Opcodes.INVOKESTATIC) {
- t1 = pop();
- if (opcode == Opcodes.INVOKESPECIAL
- && item.strVal2.charAt(0) == '<')
- {
- init(t1);
- }
+ if (opcode == Opcodes.INVOKESPECIAL
+ && item.strVal2.charAt(0) == '<') {
+ init(t1);
}
- push(cw, item.strVal3);
+ }
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.INVOKEDYNAMIC:
+ pop(item.strVal2);
+ push(cw, item.strVal2);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
break;
- case Opcodes.INVOKEDYNAMIC:
- pop(item.strVal2);
- push(cw, item.strVal2);
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
break;
- case Opcodes.NEW:
- push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
break;
- case Opcodes.NEWARRAY:
- pop();
- switch (arg) {
- case Opcodes.T_BOOLEAN:
- push(ARRAY_OF | BOOLEAN);
- break;
- case Opcodes.T_CHAR:
- push(ARRAY_OF | CHAR);
- break;
- case Opcodes.T_BYTE:
- push(ARRAY_OF | BYTE);
- break;
- case Opcodes.T_SHORT:
- push(ARRAY_OF | SHORT);
- break;
- case Opcodes.T_INT:
- push(ARRAY_OF | INTEGER);
- break;
- case Opcodes.T_FLOAT:
- push(ARRAY_OF | FLOAT);
- break;
- case Opcodes.T_DOUBLE:
- push(ARRAY_OF | DOUBLE);
- break;
- // case Opcodes.T_LONG:
- default:
- push(ARRAY_OF | LONG);
- break;
- }
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
break;
- case Opcodes.ANEWARRAY:
- String s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, '[' + s);
- } else {
- push(ARRAY_OF | OBJECT | cw.addType(s));
- }
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
break;
- case Opcodes.CHECKCAST:
- s = item.strVal1;
- pop();
- if (s.charAt(0) == '[') {
- push(cw, s);
- } else {
- push(OBJECT | cw.addType(s));
- }
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
+ break;
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
break;
- // case Opcodes.MULTIANEWARRAY:
+ // case Opcodes.T_LONG:
default:
- pop(arg);
- push(cw, item.strVal1);
+ push(ARRAY_OF | LONG);
break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, '[' + s);
+ } else {
+ push(ARRAY_OF | OBJECT | cw.addType(s));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, s);
+ } else {
+ push(OBJECT | cw.addType(s));
+ }
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(arg);
+ push(cw, item.strVal1);
+ break;
}
}
@@ -1259,11 +1272,14 @@ final class Frame {
* Merges the input frame of the given basic block with the input and output
* frames of this basic block. Returns <tt>true</tt> if the input frame of
* the given label has been changed by this operation.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param frame the basic block whose input frame must be updated.
- * @param edge the kind of the {@link Edge} between this label and 'label'.
- * See {@link Edge#info}.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param frame
+ * the basic block whose input frame must be updated.
+ * @param edge
+ * the kind of the {@link Edge} between this label and 'label'.
+ * See {@link Edge#info}.
* @return <tt>true</tt> if the input frame of the given label has been
* changed by this operation.
*/
@@ -1294,7 +1310,8 @@ final class Frame {
} else {
t = dim + inputStack[nStack - (s & VALUE)];
}
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
t = TOP;
}
}
@@ -1346,7 +1363,8 @@ final class Frame {
} else {
t = dim + inputStack[nStack - (s & VALUE)];
}
- if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
t = TOP;
}
}
@@ -1362,20 +1380,20 @@ final class Frame {
* Merges the type at the given index in the given type array with the given
* type. Returns <tt>true</tt> if the type array has been modified by this
* operation.
- *
- * @param cw the ClassWriter to which this label belongs.
- * @param t the type with which the type array element must be merged.
- * @param types an array of types.
- * @param index the index of the type that must be merged in 'types'.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * the type with which the type array element must be merged.
+ * @param types
+ * an array of types.
+ * @param index
+ * the index of the type that must be merged in 'types'.
* @return <tt>true</tt> if the type array has been modified by this
* operation.
*/
- private static boolean merge(
- final ClassWriter cw,
- int t,
- final int[] types,
- final int index)
- {
+ private static boolean merge(final ClassWriter cw, int t,
+ final int[] types, final int index) {
int u = types[index];
if (u == t) {
// if the types are equal, merge(u,t)=u, so there is no change
@@ -1399,6 +1417,7 @@ final class Frame {
// if t is the NULL type, merge(u,t)=u, so there is no change
return false;
} else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ // if t and u have the same dimension and same base kind
if ((u & BASE_KIND) == OBJECT) {
// if t is also a reference type, and if u and t have the
// same dimension merge(u,t) = dim(t) | common parent of the
@@ -1411,9 +1430,13 @@ final class Frame {
v = OBJECT | cw.addType("java/lang/Object");
}
} else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
- // if t is any other reference or array type,
- // merge(u,t)=java/lang/Object
- v = OBJECT | cw.addType("java/lang/Object");
+ // if t is any other reference or array type, the merged type
+ // is Object, or min(dim(u), dim(t)) | java/lang/Object is u
+ // and t have different array dimensions
+ int tdim = t & DIM;
+ int udim = u & DIM;
+ v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT
+ | cw.addType("java/lang/Object");
} else {
// if t is any other type, merge(u,t)=TOP
v = TOP;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
index e8906fe..e01fd40 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handle.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A reference to a field or a method.
- *
+ *
* @author Remi Forax
* @author Eric Bruneton
*/
@@ -49,7 +49,8 @@ public final class Handle {
final int tag;
/**
- * The internal name of the field or method designed by this handle.
+ * The internal name of the class that owns the field or method designated
+ * by this handle.
*/
final String owner;
@@ -65,19 +66,24 @@ public final class Handle {
/**
* Constructs a new field or method handle.
- *
- * @param tag the kind of field or method designated by this Handle. Must be
- * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
- * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
- * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
- * {@link Opcodes#H_INVOKESPECIAL},
- * {@link Opcodes#H_NEWINVOKESPECIAL} or
- * {@link Opcodes#H_INVOKEINTERFACE}.
- * @param owner the internal name of the field or method designed by this
- * handle.
- * @param name the name of the field or method designated by this handle.
- * @param desc the descriptor of the field or method designated by this
- * handle.
+ *
+ * @param tag
+ * the kind of field or method designated by this Handle. Must be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the class that owns the field or method
+ * designated by this handle.
+ * @param name
+ * the name of the field or method designated by this handle.
+ * @param desc
+ * the descriptor of the field or method designated by this
+ * handle.
*/
public Handle(int tag, String owner, String name, String desc) {
this.tag = tag;
@@ -88,7 +94,7 @@ public final class Handle {
/**
* Returns the kind of field or method designated by this handle.
- *
+ *
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
@@ -101,11 +107,11 @@ public final class Handle {
}
/**
- * Returns the internal name of the field or method designed by this
- * handle.
- *
- * @return the internal name of the field or method designed by this
- * handle.
+ * Returns the internal name of the class that owns the field or method
+ * designated by this handle.
+ *
+ * @return the internal name of the class that owns the field or method
+ * designated by this handle.
*/
public String getOwner() {
return owner;
@@ -113,7 +119,7 @@ public final class Handle {
/**
* Returns the name of the field or method designated by this handle.
- *
+ *
* @return the name of the field or method designated by this handle.
*/
public String getName() {
@@ -122,7 +128,7 @@ public final class Handle {
/**
* Returns the descriptor of the field or method designated by this handle.
- *
+ *
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
@@ -138,8 +144,8 @@ public final class Handle {
return false;
}
Handle h = (Handle) obj;
- return tag == h.tag && owner.equals(h.owner)
- && name.equals(h.name) && desc.equals(h.desc);
+ return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
+ && desc.equals(h.desc);
}
@Override
@@ -149,8 +155,13 @@ public final class Handle {
/**
* Returns the textual representation of this handle. The textual
- * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
- * this format is unambiguous, it can be parsed if necessary.
+ * representation is:
+ *
+ * <pre>
+ * owner '.' name desc ' ' '(' tag ')'
+ * </pre>
+ *
+ * . As this format is unambiguous, it can be parsed if necessary.
*/
@Override
public String toString() {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
index 94ac8e5..a387654 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Handler.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* Information about an exception handler block.
- *
+ *
* @author Eric Bruneton
*/
class Handler {
@@ -71,10 +71,13 @@ class Handler {
/**
* Removes the range between start and end from the given exception
* handlers.
- *
- * @param h an exception handler list.
- * @param start the start of the range to be removed.
- * @param end the end of the range to be removed. Maybe null.
+ *
+ * @param h
+ * an exception handler list.
+ * @param start
+ * the start of the range to be removed.
+ * @param end
+ * the end of the range to be removed. Maybe null.
* @return the exception handler list with the start-end range removed.
*/
static Handler remove(Handler h, Label start, Label end) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
index 4fab86a..fa4f454 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Item.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link ClassWriter} class.
- *
+ *
* @author Eric Bruneton
*/
final class Item {
@@ -52,11 +52,11 @@ final class Item {
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
- *
- * MethodHandle constant 9 variations are stored using a range
- * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+ *
+ * MethodHandle constant 9 variations are stored using a range of 9 values
+ * from {@link ClassWriter#HANDLE_BASE} + 1 to
* {@link ClassWriter#HANDLE_BASE} + 9.
- *
+ *
* Special Item types are used for Items that are stored in the ClassWriter
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
* avoid clashes with normal constant pool items in the ClassWriter constant
@@ -114,8 +114,9 @@ final class Item {
/**
* Constructs an uninitialized {@link Item} for constant pool element at
* given position.
- *
- * @param index index of the item to be constructed.
+ *
+ * @param index
+ * index of the item to be constructed.
*/
Item(final int index) {
this.index = index;
@@ -123,9 +124,11 @@ final class Item {
/**
* Constructs a copy of the given item.
- *
- * @param index index of the item to be constructed.
- * @param i the item that must be copied into the item to be constructed.
+ *
+ * @param index
+ * index of the item to be constructed.
+ * @param i
+ * the item that must be copied into the item to be constructed.
*/
Item(final int index, final Item i) {
this.index = index;
@@ -140,8 +143,9 @@ final class Item {
/**
* Sets this item to an integer item.
- *
- * @param intVal the value of this item.
+ *
+ * @param intVal
+ * the value of this item.
*/
void set(final int intVal) {
this.type = ClassWriter.INT;
@@ -151,8 +155,9 @@ final class Item {
/**
* Sets this item to a long item.
- *
- * @param longVal the value of this item.
+ *
+ * @param longVal
+ * the value of this item.
*/
void set(final long longVal) {
this.type = ClassWriter.LONG;
@@ -162,8 +167,9 @@ final class Item {
/**
* Sets this item to a float item.
- *
- * @param floatVal the value of this item.
+ *
+ * @param floatVal
+ * the value of this item.
*/
void set(final float floatVal) {
this.type = ClassWriter.FLOAT;
@@ -173,8 +179,9 @@ final class Item {
/**
* Sets this item to a double item.
- *
- * @param doubleVal the value of this item.
+ *
+ * @param doubleVal
+ * the value of this item.
*/
void set(final double doubleVal) {
this.type = ClassWriter.DOUBLE;
@@ -184,50 +191,54 @@ final class Item {
/**
* Sets this item to an item that do not hold a primitive value.
- *
- * @param type the type of this item.
- * @param strVal1 first part of the value of this item.
- * @param strVal2 second part of the value of this item.
- * @param strVal3 third part of the value of this item.
+ *
+ * @param type
+ * the type of this item.
+ * @param strVal1
+ * first part of the value of this item.
+ * @param strVal2
+ * second part of the value of this item.
+ * @param strVal3
+ * third part of the value of this item.
*/
- void set(
- final int type,
- final String strVal1,
- final String strVal2,
- final String strVal3)
- {
+ void set(final int type, final String strVal1, final String strVal2,
+ final String strVal3) {
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
- return;
- case ClassWriter.NAME_TYPE:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode());
- return;
- // ClassWriter.FIELD:
- // ClassWriter.METH:
- // ClassWriter.IMETH:
- // ClassWriter.HANDLE_BASE + 1..9
- default:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
- * strVal2.hashCode() * strVal3.hashCode());
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case ClassWriter.NAME_TYPE: {
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ }
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ // ClassWriter.HANDLE_BASE + 1..9
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
}
}
/**
* Sets the item to an InvokeDynamic item.
- *
- * @param name invokedynamic's name.
- * @param desc invokedynamic's desc.
- * @param bsmIndex zero based index into the class attribute BootrapMethods.
+ *
+ * @param name
+ * invokedynamic's name.
+ * @param desc
+ * invokedynamic's desc.
+ * @param bsmIndex
+ * zero based index into the class attribute BootrapMethods.
*/
void set(String name, String desc, int bsmIndex) {
this.type = ClassWriter.INDY;
@@ -240,11 +251,13 @@ final class Item {
/**
* Sets the item to a BootstrapMethod item.
- *
- * @param position position in byte in the class attribute BootrapMethods.
- * @param hashCode hashcode of the item. This hashcode is processed from
- * the hashcode of the bootstrap method and the hashcode of
- * all bootstrap arguments.
+ *
+ * @param position
+ * position in byte in the class attribute BootrapMethods.
+ * @param hashCode
+ * hashcode of the item. This hashcode is processed from the
+ * hashcode of the bootstrap method and the hashcode of all
+ * bootstrap arguments.
*/
void set(int position, int hashCode) {
this.type = ClassWriter.BSM;
@@ -255,42 +268,43 @@ final class Item {
/**
* Indicates if the given item is equal to this one. <i>This method assumes
* that the two items have the same {@link #type}</i>.
- *
- * @param i the item to be compared to this one. Both items must have the
- * same {@link #type}.
+ *
+ * @param i
+ * the item to be compared to this one. Both items must have the
+ * same {@link #type}.
* @return <tt>true</tt> if the given item if equal to this one,
* <tt>false</tt> otherwise.
*/
boolean isEqualTo(final Item i) {
switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- case ClassWriter.MTYPE:
- case ClassWriter.TYPE_NORMAL:
- return i.strVal1.equals(strVal1);
- case ClassWriter.TYPE_MERGED:
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- return i.longVal == longVal;
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- return i.intVal == intVal;
- case ClassWriter.TYPE_UNINIT:
- return i.intVal == intVal && i.strVal1.equals(strVal1);
- case ClassWriter.NAME_TYPE:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
- case ClassWriter.INDY:
- return i.longVal == longVal && i.strVal1.equals(strVal1)
- && i.strVal2.equals(strVal2);
-
- // case ClassWriter.FIELD:
- // case ClassWriter.METH:
- // case ClassWriter.IMETH:
- // case ClassWriter.HANDLE_BASE + 1..9
- default:
- return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
- && i.strVal3.equals(strVal3);
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ return i.strVal1.equals(strVal1);
+ case ClassWriter.TYPE_MERGED:
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ return i.longVal == longVal;
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ return i.intVal == intVal;
+ case ClassWriter.TYPE_UNINIT:
+ return i.intVal == intVal && i.strVal1.equals(strVal1);
+ case ClassWriter.NAME_TYPE:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+ case ClassWriter.INDY: {
+ return i.longVal == longVal && i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2);
+ }
+ // case ClassWriter.FIELD:
+ // case ClassWriter.METH:
+ // case ClassWriter.IMETH:
+ // case ClassWriter.HANDLE_BASE + 1..9
+ default:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+ && i.strVal3.equals(strVal3);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
index ef338c3..c0bbe7e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Label.java
@@ -32,10 +32,10 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A label represents a position in the bytecode of a method. Labels are used
* for jump, goto, and switch instructions, and for try catch blocks. A label
- * designates the <i>instruction</i> that is just after. Note however that
- * there can be other elements between a label and the instruction it
- * designates (such as other labels, stack map frames, line numbers, etc.).
- *
+ * designates the <i>instruction</i> that is just after. Note however that there
+ * can be other elements between a label and the instruction it designates (such
+ * as other labels, stack map frames, line numbers, etc.).
+ *
* @author Eric Bruneton
*/
public class Label {
@@ -110,14 +110,14 @@ public class Label {
/**
* Field used to associate user information to a label. Warning: this field
* is used by the ASM tree package. In order to use it with the ASM tree
- * package you must override the {@link
- * org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
+ * package you must override the
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.MethodNode#getLabelNode} method.
*/
public Object info;
/**
* Flags that indicate the status of this label.
- *
+ *
* @see #DEBUG
* @see #RESOLVED
* @see #RESIZED
@@ -154,7 +154,7 @@ public class Label {
* indicates if this reference uses 2 or 4 bytes, and its absolute value
* gives the position of the bytecode instruction. This array is also used
* as a bitset to store the subroutines to which a basic block belongs. This
- * information is needed in {@linked MethodWriter#visitMaxs}, after all
+ * information is needed in {@linked MethodWriter#visitMaxs}, after all
* forward references have been resolved. Hence the same array can be used
* for both purposes without problems.
*/
@@ -170,19 +170,19 @@ public class Label {
* represented by the Label object that corresponds to the first instruction
* of this basic block. Each node also stores the list of its successors in
* the graph, as a linked list of Edge objects.
- *
+ *
* The control flow analysis algorithms used to compute the maximum stack
* size or the stack map frames are similar and use two steps. The first
* step, during the visit of each instruction, builds information about the
* state of the local variables and the operand stack at the end of each
* basic block, called the "output frame", <i>relatively</i> to the frame
* state at the beginning of the basic block, which is called the "input
- * frame", and which is <i>unknown</i> during this step. The second step,
- * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
- * computes information about the input frame of each basic block, from the
- * input state of the first basic block (known from the method signature),
- * and by the using the previously computed relative output frames.
- *
+ * frame", and which is <i>unknown</i> during this step. The second step, in
+ * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
+ * information about the input frame of each basic block, from the input
+ * state of the first basic block (known from the method signature), and by
+ * the using the previously computed relative output frames.
+ *
* The algorithm used to compute the maximum stack size only computes the
* relative output and absolute input stack heights, while the algorithm
* used to compute stack map frames computes relative output frames and
@@ -192,10 +192,10 @@ public class Label {
/**
* Start of the output stack relatively to the input stack. The exact
* semantics of this field depends on the algorithm that is used.
- *
+ *
* When only the maximum stack size is computed, this field is the number of
* elements in the input stack.
- *
+ *
* When the stack map frames are completely computed, this field is the
* offset of the first output stack element relatively to the top of the
* input stack. This offset is always negative or null. A null offset means
@@ -240,7 +240,7 @@ public class Label {
* main loop of the fix point algorithm used in the second step of the
* control flow analysis algorithms. It is also used in
* {@link #visitSubroutine} to avoid using a recursive method.
- *
+ *
* @see MethodWriter#visitMaxs
*/
Label next;
@@ -264,13 +264,15 @@ public class Label {
* from the start of the method's bytecode. <i>This method is intended for
* {@link Attribute} sub classes, and is normally not needed by class
* generators or adapters.</i>
- *
+ *
* @return the offset corresponding to this label.
- * @throws IllegalStateException if this label is not resolved yet.
+ * @throws IllegalStateException
+ * if this label is not resolved yet.
*/
public int getOffset() {
if ((status & RESOLVED) == 0) {
- throw new IllegalStateException("Label offset position has not been resolved yet");
+ throw new IllegalStateException(
+ "Label offset position has not been resolved yet");
}
return position;
}
@@ -280,22 +282,22 @@ public class Label {
* position of the label is known, the offset is computed and written
* directly. Otherwise, a null offset is written and a new forward reference
* is declared for this label.
- *
- * @param owner the code writer that calls this method.
- * @param out the bytecode of the method.
- * @param source the position of first byte of the bytecode instruction that
- * contains this label.
- * @param wideOffset <tt>true</tt> if the reference must be stored in 4
- * bytes, or <tt>false</tt> if it must be stored with 2 bytes.
- * @throws IllegalArgumentException if this label has not been created by
- * the given code writer.
- */
- void put(
- final MethodWriter owner,
- final ByteVector out,
- final int source,
- final boolean wideOffset)
- {
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param out
+ * the bytecode of the method.
+ * @param source
+ * the position of first byte of the bytecode instruction that
+ * contains this label.
+ * @param wideOffset
+ * <tt>true</tt> if the reference must be stored in 4 bytes, or
+ * <tt>false</tt> if it must be stored with 2 bytes.
+ * @throws IllegalArgumentException
+ * if this label has not been created by the given code writer.
+ */
+ void put(final MethodWriter owner, final ByteVector out, final int source,
+ final boolean wideOffset) {
if ((status & RESOLVED) == 0) {
if (wideOffset) {
addReference(-1 - source, out.length);
@@ -318,26 +320,22 @@ public class Label {
* for a true forward reference, i.e. only if this label is not resolved
* yet. For backward references, the offset of the reference can be, and
* must be, computed and stored directly.
- *
- * @param sourcePosition the position of the referencing instruction. This
- * position will be used to compute the offset of this forward
- * reference.
- * @param referencePosition the position where the offset for this forward
- * reference must be stored.
- */
- private void addReference(
- final int sourcePosition,
- final int referencePosition)
- {
+ *
+ * @param sourcePosition
+ * the position of the referencing instruction. This position
+ * will be used to compute the offset of this forward reference.
+ * @param referencePosition
+ * the position where the offset for this forward reference must
+ * be stored.
+ */
+ private void addReference(final int sourcePosition,
+ final int referencePosition) {
if (srcAndRefPositions == null) {
srcAndRefPositions = new int[6];
}
if (referenceCount >= srcAndRefPositions.length) {
int[] a = new int[srcAndRefPositions.length + 6];
- System.arraycopy(srcAndRefPositions,
- 0,
- a,
- 0,
+ System.arraycopy(srcAndRefPositions, 0, a, 0,
srcAndRefPositions.length);
srcAndRefPositions = a;
}
@@ -350,10 +348,13 @@ public class Label {
* when this label is added to the bytecode of the method, i.e. when its
* position becomes known. This method fills in the blanks that where left
* in the bytecode by each forward reference previously added to this label.
- *
- * @param owner the code writer that calls this method.
- * @param position the position of this label in the bytecode.
- * @param data the bytecode of the method.
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param position
+ * the position of this label in the bytecode.
+ * @param data
+ * the bytecode of the method.
* @return <tt>true</tt> if a blank that was left for this label was to
* small to store the offset. In such a case the corresponding jump
* instruction is replaced with a pseudo instruction (using unused
@@ -361,14 +362,12 @@ public class Label {
* instructions will need to be replaced with true instructions with
* wider offsets (4 bytes instead of 2). This is done in
* {@link MethodWriter#resizeInstructions}.
- * @throws IllegalArgumentException if this label has already been resolved,
- * or if it has not been created by the given code writer.
- */
- boolean resolve(
- final MethodWriter owner,
- final int position,
- final byte[] data)
- {
+ * @throws IllegalArgumentException
+ * if this label has already been resolved, or if it has not
+ * been created by the given code writer.
+ */
+ boolean resolve(final MethodWriter owner, final int position,
+ final byte[] data) {
boolean needUpdate = false;
this.status |= RESOLVED;
this.position = position;
@@ -417,7 +416,7 @@ public class Label {
* isolated label or for the first label in a series of successive labels,
* this method returns the label itself. For other labels it returns the
* first label of the series.
- *
+ *
* @return the first label of the series to which this label belongs.
*/
Label getFirst() {
@@ -430,8 +429,9 @@ public class Label {
/**
* Returns true is this basic block belongs to the given subroutine.
- *
- * @param id a subroutine id.
+ *
+ * @param id
+ * a subroutine id.
* @return true is this basic block belongs to the given subroutine.
*/
boolean inSubroutine(final long id) {
@@ -444,8 +444,9 @@ public class Label {
/**
* Returns true if this basic block and the given one belong to a common
* subroutine.
- *
- * @param block another basic block.
+ *
+ * @param block
+ * another basic block.
* @return true if this basic block and the given one belong to a common
* subroutine.
*/
@@ -463,9 +464,11 @@ public class Label {
/**
* Marks this basic block as belonging to the given subroutine.
- *
- * @param id a subroutine id.
- * @param nbSubroutines the total number of subroutines in the method.
+ *
+ * @param id
+ * a subroutine id.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
*/
void addToSubroutine(final long id, final int nbSubroutines) {
if ((status & VISITED) == 0) {
@@ -480,15 +483,17 @@ public class Label {
* blocks as belonging to this subroutine. This method follows the control
* flow graph to find all the blocks that are reachable from the current
* block WITHOUT following any JSR target.
- *
- * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
- * null it is added to the successor of the RET blocks found in the
- * subroutine.
- * @param id the id of this subroutine.
- * @param nbSubroutines the total number of subroutines in the method.
- */
- void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
- {
+ *
+ * @param JSR
+ * a JSR block that jumps to this subroutine. If this JSR is not
+ * null it is added to the successor of the RET blocks found in
+ * the subroutine.
+ * @param id
+ * the id of this subroutine.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
+ */
+ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
// user managed stack of labels, to avoid using a recursive method
// (recursivity can lead to stack overflow with very large methods)
Label stack = this;
@@ -545,7 +550,7 @@ public class Label {
/**
* Returns a string representation of this label.
- *
+ *
* @return a string representation of this label.
*/
@Override
[11/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
new file mode 100644
index 0000000..ecf580f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-frames.properties
@@ -0,0 +1,62 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/Frame/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.typeCount=-
+org/objectweb/asm/ClassWriter.typeTable=-
+
+org/objectweb/asm/Label.frame=-
+
+org/objectweb/asm/MethodWriter.frameCount=-
+org/objectweb/asm/MethodWriter.stackMap=-
+org/objectweb/asm/MethodWriter.previousFrameOffset=-
+org/objectweb/asm/MethodWriter.previousFrame=-
+org/objectweb/asm/MethodWriter.frameIndex=-
+org/objectweb/asm/MethodWriter.frame=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=-
+
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=-
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=-
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=-
+org/objectweb/asm/ClassWriter.getMergedType(II)I=-
+
+org/objectweb/asm/MethodWriter.startFrame(III)V=-
+org/objectweb/asm/MethodWriter.endFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrame()V=-
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=-
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
new file mode 100644
index 0000000..97f7e34
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-resize.properties
@@ -0,0 +1,37 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+# field mappings
+
+# method mappings
+
+org/objectweb/asm/MethodWriter.resizeInstructions()V=-
\ 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/optimizer/shrink-signatures.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
new file mode 100644
index 0000000..6a48623
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-signatures.properties
@@ -0,0 +1,43 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/signature/SignatureReader/remove=true
+org/objectweb/asm/signature/SignatureVisitor/remove=true
+org/objectweb/asm/signature/SignatureWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.signature=-
+
+org/objectweb/asm/FieldWriter.signature=-
+
+org/objectweb/asm/MethodWriter.signature=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
new file mode 100644
index 0000000..1c83ca2
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-writer.properties
@@ -0,0 +1,66 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+org/objectweb/asm/ByteVector/remove=true
+org/objectweb/asm/ClassWriter/remove=true
+org/objectweb/asm/Edge/remove=true
+org/objectweb/asm/FieldWriter/remove=true
+org/objectweb/asm/Frame/remove=true
+org/objectweb/asm/Handler/remove=true
+org/objectweb/asm/Item/remove=true
+org/objectweb/asm/MethodWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/Label.position=-
+org/objectweb/asm/Label.referenceCount=-
+org/objectweb/asm/Label.srcAndRefPositions=-
+org/objectweb/asm/Label.inputStackTop=-
+org/objectweb/asm/Label.outputStackMax=-
+org/objectweb/asm/Label.frame=-
+org/objectweb/asm/Label.successor=-
+org/objectweb/asm/Label.successors=-
+org/objectweb/asm/Label.next=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=-
+
+org/objectweb/asm/Label.addReference(II)V=-
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=-
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=-
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=-
+org/objectweb/asm/Label.inSubroutine(J)Z=-
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=-
+org/objectweb/asm/Label.addToSubroutine(JI)V=-
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=-
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
new file mode 100644
index 0000000..6b2a41f
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink.properties
@@ -0,0 +1,380 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+#org/objectweb/asm/Edge=org/objectweb/asm/a
+#org/objectweb/asm/Item=org/objectweb/asm/b
+#org/objectweb/asm/FieldWriter=org/objectweb/asm/c
+#org/objectweb/asm/MethodWriter=org/objectweb/asm/d
+#org/objectweb/asm/AnnotationWriter=org/objectweb/asm/e
+#org/objectweb/asm/Context=org/objectweb/asm/f
+
+java/lang/StringBuilder=java/lang/StringBuffer
+
+
+# field mappings
+
+org/objectweb/asm/AnnotationWriter.cw=a
+org/objectweb/asm/AnnotationWriter.size=b
+org/objectweb/asm/AnnotationWriter.named=c
+org/objectweb/asm/AnnotationWriter.bv=d
+org/objectweb/asm/AnnotationWriter.parent=e
+org/objectweb/asm/AnnotationWriter.offset=f
+org/objectweb/asm/AnnotationWriter.next=g
+org/objectweb/asm/AnnotationWriter.prev=h
+
+org/objectweb/asm/Attribute.next=a
+org/objectweb/asm/Attribute.value=b
+
+org/objectweb/asm/ByteVector.data=a
+org/objectweb/asm/ByteVector.length=b
+
+org/objectweb/asm/ClassReader.items=a
+org/objectweb/asm/ClassReader.strings=c
+org/objectweb/asm/ClassReader.maxStringLength=d
+#org/objectweb/asm/ClassReader.header=e
+
+org/objectweb/asm/Context.attrs=a
+org/objectweb/asm/Context.flags=b
+org/objectweb/asm/Context.buffer=c
+org/objectweb/asm/Context.bootstrapMethods=d
+org/objectweb/asm/Context.access=e
+org/objectweb/asm/Context.name=f
+org/objectweb/asm/Context.desc=g
+org/objectweb/asm/Context.labels=h
+org/objectweb/asm/Context.typeRef=i
+org/objectweb/asm/Context.typePath=j
+org/objectweb/asm/Context.offset=k
+org/objectweb/asm/Context.start=l
+org/objectweb/asm/Context.end=m
+org/objectweb/asm/Context.index=n
+org/objectweb/asm/Context.offset=o
+org/objectweb/asm/Context.mode=p
+org/objectweb/asm/Context.localCount=q
+org/objectweb/asm/Context.localDiff=r
+org/objectweb/asm/Context.local=s
+org/objectweb/asm/Context.stackCount=t
+org/objectweb/asm/Context.stack=u
+
+org/objectweb/asm/ClassWriter.TYPE=a
+org/objectweb/asm/ClassWriter.version=b
+org/objectweb/asm/ClassWriter.index=c
+org/objectweb/asm/ClassWriter.pool=d
+org/objectweb/asm/ClassWriter.items=e
+org/objectweb/asm/ClassWriter.threshold=f
+org/objectweb/asm/ClassWriter.key=g
+org/objectweb/asm/ClassWriter.key2=h
+org/objectweb/asm/ClassWriter.key3=i
+org/objectweb/asm/ClassWriter.key4=j
+org/objectweb/asm/ClassWriter.access=k
+org/objectweb/asm/ClassWriter.name=l
+org/objectweb/asm/ClassWriter.signature=m
+org/objectweb/asm/ClassWriter.superName=n
+org/objectweb/asm/ClassWriter.interfaceCount=o
+org/objectweb/asm/ClassWriter.interfaces=p
+org/objectweb/asm/ClassWriter.sourceFile=q
+org/objectweb/asm/ClassWriter.sourceDebug=r
+org/objectweb/asm/ClassWriter.enclosingMethodOwner=s
+org/objectweb/asm/ClassWriter.enclosingMethod=t
+org/objectweb/asm/ClassWriter.anns=u
+org/objectweb/asm/ClassWriter.ianns=v
+org/objectweb/asm/ClassWriter.tanns=N
+org/objectweb/asm/ClassWriter.itanns=O
+org/objectweb/asm/ClassWriter.attrs=w
+org/objectweb/asm/ClassWriter.innerClassesCount=x
+org/objectweb/asm/ClassWriter.innerClasses=y
+org/objectweb/asm/ClassWriter.bootstrapMethodsCount=z
+org/objectweb/asm/ClassWriter.bootstrapMethods=A
+org/objectweb/asm/ClassWriter.firstField=B
+org/objectweb/asm/ClassWriter.lastField=C
+org/objectweb/asm/ClassWriter.firstMethod=D
+org/objectweb/asm/ClassWriter.lastMethod=E
+org/objectweb/asm/ClassWriter.computeMaxs=F
+org/objectweb/asm/ClassWriter.typeCount=G
+org/objectweb/asm/ClassWriter.typeTable=H
+org/objectweb/asm/ClassWriter.thisName=I
+org/objectweb/asm/ClassWriter.computeFrames=J
+org/objectweb/asm/ClassWriter.computeMaxs=K
+org/objectweb/asm/ClassWriter.invalidFrames=L
+org/objectweb/asm/ClassWriter.cr=M
+
+org/objectweb/asm/Edge.info=a
+org/objectweb/asm/Edge.successor=b
+org/objectweb/asm/Edge.next=c
+
+org/objectweb/asm/Handler.start=a
+org/objectweb/asm/Handler.end=b
+org/objectweb/asm/Handler.handler=c
+org/objectweb/asm/Handler.desc=d
+org/objectweb/asm/Handler.type=e
+org/objectweb/asm/Handler.next=f
+
+org/objectweb/asm/FieldWriter.cw=b
+org/objectweb/asm/FieldWriter.access=c
+org/objectweb/asm/FieldWriter.name=d
+org/objectweb/asm/FieldWriter.desc=e
+org/objectweb/asm/FieldWriter.signature=f
+org/objectweb/asm/FieldWriter.value=g
+org/objectweb/asm/FieldWriter.anns=h
+org/objectweb/asm/FieldWriter.ianns=i
+org/objectweb/asm/FieldWriter.tanns=k
+org/objectweb/asm/FieldWriter.itanns=l
+org/objectweb/asm/FieldWriter.attrs=j
+
+org/objectweb/asm/Item.index=a
+org/objectweb/asm/Item.type=b
+org/objectweb/asm/Item.intVal=c
+org/objectweb/asm/Item.longVal=d
+org/objectweb/asm/Item.strVal1=g
+org/objectweb/asm/Item.strVal2=h
+org/objectweb/asm/Item.strVal3=i
+org/objectweb/asm/Item.hashCode=j
+org/objectweb/asm/Item.next=k
+
+org/objectweb/asm/Label.status=a
+org/objectweb/asm/Label.line=b
+org/objectweb/asm/Label.position=c
+org/objectweb/asm/Label.referenceCount=d
+org/objectweb/asm/Label.srcAndRefPositions=e
+org/objectweb/asm/Label.inputStackTop=f
+org/objectweb/asm/Label.outputStackMax=g
+org/objectweb/asm/Label.frame=h
+org/objectweb/asm/Label.successor=i
+org/objectweb/asm/Label.successors=j
+org/objectweb/asm/Label.next=k
+
+org/objectweb/asm/Frame.SIZE=a
+org/objectweb/asm/Frame.owner=b
+org/objectweb/asm/Frame.inputLocals=c
+org/objectweb/asm/Frame.inputStack=d
+org/objectweb/asm/Frame.outputLocals=e
+org/objectweb/asm/Frame.outputStack=f
+org/objectweb/asm/Frame.outputStackTop=g
+org/objectweb/asm/Frame.initializationCount=h
+org/objectweb/asm/Frame.initializations=i
+
+org/objectweb/asm/MethodWriter.cw=b
+org/objectweb/asm/MethodWriter.access=c
+org/objectweb/asm/MethodWriter.name=d
+org/objectweb/asm/MethodWriter.desc=e
+org/objectweb/asm/MethodWriter.descriptor=f
+org/objectweb/asm/MethodWriter.signature=g
+org/objectweb/asm/MethodWriter.classReaderOffset=h
+org/objectweb/asm/MethodWriter.classReaderLength=i
+org/objectweb/asm/MethodWriter.exceptionCount=j
+org/objectweb/asm/MethodWriter.exceptions=k
+org/objectweb/asm/MethodWriter.annd=l
+org/objectweb/asm/MethodWriter.anns=m
+org/objectweb/asm/MethodWriter.ianns=n
+org/objectweb/asm/MethodWriter.tanns=U
+org/objectweb/asm/MethodWriter.itanns=V
+org/objectweb/asm/MethodWriter.panns=o
+org/objectweb/asm/MethodWriter.ipanns=p
+org/objectweb/asm/MethodWriter.attrs=q
+org/objectweb/asm/MethodWriter.code=r
+org/objectweb/asm/MethodWriter.maxStack=s
+org/objectweb/asm/MethodWriter.maxLocals=t
+org/objectweb/asm/MethodWriter.currentLocals=T
+org/objectweb/asm/MethodWriter.frameCount=u
+org/objectweb/asm/MethodWriter.stackMap=v
+org/objectweb/asm/MethodWriter.previousFrameOffset=w
+org/objectweb/asm/MethodWriter.previousFrame=x
+#org/objectweb/asm/MethodWriter.frameIndex=y
+org/objectweb/asm/MethodWriter.frame=z
+org/objectweb/asm/MethodWriter.handlerCount=A
+org/objectweb/asm/MethodWriter.firstHandler=B
+org/objectweb/asm/MethodWriter.lastHandler=C
+org/objectweb/asm/MethodWriter.methodParametersCount=Z
+org/objectweb/asm/MethodWriter.methodParameters=$
+org/objectweb/asm/MethodWriter.localVarCount=D
+org/objectweb/asm/MethodWriter.localVar=E
+org/objectweb/asm/MethodWriter.localVarTypeCount=F
+org/objectweb/asm/MethodWriter.localVarType=G
+org/objectweb/asm/MethodWriter.lineNumberCount=H
+org/objectweb/asm/MethodWriter.lineNumber=I
+org/objectweb/asm/MethodWriter.lastCodeOffset=Y
+org/objectweb/asm/MethodWriter.ctanns=W
+org/objectweb/asm/MethodWriter.ictanns=X
+org/objectweb/asm/MethodWriter.cattrs=J
+org/objectweb/asm/MethodWriter.resize=K
+org/objectweb/asm/MethodWriter.subroutines=L
+org/objectweb/asm/MethodWriter.compute=M
+org/objectweb/asm/MethodWriter.labels=N
+org/objectweb/asm/MethodWriter.previousBlock=O
+org/objectweb/asm/MethodWriter.currentBlock=P
+org/objectweb/asm/MethodWriter.stackSize=Q
+org/objectweb/asm/MethodWriter.maxStackSize=R
+org/objectweb/asm/MethodWriter.synthetics=S
+
+org/objectweb/asm/Type.sort=a
+org/objectweb/asm/Type.buf=b
+org/objectweb/asm/Type.off=c
+org/objectweb/asm/Type.len=d
+
+org/objectweb/asm/TypeReference.value=a
+
+org/objectweb/asm/TypePath.b=a
+org/objectweb/asm/TypePath.offset=b
+
+org/objectweb/asm/Handle.tag=a
+org/objectweb/asm/Handle.owner=b
+org/objectweb/asm/Handle.name=c
+org/objectweb/asm/Handle.desc=d
+
+org/objectweb/asm/signature/SignatureReader.signature=a
+
+org/objectweb/asm/signature/SignatureWriter.buf=a
+org/objectweb/asm/signature/SignatureWriter.hasFormals=b
+org/objectweb/asm/signature/SignatureWriter.hasParameters=c
+org/objectweb/asm/signature/SignatureWriter.argumentStack=d
+
+# method mappings
+
+org/objectweb/asm/AnnotationWriter.getSize()I=a
+org/objectweb/asm/AnnotationWriter.put([Lorg/objectweb/asm/AnnotationWriter;ILorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/AnnotationWriter.putTarget(ILorg/objectweb/asm/TypePath;Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Attribute.getCount()I=a
+org/objectweb/asm/Attribute.getSize(Lorg/objectweb/asm/ClassWriter;[BIII)I=a
+org/objectweb/asm/Attribute.put(Lorg/objectweb/asm/ClassWriter;[BIIILorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/ByteVector.enlarge(I)V=a
+org/objectweb/asm/ByteVector.put11(II)Lorg/objectweb/asm/ByteVector;=a
+org/objectweb/asm/ByteVector.put12(II)Lorg/objectweb/asm/ByteVector;=b
+
+org/objectweb/asm/ClassReader.copyPool(Lorg/objectweb/asm/ClassWriter;)V=a
+org/objectweb/asm/ClassReader.copyBootstrapMethods(Lorg/objectweb/asm/ClassWriter;[Lorg/objectweb/asm/Item;[C)V=a
+org/objectweb/asm/ClassReader.readField(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readMethod(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/Context;I)I=b
+org/objectweb/asm/ClassReader.readCode(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;I)V=a
+org/objectweb/asm/ClassReader.readTypeAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)[I=a
+org/objectweb/asm/ClassReader.readAnnotationTarget(Lorg/objectweb/asm/Context;I)I=a
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=a
+org/objectweb/asm/ClassReader.getAttributes()I=a
+org/objectweb/asm/ClassReader.readAttribute([Lorg/objectweb/asm/Attribute;Ljava/lang/String;II[CI[Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Attribute;=a
+org/objectweb/asm/ClassReader.readClass(Ljava/io/InputStream;Z)[B=a
+org/objectweb/asm/ClassReader.readParameterAnnotations(Lorg/objectweb/asm/MethodVisitor;Lorg/objectweb/asm/Context;IZ)V=b
+org/objectweb/asm/ClassReader.readUTF(II[C)Ljava/lang/String;=a
+org/objectweb/asm/ClassReader.getImplicitFrame(Lorg/objectweb/asm/Context;)V=a
+org/objectweb/asm/ClassReader.readFrame(IZZLorg/objectweb/asm/Context;)I=a
+org/objectweb/asm/ClassReader.readFrameType([Ljava/lang/Object;II[C[Lorg/objectweb/asm/Label;)I=a
+
+org/objectweb/asm/ClassWriter.get(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newClassItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newConstItem(Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newDouble(D)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newFloat(F)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInteger(I)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newLong(J)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newString(Ljava/lang/String;)Lorg/objectweb/asm/Item;=b
+org/objectweb/asm/ClassWriter.put122(III)V=a
+org/objectweb/asm/ClassWriter.put112(III)V=b
+org/objectweb/asm/ClassWriter.put(Lorg/objectweb/asm/Item;)V=b
+org/objectweb/asm/ClassWriter.newFieldItem(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.addType(Ljava/lang/String;)I=c
+org/objectweb/asm/ClassWriter.addUninitializedType(Ljava/lang/String;I)I=a
+org/objectweb/asm/ClassWriter.addType(Lorg/objectweb/asm/Item;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.getMergedType(II)I=a
+org/objectweb/asm/ClassWriter.newNameTypeItem(Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newMethodTypeItem(Ljava/lang/String;)Lorg/objectweb/asm/Item;=c
+org/objectweb/asm/ClassWriter.newHandleItem(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/objectweb/asm/Item;=a
+org/objectweb/asm/ClassWriter.newInvokeDynamicItem(Ljava/lang/String;Ljava/lang/String;Lorg/objectweb/asm/Handle;[Ljava/lang/Object;)Lorg/objectweb/asm/Item;=a
+
+org/objectweb/asm/FieldWriter.getSize()I=a
+org/objectweb/asm/FieldWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+
+org/objectweb/asm/Item.isEqualTo(Lorg/objectweb/asm/Item;)Z=a
+org/objectweb/asm/Item.set(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V=a
+org/objectweb/asm/Item.set(D)V=a
+org/objectweb/asm/Item.set(F)V=a
+org/objectweb/asm/Item.set(I)V=a
+org/objectweb/asm/Item.set(J)V=a
+org/objectweb/asm/Item.set(Ljava/lang/String;Ljava/lang/String;I)V=a
+org/objectweb/asm/Item.set(II)V=a
+
+org/objectweb/asm/Label.addReference(II)V=a
+org/objectweb/asm/Label.put(Lorg/objectweb/asm/MethodWriter;Lorg/objectweb/asm/ByteVector;IZ)V=a
+org/objectweb/asm/Label.resolve(Lorg/objectweb/asm/MethodWriter;I[B)Z=a
+org/objectweb/asm/Label.getFirst()Lorg/objectweb/asm/Label;=a
+org/objectweb/asm/Label.inSubroutine(J)Z=a
+org/objectweb/asm/Label.inSameSubroutine(Lorg/objectweb/asm/Label;)Z=a
+org/objectweb/asm/Label.addToSubroutine(JI)V=a
+org/objectweb/asm/Label.visitSubroutine(Lorg/objectweb/asm/Label;JI)V=b
+
+org/objectweb/asm/Frame.get(I)I=a
+org/objectweb/asm/Frame.set(II)V=a
+org/objectweb/asm/Frame.push(I)V=b
+org/objectweb/asm/Frame.push(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.type(Lorg/objectweb/asm/ClassWriter;Ljava/lang/String;)I=b
+org/objectweb/asm/Frame.pop()I=a
+org/objectweb/asm/Frame.pop(Ljava/lang/String;)V=a
+org/objectweb/asm/Frame.pop(I)V=c
+org/objectweb/asm/Frame.init(I)V=d
+org/objectweb/asm/Frame.init(Lorg/objectweb/asm/ClassWriter;I)I=a
+org/objectweb/asm/Frame.initInputFrame(Lorg/objectweb/asm/ClassWriter;I[Lorg/objectweb/asm/Type;I)V=a
+org/objectweb/asm/Frame.execute(IILorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Item;)V=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;Lorg/objectweb/asm/Frame;I)Z=a
+org/objectweb/asm/Frame.merge(Lorg/objectweb/asm/ClassWriter;I[II)Z=a
+
+org/objectweb/asm/Handler.remove(Lorg/objectweb/asm/Handler;Lorg/objectweb/asm/Label;Lorg/objectweb/asm/Label;)Lorg/objectweb/asm/Handler;=a
+
+org/objectweb/asm/MethodWriter.visitSwitchInsn(Lorg/objectweb/asm/Label;[Lorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.addSuccessor(ILorg/objectweb/asm/Label;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[III)I=a
+org/objectweb/asm/MethodWriter.getSize()I=a
+org/objectweb/asm/MethodWriter.put(Lorg/objectweb/asm/ByteVector;)V=a
+org/objectweb/asm/MethodWriter.readInt([BI)I=a
+org/objectweb/asm/MethodWriter.readShort([BI)S=b
+org/objectweb/asm/MethodWriter.readUnsignedShort([BI)I=c
+org/objectweb/asm/MethodWriter.writeShort([BII)V=a
+org/objectweb/asm/MethodWriter.visitFrame(Lorg/objectweb/asm/Frame;)V=b
+org/objectweb/asm/MethodWriter.visitImplicitFirstFrame()V=f
+org/objectweb/asm/MethodWriter.startFrame(III)I=a
+org/objectweb/asm/MethodWriter.endFrame()V=b
+org/objectweb/asm/MethodWriter.writeFrame()V=c
+org/objectweb/asm/MethodWriter.resizeInstructions()V=d
+org/objectweb/asm/MethodWriter.noSuccessor()V=e
+org/objectweb/asm/MethodWriter.writeFrameTypes(II)V=a
+org/objectweb/asm/MethodWriter.writeFrameType(Ljava/lang/Object;)V=a
+org/objectweb/asm/MethodWriter.getNewOffset([I[ILorg/objectweb/asm/Label;)V=a
+
+org/objectweb/asm/Type.getType([CI)Lorg/objectweb/asm/Type;=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;)V=a
+org/objectweb/asm/Type.getDescriptor(Ljava/lang/StringBuffer;Ljava/lang/Class;)V=a
+
+org/objectweb/asm/signature/SignatureReader.parseType(Ljava/lang/String;ILorg/objectweb/asm/signature/SignatureVisitor;)I=a
+
+org/objectweb/asm/signature/SignatureWriter.endFormals()V=a
+org/objectweb/asm/signature/SignatureWriter.endArguments()V=b
+
\ 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/signature/SignatureReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
index b72fde6..b5b2c45 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureReader.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm.signature;
/**
* A type signature parser to make a signature visitor visit an existing
* signature.
- *
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -45,9 +45,10 @@ public class SignatureReader {
/**
* Constructs a {@link SignatureReader} for the given signature.
- *
- * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
- * or <i>FieldTypeSignature</i>.
+ *
+ * @param signature
+ * A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or
+ * <i>FieldTypeSignature</i>.
*/
public SignatureReader(final String signature) {
this.signature = signature;
@@ -58,15 +59,15 @@ public class SignatureReader {
* {@link SignatureReader}. This signature is the one specified in the
* constructor (see {@link #SignatureReader(String) SignatureReader}). This
* method is intended to be called on a {@link SignatureReader} that was
- * created using a <i>ClassSignature</i> (such as the
+ * created using a <i>ClassSignature</i> (such as the <code>signature</code>
+ * parameter of the {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit
+ * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the
* <code>signature</code> parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit ClassVisitor.visit} method)
- * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
- * parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
- * method).
- *
- * @param v the visitor that must visit this signature.
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod
+ * ClassVisitor.visitMethod} method).
+ *
+ * @param v
+ * the visitor that must visit this signature.
*/
public void accept(final SignatureVisitor v) {
String signature = this.signature;
@@ -118,12 +119,12 @@ public class SignatureReader {
* method is intended to be called on a {@link SignatureReader} that was
* created using a <i>FieldTypeSignature</i>, such as the
* <code>signature</code> parameter of the
- * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField
- * ClassVisitor.visitField} or {@link
- * org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField ClassVisitor.visitField}
+ * or {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable
* MethodVisitor.visitLocalVariable} methods.
- *
- * @param v the visitor that must visit this signature.
+ *
+ * @param v
+ * the visitor that must visit this signature.
*/
public void acceptType(final SignatureVisitor v) {
parseType(this.signature, 0, v);
@@ -131,99 +132,97 @@ public class SignatureReader {
/**
* Parses a field type signature and makes the given visitor visit it.
- *
- * @param signature a string containing the signature that must be parsed.
- * @param pos index of the first character of the signature to parsed.
- * @param v the visitor that must visit this signature.
+ *
+ * @param signature
+ * a string containing the signature that must be parsed.
+ * @param pos
+ * index of the first character of the signature to parsed.
+ * @param v
+ * the visitor that must visit this signature.
* @return the index of the first character after the parsed signature.
*/
- private static int parseType(
- final String signature,
- int pos,
- final SignatureVisitor v)
- {
+ private static int parseType(final String signature, int pos,
+ final SignatureVisitor v) {
char c;
int start, end;
boolean visited, inner;
String name;
switch (c = signature.charAt(pos++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- case 'F':
- case 'J':
- case 'D':
- case 'V':
- v.visitBaseType(c);
- return pos;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'V':
+ v.visitBaseType(c);
+ return pos;
- case '[':
- return parseType(signature, pos, v.visitArrayType());
+ case '[':
+ return parseType(signature, pos, v.visitArrayType());
- case 'T':
- end = signature.indexOf(';', pos);
- v.visitTypeVariable(signature.substring(pos, end));
- return end + 1;
+ case 'T':
+ end = signature.indexOf(';', pos);
+ v.visitTypeVariable(signature.substring(pos, end));
+ return end + 1;
- default: // case 'L':
- start = pos;
- visited = false;
- inner = false;
- for (;;) {
- switch (c = signature.charAt(pos++)) {
- case '.':
- case ';':
- if (!visited) {
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- }
- if (c == ';') {
- v.visitEnd();
- return pos;
- }
- start = pos;
- visited = false;
- inner = true;
- break;
+ default: // case 'L':
+ start = pos;
+ visited = false;
+ inner = false;
+ for (;;) {
+ switch (c = signature.charAt(pos++)) {
+ case '.':
+ case ';':
+ if (!visited) {
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ }
+ if (c == ';') {
+ v.visitEnd();
+ return pos;
+ }
+ start = pos;
+ visited = false;
+ inner = true;
+ break;
- case '<':
- name = signature.substring(start, pos - 1);
- if (inner) {
- v.visitInnerClassType(name);
- } else {
- v.visitClassType(name);
- }
- visited = true;
- top: for (;;) {
- switch (c = signature.charAt(pos)) {
- case '>':
- break top;
- case '*':
- ++pos;
- v.visitTypeArgument();
- break;
- case '+':
- case '-':
- pos = parseType(signature,
- pos + 1,
- v.visitTypeArgument(c));
- break;
- default:
- pos = parseType(signature,
- pos,
- v.visitTypeArgument('='));
- break;
- }
- }
+ case '<':
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ visited = true;
+ top: for (;;) {
+ switch (c = signature.charAt(pos)) {
+ case '>':
+ break top;
+ case '*':
+ ++pos;
+ v.visitTypeArgument();
+ break;
+ case '+':
+ case '-':
+ pos = parseType(signature, pos + 1,
+ v.visitTypeArgument(c));
+ break;
+ default:
+ pos = parseType(signature, pos,
+ v.visitTypeArgument('='));
+ break;
+ }
}
}
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
index 14e9ccb..941980f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureVisitor.java
@@ -35,22 +35,22 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
* A visitor to visit a generic signature. The methods of this interface must be
* called in one of the three following orders (the last one is the only valid
* order for a {@link SignatureVisitor} that is returned by a method of this
- * interface): <ul> <li><i>ClassSignature</i> = (
- * <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
- * <tt>visitInterface</tt>* )</li>
+ * interface):
+ * <ul>
+ * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitSuperClass</tt> <tt>visitInterface</tt>* )</li>
* <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
- * <tt>visitClassBound</tt>?
- * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
- * <tt>visitReturnType</tt>
- * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
- * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
- * <tt>visitArrayType</tt> | (
+ * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (
+ * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li>
+ * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |
+ * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (
* <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
- * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
- * <tt>visitEnd</tt> ) )</li> </ul>
- *
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>
+ * ) )</li>
+ * </ul>
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -73,31 +73,36 @@ public abstract class SignatureVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
/**
* Constructs a new {@link SignatureVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public SignatureVisitor(final int api) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
this.api = api;
}
/**
* Visits a formal type parameter.
- *
- * @param name the name of the formal parameter.
+ *
+ * @param name
+ * the name of the formal parameter.
*/
public void visitFormalTypeParameter(String name) {
}
/**
* Visits the class bound of the last visited formal type parameter.
- *
+ *
* @return a non null visitor to visit the signature of the class bound.
*/
public SignatureVisitor visitClassBound() {
@@ -106,7 +111,7 @@ public abstract class SignatureVisitor {
/**
* Visits an interface bound of the last visited formal type parameter.
- *
+ *
* @return a non null visitor to visit the signature of the interface bound.
*/
public SignatureVisitor visitInterfaceBound() {
@@ -115,7 +120,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of the super class.
- *
+ *
* @return a non null visitor to visit the signature of the super class
* type.
*/
@@ -125,7 +130,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of an interface implemented by the class.
- *
+ *
* @return a non null visitor to visit the signature of the interface type.
*/
public SignatureVisitor visitInterface() {
@@ -134,7 +139,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of a method parameter.
- *
+ *
* @return a non null visitor to visit the signature of the parameter type.
*/
public SignatureVisitor visitParameterType() {
@@ -143,7 +148,7 @@ public abstract class SignatureVisitor {
/**
* Visits the return type of the method.
- *
+ *
* @return a non null visitor to visit the signature of the return type.
*/
public SignatureVisitor visitReturnType() {
@@ -152,7 +157,7 @@ public abstract class SignatureVisitor {
/**
* Visits the type of a method exception.
- *
+ *
* @return a non null visitor to visit the signature of the exception type.
*/
public SignatureVisitor visitExceptionType() {
@@ -161,24 +166,26 @@ public abstract class SignatureVisitor {
/**
* Visits a signature corresponding to a primitive type.
- *
- * @param descriptor the descriptor of the primitive type, or 'V' for
- * <tt>void</tt>.
+ *
+ * @param descriptor
+ * the descriptor of the primitive type, or 'V' for <tt>void</tt>
+ * .
*/
public void visitBaseType(char descriptor) {
}
/**
* Visits a signature corresponding to a type variable.
- *
- * @param name the name of the type variable.
+ *
+ * @param name
+ * the name of the type variable.
*/
public void visitTypeVariable(String name) {
}
/**
* Visits a signature corresponding to an array type.
- *
+ *
* @return a non null visitor to visit the signature of the array element
* type.
*/
@@ -189,16 +196,18 @@ public abstract class SignatureVisitor {
/**
* Starts the visit of a signature corresponding to a class or interface
* type.
- *
- * @param name the internal name of the class or interface.
+ *
+ * @param name
+ * the internal name of the class or interface.
*/
public void visitClassType(String name) {
}
/**
* Visits an inner class.
- *
- * @param name the local name of the inner class in its enclosing class.
+ *
+ * @param name
+ * the local name of the inner class in its enclosing class.
*/
public void visitInnerClassType(String name) {
}
@@ -212,8 +221,9 @@ public abstract class SignatureVisitor {
/**
* Visits a type argument of the last visited class or inner class type.
- *
- * @param wildcard '+', '-' or '='.
+ *
+ * @param wildcard
+ * '+', '-' or '='.
* @return a non null visitor to visit the signature of the type argument.
*/
public SignatureVisitor visitTypeArgument(char wildcard) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
index 841fdad..d1e6bac 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/signature/SignatureWriter.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
* A signature visitor that generates signatures in string format.
- *
+ *
* @author Thomas Hallgren
* @author Eric Bruneton
*/
@@ -66,7 +66,7 @@ public class SignatureWriter extends SignatureVisitor {
* Constructs a new {@link SignatureWriter} object.
*/
public SignatureWriter() {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
}
// ------------------------------------------------------------------------
@@ -193,7 +193,7 @@ public class SignatureWriter extends SignatureVisitor {
/**
* Returns the signature that was built by this signature writer.
- *
+ *
* @return the signature that was built by this signature writer.
*/
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
index 32dc008..a6a01d6 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AbstractInsnNode.java
@@ -29,15 +29,16 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a bytecode instruction. <i>An instruction can appear
* at most once in at most one {@link InsnList} at a time</i>.
- *
+ *
* @author Eric Bruneton
*/
public abstract class AbstractInsnNode {
@@ -128,6 +129,28 @@ public abstract class AbstractInsnNode {
protected int opcode;
/**
+ * The runtime visible type annotations of this instruction. This field is
+ * only used for real instructions (i.e. not for labels, frames, or line
+ * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
+ * May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this instruction. This field is
+ * only used for real instructions (i.e. not for labels, frames, or line
+ * number nodes). This list is a list of {@link TypeAnnotationNode} objects.
+ * May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* Previous instruction in the list to which this instruction belongs.
*/
AbstractInsnNode prev;
@@ -147,8 +170,9 @@ public abstract class AbstractInsnNode {
/**
* Constructs a new {@link AbstractInsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed.
*/
protected AbstractInsnNode(final int opcode) {
this.opcode = opcode;
@@ -157,7 +181,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the opcode of this instruction.
- *
+ *
* @return the opcode of this instruction.
*/
public int getOpcode() {
@@ -166,7 +190,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the type of this instruction.
- *
+ *
* @return the type of this instruction, i.e. one the constants defined in
* this class.
*/
@@ -175,7 +199,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the previous instruction in the list to which this instruction
* belongs, if any.
- *
+ *
* @return the previous instruction in the list to which this instruction
* belongs, if any. May be <tt>null</tt>.
*/
@@ -186,7 +210,7 @@ public abstract class AbstractInsnNode {
/**
* Returns the next instruction in the list to which this instruction
* belongs, if any.
- *
+ *
* @return the next instruction in the list to which this instruction
* belongs, if any. May be <tt>null</tt>.
*/
@@ -196,43 +220,107 @@ public abstract class AbstractInsnNode {
/**
* Makes the given code visitor visit this instruction.
- *
- * @param cv a code visitor.
+ *
+ * @param cv
+ * a code visitor.
*/
public abstract void accept(final MethodVisitor cv);
/**
+ * Makes the given visitor visit the annotations of this instruction.
+ *
+ * @param mv
+ * a method visitor.
+ */
+ protected final void acceptAnnotations(final MethodVisitor mv) {
+ int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitInsnAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
+ }
+
+ /**
* Returns a copy of this instruction.
- *
- * @param labels a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param labels
+ * a map from LabelNodes to cloned LabelNodes.
* @return a copy of this instruction. The returned instruction does not
* belong to any {@link InsnList}.
*/
- public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels);
+ public abstract AbstractInsnNode clone(
+ final Map<LabelNode, LabelNode> labels);
/**
* Returns the clone of the given label.
- *
- * @param label a label.
- * @param map a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param label
+ * a label.
+ * @param map
+ * a map from LabelNodes to cloned LabelNodes.
* @return the clone of the given label.
*/
- static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
+ static LabelNode clone(final LabelNode label,
+ final Map<LabelNode, LabelNode> map) {
return map.get(label);
}
/**
* Returns the clones of the given labels.
- *
- * @param labels a list of labels.
- * @param map a map from LabelNodes to cloned LabelNodes.
+ *
+ * @param labels
+ * a list of labels.
+ * @param map
+ * a map from LabelNodes to cloned LabelNodes.
* @return the clones of the given labels.
*/
- static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) {
+ static LabelNode[] clone(final List<LabelNode> labels,
+ final Map<LabelNode, LabelNode> map) {
LabelNode[] clones = new LabelNode[labels.size()];
for (int i = 0; i < clones.length; ++i) {
clones[i] = map.get(labels.get(i));
}
return clones;
}
+
+ /**
+ * Clones the annotations of the given instruction into this instruction.
+ *
+ * @param insn
+ * the source instruction.
+ * @return this instruction.
+ */
+ protected final AbstractInsnNode cloneAnnotations(
+ final AbstractInsnNode insn) {
+ if (insn.visibleTypeAnnotations != null) {
+ this.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0; i < insn.visibleTypeAnnotations.size(); ++i) {
+ TypeAnnotationNode src = insn.visibleTypeAnnotations.get(i);
+ TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+ src.typePath, src.desc);
+ src.accept(ann);
+ this.visibleTypeAnnotations.add(ann);
+ }
+ }
+ if (insn.invisibleTypeAnnotations != null) {
+ this.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>();
+ for (int i = 0; i < insn.invisibleTypeAnnotations.size(); ++i) {
+ TypeAnnotationNode src = insn.invisibleTypeAnnotations.get(i);
+ TypeAnnotationNode ann = new TypeAnnotationNode(src.typeRef,
+ src.typePath, src.desc);
+ src.accept(ann);
+ this.invisibleTypeAnnotations.add(ann);
+ }
+ }
+ return this;
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
index 2fe5b77..9d07669 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/AnnotationNode.java
@@ -29,19 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents an annotationn.
*
* @author Eric Bruneton
*/
-public class AnnotationNode extends AnnotationVisitor
-{
+public class AnnotationNode extends AnnotationVisitor {
/**
* The class descriptor of the annotation class.
@@ -56,8 +55,8 @@ public class AnnotationNode extends AnnotationVisitor
* {@link Double}, {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an
* two elements String array (for enumeration values), a
* {@link AnnotationNode}, or a {@link List} of values of one of the
- * preceding types. The list may be <tt>null</tt> if there is no name
- * value pair.
+ * preceding types. The list may be <tt>null</tt> if there is no name value
+ * pair.
*/
public List<Object> values;
@@ -66,18 +65,26 @@ public class AnnotationNode extends AnnotationVisitor
* constructor</i>. Instead, they must use the
* {@link #AnnotationNode(int, String)} version.
*
- * @param desc the class descriptor of the annotation class.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public AnnotationNode(final String desc) {
- this(Opcodes.ASM4, desc);
+ this(Opcodes.ASM5, desc);
+ if (getClass() != AnnotationNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link AnnotationNode}.
*
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param desc the class descriptor of the annotation class.
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param desc
+ * the class descriptor of the annotation class.
*/
public AnnotationNode(final int api, final String desc) {
super(api);
@@ -87,10 +94,11 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Constructs a new {@link AnnotationNode} to visit an array value.
*
- * @param values where the visited values must be stored.
+ * @param values
+ * where the visited values must be stored.
*/
AnnotationNode(final List<Object> values) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
this.values = values;
}
@@ -110,11 +118,8 @@ public class AnnotationNode extends AnnotationVisitor
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
if (values == null) {
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
@@ -125,10 +130,8 @@ public class AnnotationNode extends AnnotationVisitor
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
if (values == null) {
values = new ArrayList<Object>(this.desc != null ? 2 : 1);
}
@@ -167,7 +170,9 @@ public class AnnotationNode extends AnnotationVisitor
* recursively, do not contain elements that were introduced in more recent
* versions of the ASM API than the given version.
*
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
// nothing to do
@@ -176,7 +181,8 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Makes the given visitor visit this annotation.
*
- * @param av an annotation visitor. Maybe <tt>null</tt>.
+ * @param av
+ * an annotation visitor. Maybe <tt>null</tt>.
*/
public void accept(final AnnotationVisitor av) {
if (av != null) {
@@ -194,15 +200,15 @@ public class AnnotationNode extends AnnotationVisitor
/**
* Makes the given visitor visit a given annotation value.
*
- * @param av an annotation visitor. Maybe <tt>null</tt>.
- * @param name the value name.
- * @param value the actual value.
+ * @param av
+ * an annotation visitor. Maybe <tt>null</tt>.
+ * @param name
+ * the value name.
+ * @param value
+ * the actual value.
*/
- static void accept(
- final AnnotationVisitor av,
- final String name,
- final Object value)
- {
+ public static void accept(final AnnotationVisitor av, final String name,
+ final Object value) {
if (av != null) {
if (value instanceof String[]) {
String[] typeconst = (String[]) value;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
index 7bda1ab..0bdcc54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ClassNode.java
@@ -29,15 +29,21 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A node that represents a class.
- *
+ *
* @author Eric Bruneton
*/
public class ClassNode extends ClassVisitor {
@@ -60,15 +66,15 @@ public class ClassNode extends ClassVisitor {
public String name;
/**
- * The signature of the class. Mayt be <tt>null</tt>.
+ * The signature of the class. May be <tt>null</tt>.
*/
public String signature;
/**
* The internal of name of the super class (see
* {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). For
- * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
- * but only for the {@link Object} class.
+ * interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
+ * only for the {@link Object} class.
*/
public String superName;
@@ -86,7 +92,7 @@ public class ClassNode extends ClassVisitor {
public String sourceFile;
/**
- * Debug information to compute the correspondance between source and
+ * Debug information to compute the correspondence between source and
* compiled elements of the class. May be <tt>null</tt>.
*/
public String sourceDebug;
@@ -104,16 +110,16 @@ public class ClassNode extends ClassVisitor {
public String outerMethod;
/**
- * The descriptor of the method that contains the class, or <tt>null</tt>
- * if the class is not enclosed in a method.
+ * The descriptor of the method that contains the class, or <tt>null</tt> if
+ * the class is not enclosed in a method.
*/
public String outerMethodDesc;
/**
* The runtime visible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -121,41 +127,59 @@ public class ClassNode extends ClassVisitor {
/**
* The runtime invisible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this class. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this class. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this class. This list is a list of
* {@link Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
/**
* Informations about the inner classes of this class. This list is a list
* of {@link InnerClassNode} objects.
- *
- * @associates InnerClassNode
+ *
+ * @associates org.objectweb.asm.tree.InnerClassNode
*/
public List<InnerClassNode> innerClasses;
/**
* The fields of this class. This list is a list of {@link FieldNode}
* objects.
- *
- * @associates FieldNode
+ *
+ * @associates org.objectweb.asm.tree.FieldNode
*/
public List<FieldNode> fields;
/**
* The methods of this class. This list is a list of {@link MethodNode}
* objects.
- *
- * @associates MethodNode
+ *
+ * @associates org.objectweb.asm.tree.MethodNode
*/
public List<MethodNode> methods;
@@ -163,16 +187,23 @@ public class ClassNode extends ClassVisitor {
* Constructs a new {@link ClassNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #ClassNode(int)}
* version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public ClassNode() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != ClassNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link ClassNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public ClassNode(final int api) {
super(api);
@@ -187,14 +218,9 @@ public class ClassNode extends ClassVisitor {
// ------------------------------------------------------------------------
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
this.version = version;
this.access = access;
this.name = name;
@@ -212,21 +238,16 @@ public class ClassNode extends ClassVisitor {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
outerClass = owner;
outerMethod = name;
outerMethodDesc = desc;
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -243,6 +264,24 @@ public class ClassNode extends ClassVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
attrs = new ArrayList<Attribute>(1);
@@ -251,44 +290,25 @@ public class ClassNode extends ClassVisitor {
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
- InnerClassNode icn = new InnerClassNode(name,
- outerName,
- innerName,
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ InnerClassNode icn = new InnerClassNode(name, outerName, innerName,
access);
innerClasses.add(icn);
}
@Override
- public FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
FieldNode fn = new FieldNode(access, name, desc, signature, value);
fields.add(fn);
return fn;
}
@Override
- public MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- MethodNode mn = new MethodNode(access,
- name,
- desc,
- signature,
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ MethodNode mn = new MethodNode(access, name, desc, signature,
exceptions);
methods.add(mn);
return mn;
@@ -307,17 +327,35 @@ public class ClassNode extends ClassVisitor {
* This methods checks that this node, and all its nodes recursively, do not
* contain elements that were introduced in more recent versions of the ASM
* API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ for (FieldNode f : fields) {
+ f.check(api);
+ }
+ for (MethodNode m : methods) {
+ m.check(api);
+ }
+ }
}
/**
* Makes the given class visitor visit this class.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
// visits header
@@ -344,6 +382,19 @@ public class ClassNode extends ClassVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(cv.visitAnnotation(an.desc, false));
}
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(cv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
cv.visitAttribute(attrs.get(i));
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
index 265fb1e..848d05d 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a field instruction. A field instruction is an
* instruction that loads or stores the value of a field of an object.
- *
+ *
* @author Eric Bruneton
*/
public class FieldInsnNode extends AbstractInsnNode {
@@ -59,20 +59,21 @@ public class FieldInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link FieldInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner the internal name of the field's owner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner
+ * the internal name of the field's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
*/
- public FieldInsnNode(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public FieldInsnNode(final int opcode, final String owner,
+ final String name, final String desc) {
super(opcode);
this.owner = owner;
this.name = name;
@@ -81,9 +82,10 @@ public class FieldInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
- * PUTSTATIC, GETFIELD or PUTFIELD.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be GETSTATIC,
+ * PUTSTATIC, GETFIELD or PUTFIELD.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -95,12 +97,14 @@ public class FieldInsnNode extends AbstractInsnNode {
}
@Override
- public void accept(final MethodVisitor cv) {
- cv.visitFieldInsn(opcode, owner, name, desc);
+ public void accept(final MethodVisitor mv) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new FieldInsnNode(opcode, owner, name, desc);
+ return new FieldInsnNode(opcode, owner, name, desc)
+ .cloneAnnotations(this);
}
}
[22/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
index 4801b61..4b9c65e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ClassReader.java
@@ -37,7 +37,7 @@ import java.io.InputStream;
* This class parses a byte array conforming to the Java class file format and
* calls the appropriate visit methods of a given class visitor for each field,
* method and bytecode instruction encountered.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -112,9 +112,8 @@ public class ClassReader {
public final byte[] b;
/**
- * The start index of each constant pool item in {@link #b b}, plus one.
- * The one byte offset skips the constant pool item tag that indicates its
- * type.
+ * The start index of each constant pool item in {@link #b b}, plus one. The
+ * one byte offset skips the constant pool item tag that indicates its type.
*/
private final int[] items;
@@ -146,8 +145,9 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
+ *
+ * @param b
+ * the bytecode of the class to be read.
*/
public ClassReader(final byte[] b) {
this(b, 0, b.length);
@@ -155,15 +155,18 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- * @param off the start offset of the class data.
- * @param len the length of the class data.
+ *
+ * @param b
+ * the bytecode of the class to be read.
+ * @param off
+ * the start offset of the class data.
+ * @param len
+ * the length of the class data.
*/
public ClassReader(final byte[] b, final int off, final int len) {
this.b = b;
// checks the class version
- if (readShort(6) > Opcodes.V1_7) {
+ if (readShort(off + 6) > Opcodes.V1_8) {
throw new IllegalArgumentException();
}
// parses the constant pool
@@ -176,35 +179,35 @@ public class ClassReader {
items[i] = index + 1;
int size;
switch (b[index]) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- case ClassWriter.INDY:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- if (size > max) {
- max = size;
- }
- break;
- case ClassWriter.HANDLE:
- size = 4;
- break;
- // case ClassWriter.CLASS:
- // case ClassWriter.STR:
- // case ClassWriter.MTYPE
- default:
- size = 3;
- break;
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ case ClassWriter.NAME_TYPE:
+ case ClassWriter.INDY:
+ size = 5;
+ break;
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8:
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max) {
+ max = size;
+ }
+ break;
+ case ClassWriter.HANDLE:
+ size = 4;
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ // case ClassWriter.MTYPE
+ default:
+ size = 3;
+ break;
}
index += size;
}
@@ -217,9 +220,9 @@ public class ClassReader {
* Returns the class's access flags (see {@link Opcodes}). This value may
* not reflect Deprecated and Synthetic flags when bytecode is before 1.5
* and those flags are represented by attributes.
- *
+ *
* @return the class access flags
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public int getAccess() {
@@ -229,9 +232,9 @@ public class ClassReader {
/**
* Returns the internal name of the class (see
* {@link Type#getInternalName() getInternalName}).
- *
+ *
* @return the internal class name
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String getClassName() {
@@ -242,24 +245,23 @@ public class ClassReader {
* Returns the internal of name of the super class (see
* {@link Type#getInternalName() getInternalName}). For interfaces, the
* super class is {@link Object}.
- *
+ *
* @return the internal name of super class, or <tt>null</tt> for
* {@link Object} class.
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String getSuperName() {
- int n = items[readUnsignedShort(header + 4)];
- return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+ return readClass(header + 4, new char[maxStringLength]);
}
/**
* Returns the internal names of the class's interfaces (see
* {@link Type#getInternalName() getInternalName}).
- *
+ *
* @return the array of internal names for all implemented interfaces or
* <tt>null</tt>.
- *
+ *
* @see ClassVisitor#visit(int, int, String, String, String, String[])
*/
public String[] getInterfaces() {
@@ -279,8 +281,9 @@ public class ClassReader {
/**
* Copies the constant pool data into the given {@link ClassWriter}. Should
* be called before the {@link #accept(ClassVisitor,int)} method.
- *
- * @param classWriter the {@link ClassWriter} to copy constant pool into.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy constant pool into.
*/
void copyPool(final ClassWriter classWriter) {
char[] buf = new char[maxStringLength];
@@ -292,82 +295,63 @@ public class ClassReader {
Item item = new Item(i);
int nameType;
switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- nameType = items[readUnsignedShort(index + 2)];
- item.set(tag,
- readClass(index, buf),
- readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
- break;
-
- case ClassWriter.INT:
- item.set(readInt(index));
- break;
-
- case ClassWriter.FLOAT:
- item.set(Float.intBitsToFloat(readInt(index)));
- break;
-
- case ClassWriter.NAME_TYPE:
- item.set(tag,
- readUTF8(index, buf),
- readUTF8(index + 2, buf),
- null);
- break;
-
- case ClassWriter.LONG:
- item.set(readLong(index));
- ++i;
- break;
-
- case ClassWriter.DOUBLE:
- item.set(Double.longBitsToDouble(readLong(index)));
- ++i;
- break;
-
- case ClassWriter.UTF8: {
- String s = strings[i];
- if (s == null) {
- index = items[i];
- s = strings[i] = readUTF(index + 2,
- readUnsignedShort(index),
- buf);
- }
- item.set(tag, s, null, null);
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+ break;
+ case ClassWriter.INT:
+ item.set(readInt(index));
+ break;
+ case ClassWriter.FLOAT:
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+ case ClassWriter.NAME_TYPE:
+ item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
+ null);
+ break;
+ case ClassWriter.LONG:
+ item.set(readLong(index));
+ ++i;
+ break;
+ case ClassWriter.DOUBLE:
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+ case ClassWriter.UTF8: {
+ String s = strings[i];
+ if (s == null) {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2,
+ readUnsignedShort(index), buf);
}
- break;
-
- case ClassWriter.HANDLE: {
- int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
- nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
- item.set(ClassWriter.HANDLE_BASE + readByte(index),
- readClass(fieldOrMethodRef, buf),
- readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf));
-
+ item.set(tag, s, null, null);
+ break;
+ }
+ case ClassWriter.HANDLE: {
+ int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+ nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+ item.set(ClassWriter.HANDLE_BASE + readByte(index),
+ readClass(fieldOrMethodRef, buf),
+ readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+ break;
+ }
+ case ClassWriter.INDY:
+ if (classWriter.bootstrapMethods == null) {
+ copyBootstrapMethods(classWriter, items2, buf);
}
- break;
-
-
- case ClassWriter.INDY:
- if (classWriter.bootstrapMethods == null) {
- copyBootstrapMethods(classWriter, items2, buf);
- }
- nameType = items[readUnsignedShort(index + 2)];
- item.set(readUTF8(nameType, buf),
- readUTF8(nameType + 2, buf),
- readUnsignedShort(index));
- break;
-
-
- // case ClassWriter.STR:
- // case ClassWriter.CLASS:
- // case ClassWriter.MTYPE
- default:
- item.set(tag, readUTF8(index, buf), null, null);
- break;
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
+ readUnsignedShort(index));
+ break;
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ // case ClassWriter.MTYPE
+ default:
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
}
int index2 = item.hashCode % items2.length;
@@ -382,77 +366,59 @@ public class ClassReader {
classWriter.index = ll;
}
- private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
- int i, j, k, u, v;
-
- // skip class header
- v = header;
- v += 8 + (readUnsignedShort(v + 6) << 1);
-
- // skips fields and methods
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
+ /**
+ * Copies the bootstrap method data into the given {@link ClassWriter}.
+ * Should be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy bootstrap methods into.
+ */
+ private void copyBootstrapMethods(final ClassWriter classWriter,
+ final Item[] items, final char[] c) {
+ // finds the "BootstrapMethods" attribute
+ int u = getAttributes();
+ boolean found = false;
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("BootstrapMethods".equals(attrName)) {
+ found = true;
+ break;
}
+ u += 6 + readInt(u + 4);
}
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
+ if (!found) {
+ return;
}
-
- // read class attributes
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- String attrName = readUTF8(v, buf);
- int size = readInt(v + 2);
- if ("BootstrapMethods".equals(attrName)) {
- int boostrapMethodCount = readUnsignedShort(v + 6);
- int x = v + 8;
- for (j = 0; j < boostrapMethodCount; j++) {
- int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
- k = readUnsignedShort(x + 2);
- u = x + 4;
- for(; k > 0; --k) {
- hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
- u += 2;
- }
- Item item = new Item(j);
- item.set(x - v - 8, hashCode & 0x7FFFFFFF);
-
- int index2 = item.hashCode % items2.length;
- item.next = items2[index2];
- items2[index2] = item;
-
- x = u;
- }
-
- classWriter.bootstrapMethodsCount = boostrapMethodCount;
- ByteVector bootstrapMethods = new ByteVector(size + 62);
- bootstrapMethods.putByteArray(b, v + 8, size - 2);
- classWriter.bootstrapMethods = bootstrapMethods;
- return;
+ // copies the bootstrap methods in the class writer
+ int boostrapMethodCount = readUnsignedShort(u + 8);
+ for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
+ int position = v - u - 10;
+ int hashCode = readConst(readUnsignedShort(v), c).hashCode();
+ for (int k = readUnsignedShort(v + 2); k > 0; --k) {
+ hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
+ v += 2;
}
- v += 6 + size;
+ v += 4;
+ Item item = new Item(j);
+ item.set(position, hashCode & 0x7FFFFFFF);
+ int index = item.hashCode % items.length;
+ item.next = items[index];
+ items[index] = item;
}
-
- // we are in trouble !!!
+ int attrSize = readInt(u + 4);
+ ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
+ bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
+ classWriter.bootstrapMethodsCount = boostrapMethodCount;
+ classWriter.bootstrapMethods = bootstrapMethods;
}
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param is an input stream from which to read the class.
- * @throws IOException if a problem occurs during reading.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @throws IOException
+ * if a problem occurs during reading.
*/
public ClassReader(final InputStream is) throws IOException {
this(readClass(is, false));
@@ -460,26 +426,31 @@ public class ClassReader {
/**
* Constructs a new {@link ClassReader} object.
- *
- * @param name the binary qualified name of the class to be read.
- * @throws IOException if an exception occurs during reading.
+ *
+ * @param name
+ * the binary qualified name of the class to be read.
+ * @throws IOException
+ * if an exception occurs during reading.
*/
public ClassReader(final String name) throws IOException {
- this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
- + ".class"), true));
+ this(readClass(
+ ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ + ".class"), true));
}
/**
* Reads the bytecode of a class.
- *
- * @param is an input stream from which to read the class.
- * @param close true to close the input stream after reading.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @param close
+ * true to close the input stream after reading.
* @return the bytecode read from the given input stream.
- * @throws IOException if a problem occurs during reading.
+ * @throws IOException
+ * if a problem occurs during reading.
*/
private static byte[] readClass(final InputStream is, boolean close)
- throws IOException
- {
+ throws IOException {
if (is == null) {
throw new IOException("Class not found");
}
@@ -520,14 +491,16 @@ public class ClassReader {
// ------------------------------------------------------------------------
/**
- * Makes the given visitor visit the Java class of this {@link ClassReader}.
- * This class is the one specified in the constructor (see
+ * Makes the given visitor visit the Java class of this {@link ClassReader}
+ * . This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
*/
public void accept(final ClassVisitor classVisitor, final int flags) {
accept(classVisitor, new Attribute[0], flags);
@@ -537,1118 +510,1220 @@ public class ClassReader {
* Makes the given visitor visit the Java class of this {@link ClassReader}.
* This class is the one specified in the constructor (see
* {@link #ClassReader(byte[]) ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the
- * type of one the prototypes will not be parsed: its byte array
- * value will be passed unchanged to the ClassWriter. <i>This may
- * corrupt it if this value contains references to the constant pool,
- * or has syntactic or semantic links with a class element that has
- * been transformed by a class adapter between the reader and the
- * writer</i>.
- * @param flags option flags that can be used to modify the default behavior
- * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
- * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param attrs
+ * prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to
+ * the type of one the prototypes will not be parsed: its byte
+ * array value will be passed unchanged to the ClassWriter.
+ * <i>This may corrupt it if this value contains references to
+ * the constant pool, or has syntactic or semantic links with a
+ * class element that has been transformed by a class adapter
+ * between the reader and the writer</i>.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
*/
- public void accept(
- final ClassVisitor classVisitor,
- final Attribute[] attrs,
- final int flags)
- {
- byte[] b = this.b; // the bytecode array
+ public void accept(final ClassVisitor classVisitor,
+ final Attribute[] attrs, final int flags) {
+ int u = header; // current offset in the class file
char[] c = new char[maxStringLength]; // buffer used to read strings
- int i, j, k; // loop variables
- int u, v, w; // indexes in b
- Attribute attr;
-
- int access;
- String name;
- String desc;
- String attrName;
- String signature;
- int anns = 0;
- int ianns = 0;
- Attribute cattrs = null;
-
- // visits the header
- u = header;
- access = readUnsignedShort(u);
- name = readClass(u + 2, c);
- v = items[readUnsignedShort(u + 4)];
- String superClassName = v == 0 ? null : readUTF8(v, c);
- String[] implementedItfs = new String[readUnsignedShort(u + 6)];
- w = 0;
+
+ Context context = new Context();
+ context.attrs = attrs;
+ context.flags = flags;
+ context.buffer = c;
+
+ // reads the class declaration
+ int access = readUnsignedShort(u);
+ String name = readClass(u + 2, c);
+ String superClass = readClass(u + 4, c);
+ String[] interfaces = new String[readUnsignedShort(u + 6)];
u += 8;
- for (i = 0; i < implementedItfs.length; ++i) {
- implementedItfs[i] = readClass(u, c);
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfaces[i] = readClass(u, c);
u += 2;
}
- boolean skipCode = (flags & SKIP_CODE) != 0;
- boolean skipDebug = (flags & SKIP_DEBUG) != 0;
- boolean unzip = (flags & EXPAND_FRAMES) != 0;
-
- // skips fields and methods
- v = u;
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for (; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- // reads the class's attributes
- signature = null;
+ // reads the class attributes
+ String signature = null;
String sourceFile = null;
String sourceDebug = null;
String enclosingOwner = null;
String enclosingName = null;
String enclosingDesc = null;
- int[] bootstrapMethods = null; // start indexed of the bsms
-
- i = readUnsignedShort(v);
- v += 2;
- for (; i > 0; --i) {
- attrName = readUTF8(v, c);
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int innerClasses = 0;
+ Attribute attributes = null;
+
+ u = getAttributes();
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
// tests are sorted in decreasing frequency order
// (based on frequencies observed on typical classes)
if ("SourceFile".equals(attrName)) {
- sourceFile = readUTF8(v + 6, c);
+ sourceFile = readUTF8(u + 8, c);
} else if ("InnerClasses".equals(attrName)) {
- w = v + 6;
+ innerClasses = u + 8;
} else if ("EnclosingMethod".equals(attrName)) {
- enclosingOwner = readClass(v + 6, c);
- int item = readUnsignedShort(v + 8);
+ enclosingOwner = readClass(u + 8, c);
+ int item = readUnsignedShort(u + 10);
if (item != 0) {
enclosingName = readUTF8(items[item], c);
enclosingDesc = readUTF8(items[item] + 2, c);
}
} else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(v + 6, c);
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = v + 6;
+ signature = readUTF8(u + 8, c);
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
} else if ("Deprecated".equals(attrName)) {
access |= Opcodes.ACC_DEPRECATED;
} else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
} else if ("SourceDebugExtension".equals(attrName)) {
- int len = readInt(v + 2);
- sourceDebug = readUTF(v + 6, len, new char[len]);
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = v + 6;
+ int len = readInt(u + 4);
+ sourceDebug = readUTF(u + 8, len, new char[len]);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
} else if ("BootstrapMethods".equals(attrName)) {
- int boostrapMethodCount = readUnsignedShort(v + 6);
- bootstrapMethods = new int[boostrapMethodCount];
- int x = v + 8;
- for (j = 0; j < boostrapMethodCount; j++) {
- bootstrapMethods[j] = x;
- x += 2 + readUnsignedShort(x + 2) << 1;
+ int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
+ for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
+ bootstrapMethods[j] = v;
+ v += 2 + readUnsignedShort(v + 2) << 1;
}
+ context.bootstrapMethods = bootstrapMethods;
} else {
- attr = readAttribute(attrs,
- attrName,
- v + 6,
- readInt(v + 2),
- c,
- -1,
- null);
+ Attribute attr = readAttribute(attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
+ attr.next = attributes;
+ attributes = attr;
}
}
- v += 6 + readInt(v + 2);
- }
- // calls the visit method
- classVisitor.visit(readInt(4),
- access,
- name,
- signature,
- superClassName,
- implementedItfs);
-
- // calls the visitSource method
- if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+ u += 6 + readInt(u + 4);
+ }
+
+ // visits the class declaration
+ classVisitor.visit(readInt(items[1] - 7), access, name, signature,
+ superClass, interfaces);
+
+ // visits the source and debug info
+ if ((flags & SKIP_DEBUG) == 0
+ && (sourceFile != null || sourceDebug != null)) {
classVisitor.visitSource(sourceFile, sourceDebug);
}
- // calls the visitOuterClass method
+ // visits the outer class
if (enclosingOwner != null) {
- classVisitor.visitOuterClass(enclosingOwner,
- enclosingName,
+ classVisitor.visitOuterClass(enclosingOwner, enclosingName,
enclosingDesc);
}
- // visits the class annotations
- if (ANNOTATIONS) {
- for (i = 1; i >= 0; --i) {
- v = i == 0 ? ianns : anns;
- if (v != 0) {
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
- }
- }
+ // visits the class annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
}
}
- // visits the class attributes
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- classVisitor.visitAttribute(cattrs);
- cattrs = attr;
+ // visits the attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ classVisitor.visitAttribute(attributes);
+ attributes = attr;
}
- // calls the visitInnerClass method
- if (w != 0) {
- i = readUnsignedShort(w);
- w += 2;
- for (; i > 0; --i) {
- classVisitor.visitInnerClass(readUnsignedShort(w) == 0
- ? null
- : readClass(w, c), readUnsignedShort(w + 2) == 0
- ? null
- : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
- ? null
- : readUTF8(w + 4, c), readUnsignedShort(w + 6));
- w += 8;
+ // visits the inner classes
+ if (innerClasses != 0) {
+ int v = innerClasses + 2;
+ for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
+ classVisitor.visitInnerClass(readClass(v, c),
+ readClass(v + 2, c), readUTF8(v + 4, c),
+ readUnsignedShort(v + 6));
+ v += 8;
}
}
- // visits the fields
- i = readUnsignedShort(u);
+ // visits the fields and methods
+ u = header + 10 + 2 * interfaces.length;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readField(classVisitor, context, u);
+ }
u += 2;
- for (; i > 0; --i) {
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- // visits the field's attributes and looks for a ConstantValue
- // attribute
- int fieldValueItem = 0;
- signature = null;
- anns = 0;
- ianns = 0;
- cattrs = null;
-
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("ConstantValue".equals(attrName)) {
- fieldValueItem = readUnsignedShort(u + 6);
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u + 6, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u + 6;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u + 6;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u + 6,
- readInt(u + 2),
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readMethod(classVisitor, context, u);
+ }
+
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
+
+ /**
+ * Reads a field and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the field.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the field in the class file.
+ * @return the offset of the first byte following the field in the class.
+ */
+ private int readField(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the field declaration
+ char[] c = context.buffer;
+ int access = readUnsignedShort(u);
+ String name = readUTF8(u + 2, c);
+ String desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the field attributes
+ String signature = null;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ Object value = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName)) {
+ int item = readUnsignedShort(u + 8);
+ value = item == 0 ? null : readConst(item, c);
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else {
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
- u += 6 + readInt(u + 2);
}
- // visits the field
- FieldVisitor fv = classVisitor.visitField(access,
- name,
- desc,
- signature,
- fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
- // visits the field annotations and attributes
- if (fv != null) {
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- v = j == 0 ? ianns : anns;
- if (v != 0) {
- k = readUnsignedShort(v);
- v += 2;
- for (; k > 0; --k) {
- v = readAnnotationValues(v + 2,
- c,
- true,
- fv.visitAnnotation(readUTF8(v, c), j != 0));
- }
- }
- }
- }
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- fv.visitAttribute(cattrs);
- cattrs = attr;
- }
- fv.visitEnd();
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // visits the field declaration
+ FieldVisitor fv = classVisitor.visitField(access, name, desc,
+ signature, value);
+ if (fv == null) {
+ return u;
+ }
+
+ // visits the field annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
}
}
- // visits the methods
- i = readUnsignedShort(u);
- u += 2;
- for (; i > 0; --i) {
- int u0 = u + 6;
- access = readUnsignedShort(u);
- name = readUTF8(u + 2, c);
- desc = readUTF8(u + 4, c);
- signature = null;
- anns = 0;
- ianns = 0;
- int dann = 0;
- int mpanns = 0;
- int impanns = 0;
- cattrs = null;
- v = 0;
- w = 0;
-
- // looks for Code and Exceptions attributes
- j = readUnsignedShort(u + 6);
- u += 8;
- for (; j > 0; --j) {
- attrName = readUTF8(u, c);
- int attrSize = readInt(u + 2);
- u += 6;
- // tests are sorted in decreasing frequency order
- // (based on frequencies observed on typical classes)
- if ("Code".equals(attrName)) {
- if (!skipCode) {
- v = u;
- }
- } else if ("Exceptions".equals(attrName)) {
- w = u;
- } else if (SIGNATURES && "Signature".equals(attrName)) {
- signature = readUTF8(u, c);
- } else if ("Deprecated".equals(attrName)) {
- access |= Opcodes.ACC_DEPRECATED;
- } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
- anns = u;
- } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
- dann = u;
- } else if ("Synthetic".equals(attrName)) {
- access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
- } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
- ianns = u;
- } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
- {
- mpanns = u;
- } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
- {
- impanns = u;
- } else {
- attr = readAttribute(attrs,
- attrName,
- u,
- attrSize,
- c,
- -1,
- null);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
+ // visits the field attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ fv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the end of the field
+ fv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads a method and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the method.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the method in the class file.
+ * @return the offset of the first byte following the method in the class.
+ */
+ private int readMethod(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the method declaration
+ char[] c = context.buffer;
+ context.access = readUnsignedShort(u);
+ context.name = readUTF8(u + 2, c);
+ context.desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the method attributes
+ int code = 0;
+ int exception = 0;
+ String[] exceptions = null;
+ String signature = null;
+ int methodParameters = 0;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ int firstAttribute = u;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName)) {
+ if ((context.flags & SKIP_CODE) == 0) {
+ code = u + 8;
}
- u += attrSize;
- }
- // reads declared exceptions
- String[] exceptions;
- if (w == 0) {
- exceptions = null;
+ } else if ("Exceptions".equals(attrName)) {
+ exceptions = new String[readUnsignedShort(u + 8)];
+ exception = u + 10;
+ for (int j = 0; j < exceptions.length; ++j) {
+ exceptions[j] = readClass(exception, c);
+ exception += 2;
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ context.access |= Opcodes.ACC_DEPRECATED;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+ dann = u + 8;
+ } else if ("Synthetic".equals(attrName)) {
+ context.access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
+ mpanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
+ impanns = u + 8;
+ } else if ("MethodParameters".equals(attrName)) {
+ methodParameters = u + 8;
} else {
- exceptions = new String[readUnsignedShort(w)];
- w += 2;
- for (j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(w, c);
- w += 2;
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
}
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
- // visits the method's code, if any
- MethodVisitor mv = classVisitor.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
+ // visits the method declaration
+ MethodVisitor mv = classVisitor.visitMethod(context.access,
+ context.name, context.desc, signature, exceptions);
+ if (mv == null) {
+ return u;
+ }
- if (mv != null) {
- /*
- * if the returned MethodVisitor is in fact a MethodWriter, it
- * means there is no method adapter between the reader and the
- * writer. If, in addition, the writer's constant pool was
- * copied from this reader (mw.cw.cr == this), and the signature
- * and exceptions of the method have not been changed, then it
- * is possible to skip all visit events and just copy the
- * original code of the method to the writer (the access, name
- * and descriptor can have been changed, this is not important
- * since they are not copied as is from the reader).
- */
- if (WRITER && mv instanceof MethodWriter) {
- MethodWriter mw = (MethodWriter) mv;
- if (mw.cw.cr == this) {
- if (signature == mw.signature) {
- boolean sameExceptions = false;
- if (exceptions == null) {
- sameExceptions = mw.exceptionCount == 0;
- } else {
- if (exceptions.length == mw.exceptionCount) {
- sameExceptions = true;
- for (j = exceptions.length - 1; j >= 0; --j)
- {
- w -= 2;
- if (mw.exceptions[j] != readUnsignedShort(w))
- {
- sameExceptions = false;
- break;
- }
- }
- }
- }
- if (sameExceptions) {
- /*
- * we do not copy directly the code into
- * MethodWriter to save a byte array copy
- * operation. The real copy will be done in
- * ClassWriter.toByteArray().
- */
- mw.classReaderOffset = u0;
- mw.classReaderLength = u - u0;
- continue;
- }
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it means
+ * there is no method adapter between the reader and the writer. If, in
+ * addition, the writer's constant pool was copied from this reader
+ * (mw.cw.cr == this), and the signature and exceptions of the method
+ * have not been changed, then it is possible to skip all visit events
+ * and just copy the original code of the method to the writer (the
+ * access, name and descriptor can have been changed, this is not
+ * important since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter) {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this && signature == mw.signature) {
+ boolean sameExceptions = false;
+ if (exceptions == null) {
+ sameExceptions = mw.exceptionCount == 0;
+ } else if (exceptions.length == mw.exceptionCount) {
+ sameExceptions = true;
+ for (int j = exceptions.length - 1; j >= 0; --j) {
+ exception -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(exception)) {
+ sameExceptions = false;
+ break;
}
}
}
-
- if (ANNOTATIONS && dann != 0) {
- AnnotationVisitor dv = mv.visitAnnotationDefault();
- readAnnotationValue(dann, c, null, dv);
- if (dv != null) {
- dv.visitEnd();
- }
- }
- if (ANNOTATIONS) {
- for (j = 1; j >= 0; --j) {
- w = j == 0 ? ianns : anns;
- if (w != 0) {
- k = readUnsignedShort(w);
- w += 2;
- for (; k > 0; --k) {
- w = readAnnotationValues(w + 2,
- c,
- true,
- mv.visitAnnotation(readUTF8(w, c), j != 0));
- }
- }
- }
+ if (sameExceptions) {
+ /*
+ * we do not copy directly the code into MethodWriter to
+ * save a byte array copy operation. The real copy will be
+ * done in ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = firstAttribute;
+ mw.classReaderLength = u - firstAttribute;
+ return u;
}
- if (ANNOTATIONS && mpanns != 0) {
- readParameterAnnotations(mpanns, desc, c, true, mv);
+ }
+ }
+
+ // visit the method parameters
+ if (methodParameters != 0) {
+ for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
+ mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
+ }
+ }
+
+ // visits the method annotations
+ if (ANNOTATIONS && dann != 0) {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null) {
+ dv.visitEnd();
+ }
+ }
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0) {
+ readParameterAnnotations(mv, context, mpanns, true);
+ }
+ if (ANNOTATIONS && impanns != 0) {
+ readParameterAnnotations(mv, context, impanns, false);
+ }
+
+ // visits the method attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ mv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the method code
+ if (code != 0) {
+ mv.visitCode();
+ readCode(mv, context, code);
+ }
+
+ // visits the end of the method
+ mv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads the bytecode of a method and makes the given visitor visit it.
+ *
+ * @param mv
+ * the visitor that must visit the method's code.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the code attribute in the class file.
+ */
+ private void readCode(final MethodVisitor mv, final Context context, int u) {
+ // reads the header
+ byte[] b = this.b;
+ char[] c = context.buffer;
+ int maxStack = readUnsignedShort(u);
+ int maxLocals = readUnsignedShort(u + 2);
+ int codeLength = readInt(u + 4);
+ u += 8;
+
+ // reads the bytecode to find the labels
+ int codeStart = u;
+ int codeEnd = u + codeLength;
+ Label[] labels = context.labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ readLabel(offset + readShort(u + 1), labels);
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ readLabel(offset + readInt(u + 1), labels);
+ u += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
}
- if (ANNOTATIONS && impanns != 0) {
- readParameterAnnotations(impanns, desc, c, false, mv);
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 4;
}
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- mv.visitAttribute(cattrs);
- cattrs = attr;
+ u += 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 4); i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 8;
}
+ u += 8;
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ u += 4;
+ break;
}
+ }
- if (mv != null && v != 0) {
- int maxStack = readUnsignedShort(v);
- int maxLocals = readUnsignedShort(v + 2);
- int codeLength = readInt(v + 4);
- v += 8;
+ // reads the try catch entries to find the labels, and also visits them
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ Label start = readLabel(readUnsignedShort(u + 2), labels);
+ Label end = readLabel(readUnsignedShort(u + 4), labels);
+ Label handler = readLabel(readUnsignedShort(u + 6), labels);
+ String type = readUTF8(items[readUnsignedShort(u + 8)], c);
+ mv.visitTryCatchBlock(start, end, handler, type);
+ u += 8;
+ }
+ u += 2;
- int codeStart = v;
- int codeEnd = v + codeLength;
-
- mv.visitCode();
-
- // 1st phase: finds the labels
- int label;
- Label[] labels = new Label[codeLength + 2];
- readLabel(codeLength + 1, labels);
- while (v < codeEnd) {
- w = v - codeStart;
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- readLabel(w + readShort(v + 1), labels);
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- readLabel(w + readInt(v + 1), labels);
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Opcodes.IINC) {
- v += 6;
- } else {
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 8) - readInt(v + 4) + 1;
- v += 12;
- for (; j > 0; --j) {
- readLabel(w + readInt(v), labels);
- v += 4;
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes*
- v = v + 4 - (w & 3);
- // reads instruction
- readLabel(w + readInt(v), labels);
- j = readInt(v + 4);
- v += 8;
- for (; j > 0; --j) {
- readLabel(w + readInt(v + 4), labels);
- v += 8;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- v += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- case ClassWriter.INDYMETH_INSN:
- v += 5;
- break;
- // case MANA_INSN:
- default:
- v += 4;
- break;
- }
- }
- // parses the try catch entries
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- Label start = readLabel(readUnsignedShort(v), labels);
- Label end = readLabel(readUnsignedShort(v + 2), labels);
- Label handler = readLabel(readUnsignedShort(v + 4), labels);
- int type = readUnsignedShort(v + 6);
- if (type == 0) {
- mv.visitTryCatchBlock(start, end, handler, null);
- } else {
- mv.visitTryCatchBlock(start,
- end,
- handler,
- readUTF8(items[type], c));
- }
- v += 8;
- }
- // parses the local variable, line number tables, and code
- // attributes
- int varTable = 0;
- int varTypeTable = 0;
- int stackMap = 0;
- int stackMapSize = 0;
- int frameCount = 0;
- int frameMode = 0;
- int frameOffset = 0;
- int frameLocalCount = 0;
- int frameLocalDiff = 0;
- int frameStackCount = 0;
- Object[] frameLocal = null;
- Object[] frameStack = null;
- boolean zip = true;
- cattrs = null;
- j = readUnsignedShort(v);
- v += 2;
- for (; j > 0; --j) {
- attrName = readUTF8(v, c);
- if ("LocalVariableTable".equals(attrName)) {
- if (!skipDebug) {
- varTable = v + 6;
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- label += readUnsignedShort(w + 2);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- w += 10;
- }
- }
- } else if ("LocalVariableTypeTable".equals(attrName)) {
- varTypeTable = v + 6;
- } else if ("LineNumberTable".equals(attrName)) {
- if (!skipDebug) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for (; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- readLabel(label, labels).status |= Label.DEBUG;
- }
- labels[label].line = readUnsignedShort(w + 2);
- w += 4;
- }
- }
- } else if (FRAMES && "StackMapTable".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- stackMapSize = readInt(v + 2);
- frameCount = readUnsignedShort(v + 6);
+ // reads the code attributes
+ int[] tanns = null; // start index of each visible type annotation
+ int[] itanns = null; // start index of each invisible type annotation
+ int tann = 0; // current index in tanns array
+ int itann = 0; // current index in itanns array
+ int ntoff = -1; // next visible type annotation code offset
+ int nitoff = -1; // next invisible type annotation code offset
+ int varTable = 0;
+ int varTypeTable = 0;
+ boolean zip = true;
+ boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
+ int stackMap = 0;
+ int stackMapSize = 0;
+ int frameCount = 0;
+ Context frame = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("LocalVariableTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ varTable = u + 8;
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- /*
- * here we do not extract the labels corresponding to
- * the attribute content. This would require a full
- * parsing of the attribute, which would need to be
- * repeated in the second phase (see below). Instead the
- * content of the attribute is read one frame at a time
- * (i.e. after a frame has been visited, the next frame
- * is read), and the labels it contains are also
- * extracted one frame at a time. Thanks to the ordering
- * of frames, having only a "one frame lookahead" is not
- * a problem, i.e. it is not possible to see an offset
- * smaller than the offset of the current insn and for
- * which no Label exist.
- */
- /*
- * This is not true for UNINITIALIZED type offsets. We
- * solve this by parsing the stack map table without a
- * full decoding (see below).
- */
- } else if (FRAMES && "StackMap".equals(attrName)) {
- if ((flags & SKIP_FRAMES) == 0) {
- stackMap = v + 8;
- stackMapSize = readInt(v + 2);
- frameCount = readUnsignedShort(v + 6);
- zip = false;
- }
- /*
- * IMPORTANT! here we assume that the frames are
- * ordered, as in the StackMapTable attribute, although
- * this is not guaranteed by the attribute format.
- */
- } else {
- for (k = 0; k < attrs.length; ++k) {
- if (attrs[k].type.equals(attrName)) {
- attr = attrs[k].read(this,
- v + 6,
- readInt(v + 2),
- c,
- codeStart - 8,
- labels);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
+ label += readUnsignedShort(v + 12);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
+ v += 10;
}
- v += 6 + readInt(v + 2);
}
-
- // 2nd phase: visits each instruction
- if (FRAMES && stackMap != 0) {
- // creates the very first (implicit) frame from the method
- // descriptor
- frameLocal = new Object[maxLocals];
- frameStack = new Object[maxStack];
- if (unzip) {
- int local = 0;
- if ((access & Opcodes.ACC_STATIC) == 0) {
- if ("<init>".equals(name)) {
- frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
- } else {
- frameLocal[local++] = readClass(header + 2, c);
- }
- }
- j = 1;
- loop: while (true) {
- k = j;
- switch (desc.charAt(j++)) {
- case 'Z':
- case 'C':
- case 'B':
- case 'S':
- case 'I':
- frameLocal[local++] = Opcodes.INTEGER;
- break;
- case 'F':
- frameLocal[local++] = Opcodes.FLOAT;
- break;
- case 'J':
- frameLocal[local++] = Opcodes.LONG;
- break;
- case 'D':
- frameLocal[local++] = Opcodes.DOUBLE;
- break;
- case '[':
- while (desc.charAt(j) == '[') {
- ++j;
- }
- if (desc.charAt(j) == 'L') {
- ++j;
- while (desc.charAt(j) != ';') {
- ++j;
- }
- }
- frameLocal[local++] = desc.substring(k, ++j);
- break;
- case 'L':
- while (desc.charAt(j) != ';') {
- ++j;
- }
- frameLocal[local++] = desc.substring(k + 1,
- j++);
- break;
- default:
- break loop;
- }
+ } else if ("LocalVariableTypeTable".equals(attrName)) {
+ varTypeTable = u + 8;
+ } else if ("LineNumberTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
}
- frameLocalCount = local;
+ labels[label].line = readUnsignedShort(v + 12);
+ v += 4;
}
- /*
- * for the first explicit frame the offset is not
- * offset_delta + 1 but only offset_delta; setting the
- * implicit frame offset to -1 allow the use of the
- * "offset_delta + 1" rule in all cases
- */
- frameOffset = -1;
- /*
- * Finds labels for UNINITIALIZED frame types. Instead of
- * decoding each element of the stack map table, we look
- * for 3 consecutive bytes that "look like" an UNINITIALIZED
- * type (tag 8, offset within code bounds, NEW instruction
- * at this offset). We may find false positives (i.e. not
- * real UNINITIALIZED types), but this should be rare, and
- * the only consequence will be the creation of an unneeded
- * label. This is better than creating a label for each NEW
- * instruction, and faster than fully decoding the whole
- * stack map table.
- */
- for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
- if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
- k = readUnsignedShort(j + 1);
- if (k >= 0 && k < codeLength) { // potential offset
- if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
- readLabel(k, labels);
- }
- }
+ }
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = readTypeAnnotations(mv, context, u + 8, true);
+ ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
+ : readUnsignedShort(tanns[0] + 1);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = readTypeAnnotations(mv, context, u + 8, false);
+ nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
+ : readUnsignedShort(itanns[0] + 1);
+ } else if (FRAMES && "StackMapTable".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * here we do not extract the labels corresponding to the
+ * attribute content. This would require a full parsing of the
+ * attribute, which would need to be repeated in the second
+ * phase (see below). Instead the content of the attribute is
+ * read one frame at a time (i.e. after a frame has been
+ * visited, the next frame is read), and the labels it contains
+ * are also extracted one frame at a time. Thanks to the
+ * ordering of frames, having only a "one frame lookahead" is
+ * not a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for which no
+ * Label exist.
+ */
+ /*
+ * This is not true for UNINITIALIZED type offsets. We solve
+ * this by parsing the stack map table without a full decoding
+ * (see below).
+ */
+ } else if (FRAMES && "StackMap".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ zip = false;
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are ordered, as in
+ * the StackMapTable attribute, although this is not guaranteed
+ * by the attribute format.
+ */
+ } else {
+ for (int j = 0; j < context.attrs.length; ++j) {
+ if (context.attrs[j].type.equals(attrName)) {
+ Attribute attr = context.attrs[j].read(this, u + 8,
+ readInt(u + 4), c, codeStart - 8, labels);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
}
}
}
- v = codeStart;
- Label l;
- while (v < codeEnd) {
- w = v - codeStart;
-
- l = labels[w];
- if (l != null) {
- mv.visitLabel(l);
- if (!skipDebug && l.line > 0) {
- mv.visitLineNumber(l.line, l);
+ }
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // generates the first (implicit) stack map frame
+ if (FRAMES && stackMap != 0) {
+ /*
+ * for the first explicit frame the offset is not offset_delta + 1
+ * but only offset_delta; setting the implicit frame offset to -1
+ * allow the use of the "offset_delta + 1" rule in all cases
+ */
+ frame = context;
+ frame.offset = -1;
+ frame.mode = 0;
+ frame.localCount = 0;
+ frame.localDiff = 0;
+ frame.stackCount = 0;
+ frame.local = new Object[maxLocals];
+ frame.stack = new Object[maxStack];
+ if (unzip) {
+ getImplicitFrame(context);
+ }
+ /*
+ * Finds labels for UNINITIALIZED frame types. Instead of decoding
+ * each element of the stack map table, we look for 3 consecutive
+ * bytes that "look like" an UNINITIALIZED type (tag 8, offset
+ * within code bounds, NEW instruction at this offset). We may find
+ * false positives (i.e. not real UNINITIALIZED types), but this
+ * should be rare, and the only consequence will be the creation of
+ * an unneeded label. This is better than creating a label for each
+ * NEW instruction, and faster than fully decoding the whole stack
+ * map table.
+ */
+ for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
+ if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
+ int v = readUnsignedShort(i + 1);
+ if (v >= 0 && v < codeLength) {
+ if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
+ readLabel(v, labels);
}
}
+ }
+ }
+ }
- while (FRAMES && frameLocal != null
- && (frameOffset == w || frameOffset == -1))
- {
- // if there is a frame for this offset,
- // makes the visitor visit it,
- // and reads the next frame if there is one.
- if (!zip || unzip) {
- mv.visitFrame(Opcodes.F_NEW,
- frameLocalCount,
- frameLocal,
- frameStackCount,
- frameStack);
- } else if (frameOffset != -1) {
- mv.visitFrame(frameMode,
- frameLocalDiff,
- frameLocal,
- frameStackCount,
- frameStack);
- }
+ // visits the instructions
+ u = codeStart;
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+
+ // visits the label and line number for this offset, if any
+ Label l = labels[offset];
+ if (l != null) {
+ mv.visitLabel(l);
+ if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
+ mv.visitLineNumber(l.line, l);
+ }
+ }
- if (frameCount > 0) {
- int tag, delta, n;
- if (zip) {
- tag = b[stackMap++] & 0xFF;
- } else {
- tag = MethodWriter.FULL_FRAME;
- frameOffset = -1;
- }
- frameLocalDiff = 0;
- if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
- {
- delta = tag;
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.RESERVED) {
- delta = tag
- - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else {
- delta = readUnsignedShort(stackMap);
- stackMap += 2;
- if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
- {
- stackMap = readFrameType(frameStack,
- 0,
- stackMap,
- c,
- labels);
- frameMode = Opcodes.F_SAME1;
- frameStackCount = 1;
- } else if (tag >= MethodWriter.CHOP_FRAME
- && tag < MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_CHOP;
- frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
- - tag;
- frameLocalCount -= frameLocalDiff;
- frameStackCount = 0;
- } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
- {
- frameMode = Opcodes.F_SAME;
- frameStackCount = 0;
- } else if (tag < MethodWriter.FULL_FRAME) {
- j = unzip ?
<TRUNCATED>
[23/23] git commit: 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?"
Posted by ka...@apache.org.
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?"
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/a0ac605d
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/a0ac605d
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/a0ac605d
Branch: refs/heads/5.3
Commit: a0ac605dbd89f543b0396d747f5909e1ba38205b
Parents: 1a03c56
Author: kaosko <ka...@apache.org>
Authored: Tue Mar 25 11:29:43 2014 -0700
Committer: kaosko <ka...@apache.org>
Committed: Tue Mar 25 11:29:43 2014 -0700
----------------------------------------------------------------------
plastic/LICENSE-ASM-3_3_1.txt | 29 -
plastic/LICENSE-ASM-5_0.txt | 29 +
plastic/NOTICE.txt | 4 +-
.../internal/plastic/asm/AnnotationVisitor.java | 82 +-
.../internal/plastic/asm/AnnotationWriter.java | 123 +-
.../internal/plastic/asm/Attribute.java | 213 +-
.../internal/plastic/asm/ByteVector.java | 168 +-
.../internal/plastic/asm/ClassReader.java | 3350 ++++++++++--------
.../internal/plastic/asm/ClassVisitor.java | 291 +-
.../internal/plastic/asm/ClassWriter.java | 694 ++--
.../tapestry5/internal/plastic/asm/Context.java | 145 +
.../tapestry5/internal/plastic/asm/Edge.java | 2 +-
.../internal/plastic/asm/FieldVisitor.java | 75 +-
.../internal/plastic/asm/FieldWriter.java | 138 +-
.../tapestry5/internal/plastic/asm/Frame.java | 1087 +++---
.../tapestry5/internal/plastic/asm/Handle.java | 65 +-
.../tapestry5/internal/plastic/asm/Handler.java | 13 +-
.../tapestry5/internal/plastic/asm/Item.java | 188 +-
.../tapestry5/internal/plastic/asm/Label.java | 169 +-
.../internal/plastic/asm/MethodVisitor.java | 808 +++--
.../internal/plastic/asm/MethodWriter.java | 1535 ++++----
.../tapestry5/internal/plastic/asm/Opcodes.java | 9 +-
.../tapestry5/internal/plastic/asm/Type.java | 333 +-
.../internal/plastic/asm/TypePath.java | 193 +
.../internal/plastic/asm/TypeReference.java | 452 +++
.../plastic/asm/commons/AdviceAdapter.java | 646 ++++
.../plastic/asm/commons/AnalyzerAdapter.java | 947 +++++
.../plastic/asm/commons/CodeSizeEvaluator.java | 238 ++
.../plastic/asm/commons/GeneratorAdapter.java | 1628 +++++++++
.../plastic/asm/commons/InstructionAdapter.java | 1170 ++++++
.../plastic/asm/commons/JSRInlinerAdapter.java | 333 +-
.../asm/commons/LocalVariablesSorter.java | 381 ++
.../internal/plastic/asm/commons/Method.java | 282 ++
.../internal/plastic/asm/commons/Remapper.java | 223 ++
.../asm/commons/RemappingAnnotationAdapter.java | 79 +
.../asm/commons/RemappingClassAdapter.java | 135 +
.../asm/commons/RemappingFieldAdapter.java | 71 +
.../asm/commons/RemappingMethodAdapter.java | 224 ++
.../asm/commons/RemappingSignatureAdapter.java | 155 +
.../asm/commons/SerialVersionUIDAdder.java | 540 +++
.../plastic/asm/commons/SimpleRemapper.java | 69 +
.../plastic/asm/commons/StaticInitMerger.java | 97 +
.../asm/commons/TableSwitchGenerator.java | 57 +
.../asm/commons/TryCatchBlockSorter.java | 96 +
.../internal/plastic/asm/commons/package.html | 48 +
.../optimizer/AnnotationConstantsCollector.java | 147 +
.../asm/optimizer/ClassConstantsCollector.java | 198 ++
.../plastic/asm/optimizer/ClassOptimizer.java | 260 ++
.../plastic/asm/optimizer/Constant.java | 323 ++
.../plastic/asm/optimizer/ConstantPool.java | 249 ++
.../asm/optimizer/FieldConstantsCollector.java | 89 +
.../plastic/asm/optimizer/JarOptimizer.java | 235 ++
.../asm/optimizer/MethodConstantsCollector.java | 224 ++
.../plastic/asm/optimizer/MethodOptimizer.java | 136 +
.../plastic/asm/optimizer/NameMapping.java | 114 +
.../plastic/asm/optimizer/Shrinker.java | 283 ++
.../plastic/asm/optimizer/jdk1.2.2_017.txt.gz | Bin 0 -> 113814 bytes
.../plastic/asm/optimizer/jdk1.3.1_19.txt.gz | Bin 0 -> 128067 bytes
.../asm/optimizer/shrink-annotations.properties | 53 +
.../asm/optimizer/shrink-frames.properties | 62 +
.../asm/optimizer/shrink-resize.properties | 37 +
.../asm/optimizer/shrink-signatures.properties | 43 +
.../asm/optimizer/shrink-writer.properties | 66 +
.../plastic/asm/optimizer/shrink.properties | 380 ++
.../plastic/asm/signature/SignatureReader.java | 191 +-
.../plastic/asm/signature/SignatureVisitor.java | 88 +-
.../plastic/asm/signature/SignatureWriter.java | 6 +-
.../plastic/asm/tree/AbstractInsnNode.java | 132 +-
.../plastic/asm/tree/AnnotationNode.java | 72 +-
.../internal/plastic/asm/tree/ClassNode.java | 199 +-
.../plastic/asm/tree/FieldInsnNode.java | 48 +-
.../internal/plastic/asm/tree/FieldNode.java | 198 +-
.../internal/plastic/asm/tree/FrameNode.java | 141 +-
.../internal/plastic/asm/tree/IincInsnNode.java | 17 +-
.../plastic/asm/tree/InnerClassNode.java | 46 +-
.../internal/plastic/asm/tree/InsnList.java | 184 +-
.../internal/plastic/asm/tree/InsnNode.java | 46 +-
.../internal/plastic/asm/tree/IntInsnNode.java | 26 +-
.../plastic/asm/tree/InvokeDynamicInsnNode.java | 32 +-
.../internal/plastic/asm/tree/JumpInsnNode.java | 39 +-
.../internal/plastic/asm/tree/LabelNode.java | 4 +-
.../internal/plastic/asm/tree/LdcInsnNode.java | 18 +-
.../plastic/asm/tree/LineNumberNode.java | 16 +-
.../asm/tree/LocalVariableAnnotationNode.java | 157 +
.../plastic/asm/tree/LocalVariableNode.java | 51 +-
.../plastic/asm/tree/LookupSwitchInsnNode.java | 36 +-
.../plastic/asm/tree/MethodInsnNode.java | 77 +-
.../internal/plastic/asm/tree/MethodNode.java | 542 ++-
.../asm/tree/MultiANewArrayInsnNode.java | 17 +-
.../plastic/asm/tree/ParameterNode.java | 76 +
.../plastic/asm/tree/TableSwitchInsnNode.java | 41 +-
.../plastic/asm/tree/TryCatchBlockNode.java | 97 +-
.../plastic/asm/tree/TypeAnnotationNode.java | 100 +
.../internal/plastic/asm/tree/TypeInsnNode.java | 28 +-
.../internal/plastic/asm/tree/VarInsnNode.java | 34 +-
.../plastic/asm/tree/analysis/Analyzer.java | 549 +++
.../asm/tree/analysis/AnalyzerException.java | 61 +
.../asm/tree/analysis/BasicInterpreter.java | 358 ++
.../plastic/asm/tree/analysis/BasicValue.java | 111 +
.../asm/tree/analysis/BasicVerifier.java | 433 +++
.../plastic/asm/tree/analysis/Frame.java | 738 ++++
.../plastic/asm/tree/analysis/Interpreter.java | 226 ++
.../asm/tree/analysis/SimpleVerifier.java | 320 ++
.../plastic/asm/tree/analysis/SmallSet.java | 134 +
.../asm/tree/analysis/SourceInterpreter.java | 198 ++
.../plastic/asm/tree/analysis/SourceValue.java | 97 +
.../plastic/asm/tree/analysis/Subroutine.java | 90 +
.../plastic/asm/tree/analysis/Value.java | 45 +
.../plastic/asm/tree/analysis/package.html | 67 +
.../internal/plastic/asm/util/ASMifiable.java | 19 +-
.../internal/plastic/asm/util/ASMifier.java | 1285 +++++++
.../asm/util/CheckAnnotationAdapter.java | 136 +
.../plastic/asm/util/CheckClassAdapter.java | 1009 ++++++
.../plastic/asm/util/CheckFieldAdapter.java | 122 +
.../plastic/asm/util/CheckMethodAdapter.java | 1542 ++++++++
.../plastic/asm/util/CheckSignatureAdapter.java | 330 ++
.../internal/plastic/asm/util/Printer.java | 421 ++-
.../internal/plastic/asm/util/Textifiable.java | 16 +-
.../internal/plastic/asm/util/Textifier.java | 732 ++--
.../asm/util/TraceAnnotationVisitor.java | 32 +-
.../plastic/asm/util/TraceClassVisitor.java | 158 +-
.../plastic/asm/util/TraceFieldVisitor.java | 27 +-
.../plastic/asm/util/TraceMethodVisitor.java | 172 +-
.../plastic/asm/util/TraceSignatureVisitor.java | 70 +-
.../plastic/asm/xml/ASMContentHandler.java | 1453 ++++++++
.../internal/plastic/asm/xml/Processor.java | 1044 ++++++
.../internal/plastic/asm/xml/SAXAdapter.java | 89 +
.../plastic/asm/xml/SAXAnnotationAdapter.java | 242 ++
.../plastic/asm/xml/SAXClassAdapter.java | 335 ++
.../plastic/asm/xml/SAXCodeAdapter.java | 415 +++
.../plastic/asm/xml/SAXFieldAdapter.java | 71 +
.../internal/plastic/asm/xml/asm-xml.dtd | 349 ++
.../internal/plastic/asm/xml/package.html | 96 +
133 files changed, 31009 insertions(+), 5855 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-3_3_1.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-3_3_1.txt b/plastic/LICENSE-ASM-3_3_1.txt
deleted file mode 100644
index c5aba7b..0000000
--- a/plastic/LICENSE-ASM-3_3_1.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-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.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/LICENSE-ASM-5_0.txt
----------------------------------------------------------------------
diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt
new file mode 100644
index 0000000..c5aba7b
--- /dev/null
+++ b/plastic/LICENSE-ASM-5_0.txt
@@ -0,0 +1,29 @@
+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.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/NOTICE.txt
----------------------------------------------------------------------
diff --git a/plastic/NOTICE.txt b/plastic/NOTICE.txt
index 96158f5..beec8e0 100644
--- a/plastic/NOTICE.txt
+++ b/plastic/NOTICE.txt
@@ -1,6 +1,6 @@
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).
-This product imports and repackages ASM 3.3.1 code which is
-released under the BSD License
+This product imports and repackages ASM 5.0.1 code which is
+released under a BSD style License
http://asm.ow2.org/license.html
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
index 693b355..1102d54 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationVisitor.java
@@ -33,7 +33,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* A visitor to visit a Java annotation. The methods of this class must be
* called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
* <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -41,7 +41,7 @@ public abstract class AnnotationVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -53,9 +53,10 @@ public abstract class AnnotationVisitor {
/**
* Constructs a new {@link AnnotationVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public AnnotationVisitor(final int api) {
this(api, null);
@@ -63,31 +64,36 @@ public abstract class AnnotationVisitor {
/**
* Constructs a new {@link AnnotationVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param av the annotation visitor to which this visitor must delegate
- * method calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param av
+ * the annotation visitor to which this visitor must delegate
+ * method calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.av = av;
}
/**
* Visits a primitive value of the annotation.
- *
- * @param name the value name.
- * @param value the actual value, whose type must be {@link Byte},
- * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
- * , {@link Long}, {@link Float}, {@link Double}, {@link String} or
- * {@link Type} or OBJECT or ARRAY sort. This value can also be an
- * array of byte, boolean, short, char, int, long, float or double
- * values (this is equivalent to using {@link #visitArray visitArray}
- * and visiting each array element in turn, but is more convenient).
+ *
+ * @param name
+ * the value name.
+ * @param value
+ * the actual value, whose type must be {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+ * value can also be an array of byte, boolean, short, char, int,
+ * long, float or double values (this is equivalent to using
+ * {@link #visitArray visitArray} and visiting each array element
+ * in turn, but is more convenient).
*/
public void visit(String name, Object value) {
if (av != null) {
@@ -97,10 +103,13 @@ public abstract class AnnotationVisitor {
/**
* Visits an enumeration value of the annotation.
- *
- * @param name the value name.
- * @param desc the class descriptor of the enumeration class.
- * @param value the actual enumeration value.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the enumeration class.
+ * @param value
+ * the actual enumeration value.
*/
public void visitEnum(String name, String desc, String value) {
if (av != null) {
@@ -110,13 +119,15 @@ public abstract class AnnotationVisitor {
/**
* Visits a nested annotation value of the annotation.
- *
- * @param name the value name.
- * @param desc the class descriptor of the nested annotation class.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the nested annotation class.
* @return a visitor to visit the actual nested annotation value, or
- * <tt>null</tt> if this visitor is not interested in visiting
- * this nested annotation. <i>The nested annotation value must be
- * fully visited before calling other methods on this annotation
+ * <tt>null</tt> if this visitor is not interested in visiting this
+ * nested annotation. <i>The nested annotation value must be fully
+ * visited before calling other methods on this annotation
* visitor</i>.
*/
public AnnotationVisitor visitAnnotation(String name, String desc) {
@@ -131,11 +142,12 @@ public abstract class AnnotationVisitor {
* types (such as byte, boolean, short, char, int, long, float or double)
* can be passed as value to {@link #visit visit}. This is what
* {@link ClassReader} does.
- *
- * @param name the value name.
+ *
+ * @param name
+ * the value name.
* @return a visitor to visit the actual array value elements, or
- * <tt>null</tt> if this visitor is not interested in visiting
- * these values. The 'name' parameters passed to the methods of this
+ * <tt>null</tt> if this visitor is not interested in visiting these
+ * values. The 'name' parameters passed to the methods of this
* visitor are ignored. <i>All the array values must be visited
* before calling other methods on this annotation visitor</i>.
*/
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
index a26f5ca..679aa66 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/AnnotationWriter.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* An {@link AnnotationVisitor} that generates annotations in bytecode form.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -89,22 +89,22 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Constructs a new {@link AnnotationWriter}.
- *
- * @param cw the class writer to which this annotation must be added.
- * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
- * @param bv where the annotation values must be stored.
- * @param parent where the number of annotation values must be stored.
- * @param offset where in <tt>parent</tt> the number of annotation values must
- * be stored.
+ *
+ * @param cw
+ * the class writer to which this annotation must be added.
+ * @param named
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+ * @param bv
+ * where the annotation values must be stored.
+ * @param parent
+ * where the number of annotation values must be stored.
+ * @param offset
+ * where in <tt>parent</tt> the number of annotation values must
+ * be stored.
*/
- AnnotationWriter(
- final ClassWriter cw,
- final boolean named,
- final ByteVector bv,
- final ByteVector parent,
- final int offset)
- {
- super(Opcodes.ASM4);
+ AnnotationWriter(final ClassWriter cw, final boolean named,
+ final ByteVector bv, final ByteVector parent, final int offset) {
+ super(Opcodes.ASM5);
this.cw = cw;
this.named = named;
this.bv = bv;
@@ -190,11 +190,8 @@ final class AnnotationWriter extends AnnotationVisitor {
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
@@ -203,10 +200,8 @@ final class AnnotationWriter extends AnnotationVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
++size;
if (named) {
bv.putShort(cw.newUTF8(name));
@@ -242,7 +237,7 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Returns the size of this annotation writer list.
- *
+ *
* @return the size of this annotation writer list.
*/
int getSize() {
@@ -258,8 +253,9 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Puts the annotations of this annotation writer list into the given byte
* vector.
- *
- * @param out where the annotations must be put.
+ *
+ * @param out
+ * where the annotations must be put.
*/
void put(final ByteVector out) {
int n = 0;
@@ -285,16 +281,16 @@ final class AnnotationWriter extends AnnotationVisitor {
/**
* Puts the given annotation lists into the given byte vector.
- *
- * @param panns an array of annotation writer lists.
- * @param off index of the first annotation to be written.
- * @param out where the annotations must be put.
+ *
+ * @param panns
+ * an array of annotation writer lists.
+ * @param off
+ * index of the first annotation to be written.
+ * @param out
+ * where the annotations must be put.
*/
- static void put(
- final AnnotationWriter[] panns,
- final int off,
- final ByteVector out)
- {
+ static void put(final AnnotationWriter[] panns, final int off,
+ final ByteVector out) {
int size = 1 + 2 * (panns.length - off);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
@@ -319,4 +315,57 @@ final class AnnotationWriter extends AnnotationVisitor {
}
}
}
+
+ /**
+ * Puts the given type reference and type path into the given bytevector.
+ * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param out
+ * where the type reference and type path must be put.
+ */
+ static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
+ switch (typeRef >>> 24) {
+ case 0x00: // CLASS_TYPE_PARAMETER
+ case 0x01: // METHOD_TYPE_PARAMETER
+ case 0x16: // METHOD_FORMAL_PARAMETER
+ out.putShort(typeRef >>> 16);
+ break;
+ case 0x13: // FIELD
+ case 0x14: // METHOD_RETURN
+ case 0x15: // METHOD_RECEIVER
+ out.putByte(typeRef >>> 24);
+ break;
+ case 0x47: // CAST
+ case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+ case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+ out.putInt(typeRef);
+ break;
+ // case 0x10: // CLASS_EXTENDS
+ // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+ // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+ // case 0x17: // THROWS
+ // case 0x42: // EXCEPTION_PARAMETER
+ // case 0x43: // INSTANCEOF
+ // case 0x44: // NEW
+ // case 0x45: // CONSTRUCTOR_REFERENCE
+ // case 0x46: // METHOD_REFERENCE
+ default:
+ out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
+ break;
+ }
+ if (typePath == null) {
+ out.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ out.putByteArray(typePath.b, typePath.offset, length);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
index 8f29872..fae580f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Attribute.java
@@ -31,7 +31,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A non standard class, field, method or code attribute.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -54,8 +54,9 @@ public class Attribute {
/**
* Constructs a new empty attribute.
- *
- * @param type the type of the attribute.
+ *
+ * @param type
+ * the type of the attribute.
*/
protected Attribute(final String type) {
this.type = type;
@@ -64,7 +65,7 @@ public class Attribute {
/**
* Returns <tt>true</tt> if this type of attribute is unknown. The default
* implementation of this method always returns <tt>true</tt>.
- *
+ *
* @return <tt>true</tt> if this type of attribute is unknown.
*/
public boolean isUnknown() {
@@ -73,7 +74,7 @@ public class Attribute {
/**
* Returns <tt>true</tt> if this type of attribute is a code attribute.
- *
+ *
* @return <tt>true</tt> if this type of attribute is a code attribute.
*/
public boolean isCodeAttribute() {
@@ -82,7 +83,7 @@ public class Attribute {
/**
* Returns the labels corresponding to this attribute.
- *
+ *
* @return the labels corresponding to this attribute, or <tt>null</tt> if
* this attribute is not a code attribute that contains labels.
*/
@@ -91,39 +92,39 @@ public class Attribute {
}
/**
- * Reads a {@link #type type} attribute. This method must return a <i>new</i>
- * {@link Attribute} object, of type {@link #type type}, corresponding to
- * the <tt>len</tt> bytes starting at the given offset, in the given class
- * reader.
- *
- * @param cr the class that contains the attribute to be read.
- * @param off index of the first byte of the attribute's content in {@link
- * ClassReader#b cr.b}. The 6 attribute header bytes, containing the
- * type and the length of the attribute, are not taken into account
- * here.
- * @param len the length of the attribute's content.
- * @param buf buffer to be used to call
- * {@link ClassReader#readUTF8 readUTF8},
- * {@link ClassReader#readClass(int,char[]) readClass} or
- * {@link ClassReader#readConst readConst}.
- * @param codeOff index of the first byte of code's attribute content in
- * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
- * not a code attribute. The 6 attribute header bytes, containing the
- * type and the length of the attribute, are not taken into account
- * here.
- * @param labels the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
+ * Reads a {@link #type type} attribute. This method must return a
+ * <i>new</i> {@link Attribute} object, of type {@link #type type},
+ * corresponding to the <tt>len</tt> bytes starting at the given offset, in
+ * the given class reader.
+ *
+ * @param cr
+ * the class that contains the attribute to be read.
+ * @param off
+ * index of the first byte of the attribute's content in
+ * {@link ClassReader#b cr.b}. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param len
+ * the length of the attribute's content.
+ * @param buf
+ * buffer to be used to call {@link ClassReader#readUTF8
+ * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
+ * or {@link ClassReader#readConst readConst}.
+ * @param codeOff
+ * index of the first byte of code's attribute content in
+ * {@link ClassReader#b cr.b}, or -1 if the attribute to be read
+ * is not a code attribute. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param labels
+ * the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
- protected Attribute read(
- final ClassReader cr,
- final int off,
- final int len,
- final char[] buf,
- final int codeOff,
- final Label[] labels)
- {
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
Attribute attr = new Attribute(type);
attr.value = new byte[len];
System.arraycopy(cr.b, off, attr.value, 0, len);
@@ -132,31 +133,31 @@ public class Attribute {
/**
* Returns the byte array form of this attribute.
- *
- * @param cw the class to which this attribute must be added. This parameter
- * can be used to add to the constant pool of this class the items
- * that corresponds to this attribute.
- * @param code the bytecode of the method corresponding to this code
- * attribute, or <tt>null</tt> if this attribute is not a code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to this
- * code attribute, or <tt>null</tt> if this attribute is not a code
- * attribute.
- * @param maxStack the maximum stack size of the method corresponding to
- * this code attribute, or -1 if this attribute is not a code
- * attribute.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to this code attribute, or -1 if this attribute is
- * not a code attribute.
+ *
+ * @param cw
+ * the class to which this attribute must be added. This
+ * parameter can be used to add to the constant pool of this
+ * class the items that corresponds to this attribute.
+ * @param code
+ * the bytecode of the method corresponding to this code
+ * attribute, or <tt>null</tt> if this attribute is not a code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to this
+ * code attribute, or <tt>null</tt> if this attribute is not a
+ * code attribute.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to this
+ * code attribute, or -1 if this attribute is not a code
+ * attribute.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to this code attribute, or -1 if this attribute
+ * is not a code attribute.
* @return the byte array form of this attribute.
*/
- protected ByteVector write(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals)
- {
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
ByteVector v = new ByteVector();
v.data = value;
v.length = value.length;
@@ -165,7 +166,7 @@ public class Attribute {
/**
* Returns the length of the attribute list that begins with this attribute.
- *
+ *
* @return the length of the attribute list that begins with this attribute.
*/
final int getCount() {
@@ -180,31 +181,31 @@ public class Attribute {
/**
* Returns the size of all the attributes in this attribute list.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes are
- * not code attributes.
- * @param maxStack the maximum stack size of the method corresponding to
- * these code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes
- * are not code attributes.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
* @return the size of all the attributes in this attribute list. This size
* includes the size of the attribute headers.
*/
- final int getSize(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals)
- {
+ final int getSize(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals) {
Attribute attr = this;
int size = 0;
while (attr != null) {
@@ -218,31 +219,31 @@ public class Attribute {
/**
* Writes all the attributes of this attribute list in the given byte
* vector.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to
- * these code attributes, or <tt>null</tt> if these attributes are
- * not code attributes.
- * @param maxStack the maximum stack size of the method corresponding to
- * these code attributes, or -1 if these attributes are not code
- * attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes
- * are not code attributes.
- * @param out where the attributes must be written.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
+ * @param out
+ * where the attributes must be written.
*/
- final void put(
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals,
- final ByteVector out)
- {
+ final void put(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals, final ByteVector out) {
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
index e689d87..24506f9 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/ByteVector.java
@@ -32,7 +32,7 @@ package org.apache.tapestry5.internal.plastic.asm;
/**
* A dynamically extensible vector of bytes. This class is roughly equivalent to
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- *
+ *
* @author Eric Bruneton
*/
public class ByteVector {
@@ -58,8 +58,9 @@ public class ByteVector {
/**
* Constructs a new {@link ByteVector ByteVector} with the given initial
* size.
- *
- * @param initialSize the initial size of the byte vector to be constructed.
+ *
+ * @param initialSize
+ * the initial size of the byte vector to be constructed.
*/
public ByteVector(final int initialSize) {
data = new byte[initialSize];
@@ -68,8 +69,9 @@ public class ByteVector {
/**
* Puts a byte into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param b a byte.
+ *
+ * @param b
+ * a byte.
* @return this byte vector.
*/
public ByteVector putByte(final int b) {
@@ -85,9 +87,11 @@ public class ByteVector {
/**
* Puts two bytes into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param b1 a byte.
- * @param b2 another byte.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
* @return this byte vector.
*/
ByteVector put11(final int b1, final int b2) {
@@ -105,8 +109,9 @@ public class ByteVector {
/**
* Puts a short into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param s a short.
+ *
+ * @param s
+ * a short.
* @return this byte vector.
*/
public ByteVector putShort(final int s) {
@@ -124,9 +129,11 @@ public class ByteVector {
/**
* Puts a byte and a short into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param b a byte.
- * @param s a short.
+ *
+ * @param b
+ * a byte.
+ * @param s
+ * a short.
* @return this byte vector.
*/
ByteVector put12(final int b, final int s) {
@@ -145,8 +152,9 @@ public class ByteVector {
/**
* Puts an int into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param i an int.
+ *
+ * @param i
+ * an int.
* @return this byte vector.
*/
public ByteVector putInt(final int i) {
@@ -166,8 +174,9 @@ public class ByteVector {
/**
* Puts a long into this byte vector. The byte vector is automatically
* enlarged if necessary.
- *
- * @param l a long.
+ *
+ * @param l
+ * a long.
* @return this byte vector.
*/
public ByteVector putLong(final long l) {
@@ -193,12 +202,16 @@ public class ByteVector {
/**
* Puts an UTF8 string into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param s a String.
+ *
+ * @param s
+ * a String whose UTF8 encoded length must be less than 65536.
* @return this byte vector.
*/
public ByteVector putUTF8(final String s) {
int charLength = s.length();
+ if (charLength > 65535) {
+ throw new IllegalArgumentException();
+ }
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
@@ -217,38 +230,68 @@ public class ByteVector {
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
- int byteLength = i;
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- data[length] = (byte) (byteLength >>> 8);
- data[length + 1] = (byte) byteLength;
- if (length + 2 + byteLength > data.length) {
- length = len;
- enlarge(2 + byteLength);
- data = this.data;
- }
- for (int j = i; j < charLength; ++j) {
- c = s.charAt(j);
- if (c >= '\001' && c <= '\177') {
- data[len++] = (byte) c;
- } else if (c > '\u07FF') {
- data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
- data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- } else {
- data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
- data[len++] = (byte) (0x80 | c & 0x3F);
- }
- }
- break;
+ length = len;
+ return encodeUTF8(s, i, 65535);
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary. The string length is encoded in two
+ * bytes before the encoded characters, if there is space for that (i.e. if
+ * this.length - i - 2 >= 0).
+ *
+ * @param s
+ * the String to encode.
+ * @param i
+ * the index of the first character to encode. The previous
+ * characters are supposed to have already been encoded, using
+ * only one byte per character.
+ * @param maxByteLength
+ * the maximum byte length of the encoded string, including the
+ * already encoded characters.
+ * @return this byte vector.
+ */
+ ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+ int charLength = s.length();
+ int byteLength = i;
+ char c;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ if (byteLength > maxByteLength) {
+ throw new IllegalArgumentException();
+ }
+ int start = length - i - 2;
+ if (start >= 0) {
+ data[start] = (byte) (byteLength >>> 8);
+ data[start + 1] = (byte) byteLength;
+ }
+ if (length + byteLength - i > data.length) {
+ enlarge(byteLength - i);
+ }
+ int len = length;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
@@ -258,15 +301,17 @@ public class ByteVector {
/**
* Puts an array of bytes into this byte vector. The byte vector is
* automatically enlarged if necessary.
- *
- * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
- * null bytes into this byte vector.
- * @param off index of the fist byte of b that must be copied.
- * @param len number of bytes of b that must be copied.
+ *
+ * @param b
+ * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+ * null bytes into this byte vector.
+ * @param off
+ * index of the fist byte of b that must be copied.
+ * @param len
+ * number of bytes of b that must be copied.
* @return this byte vector.
*/
- public ByteVector putByteArray(final byte[] b, final int off, final int len)
- {
+ public ByteVector putByteArray(final byte[] b, final int off, final int len) {
if (length + len > data.length) {
enlarge(len);
}
@@ -279,9 +324,10 @@ public class ByteVector {
/**
* Enlarge this byte vector so that it can receive n more bytes.
- *
- * @param size number of additional bytes that this byte vector should be
- * able to receive.
+ *
+ * @param size
+ * number of additional bytes that this byte vector should be
+ * able to receive.
*/
private void enlarge(final int size) {
int length1 = 2 * data.length;
[04/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
index c74a17f..a849298 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Printer.java
@@ -29,18 +29,19 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.Attribute;
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 java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* An abstract converter from visit events to text.
- *
+ *
* @author Eric Bruneton
*/
public abstract class Printer {
@@ -103,8 +104,8 @@ public abstract class Printer {
}
s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
- + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
- + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+ + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+ + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
HANDLE_TAG = new String[10];
j = 0;
i = 1;
@@ -116,7 +117,7 @@ public abstract class Printer {
/**
* The ASM API version implemented by this class. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -149,81 +150,67 @@ public abstract class Printer {
}
/**
- * Class header.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
+ * Class header. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visit}.
*/
- public abstract void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces);
+ public abstract void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces);
/**
- * Class source.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
+ * Class source. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitSource}.
*/
public abstract void visitSource(final String file, final String debug);
/**
- * Class outer class.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
+ * Class outer class. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitOuterClass}.
*/
- public abstract void visitOuterClass(
- final String owner,
- final String name,
- final String desc);
+ public abstract void visitOuterClass(final String owner, final String name,
+ final String desc);
/**
- * Class annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
+ * Class annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAnnotation}.
*/
- public abstract Printer visitClassAnnotation(
- final String desc,
- final boolean visible);
+ public abstract Printer visitClassAnnotation(final String desc,
+ final boolean visible);
/**
- * Class attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
+ * Class type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitTypeAnnotation}.
+ */
+ public Printer visitClassTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Class attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitAttribute}.
*/
public abstract void visitClassAttribute(final Attribute attr);
/**
- * Class inner name.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
+ * Class inner name. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitInnerClass}.
*/
- public abstract void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access);
+ public abstract void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access);
/**
- * Class field.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
+ * Class field. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitField}.
*/
- public abstract Printer visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value);
+ public abstract Printer visitField(final int access, final String name,
+ final String desc, final String signature, final Object value);
/**
- * Class method.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
+ * Class method. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitMethod}.
*/
- public abstract Printer visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions);
+ public abstract Printer visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions);
/**
- * Class end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
+ * Class end. See {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitEnd}.
*/
public abstract void visitClassEnd();
@@ -232,37 +219,31 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Annotation value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
+ * Annotation value. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visit}.
*/
public abstract void visit(final String name, final Object value);
/**
- * Annotation enum value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
+ * Annotation enum value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnum}.
*/
- public abstract void visitEnum(
- final String name,
- final String desc,
- final String value);
+ public abstract void visitEnum(final String name, final String desc,
+ final String value);
/**
- * Nested annotation value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
+ * Nested annotation value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitAnnotation}.
*/
- public abstract Printer visitAnnotation(
- final String name,
- final String desc);
+ public abstract Printer visitAnnotation(final String name, final String desc);
/**
- * Annotation array value.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
+ * Annotation array value. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitArray}.
*/
public abstract Printer visitArray(final String name);
/**
- * Annotation end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
+ * Annotation end. See {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor#visitEnd}.
*/
public abstract void visitAnnotationEnd();
@@ -271,22 +252,29 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Field annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+ * Field annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitFieldAnnotation(final String desc,
+ final boolean visible);
+
+ /**
+ * Field type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitTypeAnnotation}.
*/
- public abstract Printer visitFieldAnnotation(
- final String desc,
- final boolean visible);
+ public Printer visitFieldTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Field attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
+ * Field attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitAttribute}.
*/
public abstract void visitFieldAttribute(final Attribute attr);
/**
- * Field end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
+ * Field end. See {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor#visitEnd}.
*/
public abstract void visitFieldEnd();
@@ -295,199 +283,237 @@ public abstract class Printer {
// ------------------------------------------------------------------------
/**
- * Method default annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
+ * Method parameter. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameter(String, int)}.
+ */
+ public void visitParameter(String name, int access) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Method default annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotationDefault}.
*/
public abstract Printer visitAnnotationDefault();
/**
- * Method annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
+ * Method annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAnnotation}.
*/
- public abstract Printer visitMethodAnnotation(
- final String desc,
- final boolean visible);
+ public abstract Printer visitMethodAnnotation(final String desc,
+ final boolean visible);
/**
- * Method parameter annotation.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+ * Method type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeAnnotation}.
*/
- public abstract Printer visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible);
+ public Printer visitMethodTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method attribute.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
+ * Method parameter annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitParameterAnnotation}.
+ */
+ public abstract Printer visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible);
+
+ /**
+ * Method attribute. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitAttribute}.
*/
public abstract void visitMethodAttribute(final Attribute attr);
/**
- * Method start.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
+ * Method start. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitCode}.
*/
public abstract void visitCode();
/**
- * Method stack frame.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
+ * Method stack frame. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFrame}.
*/
- public abstract void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack);
+ public abstract void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}.
+ * Method instruction. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsn}
+ * .
*/
public abstract void visitInsn(final int opcode);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIntInsn}.
*/
public abstract void visitIntInsn(final int opcode, final int operand);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitVarInsn}.
*/
public abstract void visitVarInsn(final int opcode, final int var);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTypeInsn}.
*/
public abstract void visitTypeInsn(final int opcode, final String type);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitFieldInsn}.
*/
- public abstract void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc);
+ public abstract void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
*/
- public abstract void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc);
+ @Deprecated
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMethodInsn}.
*/
- public abstract void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs);
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ */
+ public abstract void visitInvokeDynamicInsn(String name, String desc,
+ Handle bsm, Object... bsmArgs);
+
+ /**
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitJumpInsn}.
*/
public abstract void visitJumpInsn(final int opcode, final Label label);
/**
- * Method label.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
+ * Method label. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLabel}.
*/
public abstract void visitLabel(final Label label);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLdcInsn}.
*/
public abstract void visitLdcInsn(final Object cst);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitIincInsn}.
*/
public abstract void visitIincInsn(final int var, final int increment);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTableSwitchInsn}.
+ */
+ public abstract void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels);
+
+ /**
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
*/
- public abstract void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels);
+ public abstract void visitLookupSwitchInsn(final Label dflt,
+ final int[] keys, final Label[] labels);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLookupSwitchInsn}.
+ * Method instruction. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
*/
- public abstract void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels);
+ public abstract void visitMultiANewArrayInsn(final String desc,
+ final int dims);
/**
- * Method instruction.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMultiANewArrayInsn}.
+ * Instruction type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitInsnAnnotation}.
*/
- public abstract void visitMultiANewArrayInsn(
- final String desc,
- final int dims);
+ public Printer visitInsnAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method exception handler.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
+ * Method exception handler. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchBlock}.
*/
- public abstract void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type);
+ public abstract void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type);
/**
- * Method debug info.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+ * Try catch block type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
*/
- public abstract void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index);
+ public Printer visitTryCatchAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
+
+ /**
+ * Method debug info. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLocalVariable}.
+ */
+ public abstract void visitLocalVariable(final String name,
+ final String desc, final String signature, final Label start,
+ final Label end, final int index);
+
+ /**
+ * Local variable type annotation. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitTryCatchAnnotation}.
+ */
+ public Printer visitLocalVariableAnnotation(final int typeRef,
+ final TypePath typePath, final Label[] start, final Label[] end,
+ final int[] index, final String desc, final boolean visible) {
+ throw new RuntimeException("Must be overriden");
+ }
/**
- * Method debug info.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
+ * Method debug info. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitLineNumber}.
*/
public abstract void visitLineNumber(final int line, final Label start);
/**
- * Method max stack and max locals.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
+ * Method max stack and max locals. See
+ * {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitMaxs}.
*/
public abstract void visitMaxs(final int maxStack, final int maxLocals);
/**
- * Method end.
- * See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
+ * Method end. See {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor#visitEnd}.
*/
public abstract void visitMethodEnd();
/**
* Returns the text constructed by this visitor.
- *
+ *
* @return the text constructed by this visitor.
*/
public List<Object> getText() {
@@ -496,8 +522,9 @@ public abstract class Printer {
/**
* Prints the text constructed by this visitor.
- *
- * @param pw the print writer to be used.
+ *
+ * @param pw
+ * the print writer to be used.
*/
public void print(final PrintWriter pw) {
printList(pw, text);
@@ -505,9 +532,11 @@ public abstract class Printer {
/**
* 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.
+ *
+ * @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('\"');
@@ -540,10 +569,12 @@ public abstract class Printer {
/**
* 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.
+ *
+ * @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) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
index 81156fc..dfa5e41 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifiable.java
@@ -29,26 +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 a readable
* representation of itself.
- *
+ *
* Implementations should construct readable output from an attribute data
* structure. Such representation could be used in unit test assertions.
- *
+ *
* @author Eugene Kuleshov
*/
public interface Textifiable {
/**
* Build a human readable representation of this attribute.
- *
- * @param buf a buffer used for printing Java code.
- * @param labelNames map of label instances to their names.
+ *
+ * @param buf
+ * a buffer used for printing Java code.
+ * @param labelNames
+ * map of label instances to their names.
*/
void textify(StringBuffer buf, 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/Textifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
index 3598080..854fe7c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/Textifier.java
@@ -29,14 +29,21 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
-import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
-
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;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureReader;
+
/**
* A {@link Printer} that prints a disassembled view of the classes it visits.
*
@@ -130,36 +137,49 @@ public class Textifier extends Printer {
*/
protected Map<Label, String> labelNames;
+ /**
+ * Class access flags
+ */
+ private int access;
+
private int valueNumber = 0;
/**
* Constructs a new {@link Textifier}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the {@link #Textifier(int)}
* version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public Textifier() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != Textifier.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link Textifier}.
*
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected Textifier(final int api) {
super(api);
}
/**
- * Prints a disassembled view of the given class to the standard output. <p>
- * Usage: Textifier [-debug] <binary class name or class
- * file name >
+ * Prints a disassembled view of the given class to the standard output.
+ * <p>
+ * Usage: Textifier [-debug] <binary class name or class file name >
*
- * @param args the command line arguments.
+ * @param args
+ * the command line arguments.
*
- * @throws Exception if the class cannot be found, or if an IO exception
- * occurs.
+ * @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;
@@ -177,21 +197,20 @@ public class Textifier extends Printer {
}
}
if (!ok) {
- System.err.println("Prints a disassembled view of the given class.");
+ System.err
+ .println("Prints a disassembled view of the given class.");
System.err.println("Usage: Textifier [-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)
- {
+ || args[i].indexOf('/') > -1) {
cr = new ClassReader(new FileInputStream(args[i]));
} else {
cr = new ClassReader(args[i]);
}
- cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
- flags);
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)), flags);
}
// ------------------------------------------------------------------------
@@ -199,38 +218,28 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ this.access = access;
int major = version & 0xFFFF;
int minor = version >>> 16;
buf.setLength(0);
- buf.append("// class version ")
- .append(major)
- .append('.')
- .append(minor)
- .append(" (")
- .append(version)
- .append(")\n");
+ buf.append("// class version ").append(major).append('.').append(minor)
+ .append(" (").append(version).append(")\n");
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append("// DEPRECATED\n");
}
- buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
appendDescriptor(CLASS_SIGNATURE, signature);
if (signature != null) {
TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
SignatureReader r = new SignatureReader(signature);
r.accept(sv);
- buf.append("// declaration: ")
- .append(name)
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append("// declaration: ").append(name)
+ .append(sv.getDeclaration()).append('\n');
}
appendAccess(access & ~Opcodes.ACC_SUPER);
@@ -264,15 +273,11 @@ public class Textifier extends Printer {
public void visitSource(final String file, final String debug) {
buf.setLength(0);
if (file != null) {
- buf.append(tab)
- .append("// compiled from: ")
- .append(file)
+ buf.append(tab).append("// compiled from: ").append(file)
.append('\n');
}
if (debug != null) {
- buf.append(tab)
- .append("// debug info: ")
- .append(debug)
+ buf.append(tab).append("// debug info: ").append(debug)
.append('\n');
}
if (buf.length() > 0) {
@@ -281,11 +286,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
buf.setLength(0);
buf.append(tab).append("OUTERCLASS ");
appendDescriptor(INTERNAL_NAME, owner);
@@ -299,30 +301,33 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitClassAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitClassAnnotation(final String desc,
+ final boolean visible) {
text.add("\n");
return visitAnnotation(desc, visible);
}
@Override
+ public Printer visitClassTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ text.add("\n");
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
public void visitClassAttribute(final Attribute attr) {
text.add("\n");
visitAttribute(attr);
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
buf.setLength(0);
buf.append(tab).append("// access flags 0x");
- buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n');
+ buf.append(
+ Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase())
+ .append('\n');
buf.append(tab);
appendAccess(access);
buf.append("INNERCLASS ");
@@ -336,19 +341,15 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public Textifier visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
buf.setLength(0);
buf.append('\n');
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append(tab).append("// DEPRECATED\n");
}
- buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
if (signature != null) {
buf.append(tab);
appendDescriptor(FIELD_SIGNATURE, signature);
@@ -356,10 +357,8 @@ public class Textifier extends Printer {
TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
SignatureReader r = new SignatureReader(signature);
r.acceptType(sv);
- buf.append(tab)
- .append("// declaration: ")
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append(tab).append("// declaration: ")
+ .append(sv.getDeclaration()).append('\n');
}
buf.append(tab);
@@ -385,19 +384,15 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ public Textifier visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
buf.setLength(0);
buf.append('\n');
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
buf.append(tab).append("// DEPRECATED\n");
}
- buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ buf.append(tab).append("// access flags 0x")
+ .append(Integer.toHexString(access).toUpperCase()).append('\n');
if (signature != null) {
buf.append(tab);
@@ -410,12 +405,8 @@ public class Textifier extends Printer {
String genericReturn = v.getReturnType();
String genericExceptions = v.getExceptions();
- buf.append(tab)
- .append("// declaration: ")
- .append(genericReturn)
- .append(' ')
- .append(name)
- .append(genericDecl);
+ buf.append(tab).append("// declaration: ").append(genericReturn)
+ .append(' ').append(name).append(genericDecl);
if (genericExceptions != null) {
buf.append(" throws ").append(genericExceptions);
}
@@ -433,6 +424,11 @@ public class Textifier extends Printer {
if ((access & Opcodes.ACC_BRIDGE) != 0) {
buf.append("bridge ");
}
+ if ((this.access & Opcodes.ACC_INTERFACE) != 0
+ && (access & Opcodes.ACC_ABSTRACT) == 0
+ && (access & Opcodes.ACC_STATIC) == 0) {
+ buf.append("default ");
+ }
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
@@ -588,11 +584,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -604,10 +597,7 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitAnnotation(
- final String name,
- final String desc)
- {
+ public Textifier visitAnnotation(final String name, final String desc) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -624,9 +614,7 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitArray(
- final String name)
- {
+ public Textifier visitArray(final String name) {
buf.setLength(0);
appendComa(valueNumber++);
if (name != null) {
@@ -649,14 +637,18 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
- public Textifier visitFieldAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitFieldAnnotation(final String desc,
+ final boolean visible) {
return visitAnnotation(desc, visible);
}
@Override
+ public Printer visitFieldTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
public void visitFieldAttribute(final Attribute attr) {
visitAttribute(attr);
}
@@ -670,6 +662,16 @@ public class Textifier extends Printer {
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(final String name, final int access) {
+ buf.setLength(0);
+ buf.append(tab2).append("// parameter ");
+ appendAccess(access);
+ buf.append(' ').append((name == null) ? "<no name>" : name)
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
public Textifier visitAnnotationDefault() {
text.add(tab2 + "default=");
Textifier t = createTextifier();
@@ -679,19 +681,20 @@ public class Textifier extends Printer {
}
@Override
- public Textifier visitMethodAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitMethodAnnotation(final String desc,
+ final boolean visible) {
return visitAnnotation(desc, visible);
}
@Override
- public Textifier visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public Printer visitMethodTypeAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
+ public Textifier visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
buf.setLength(0);
buf.append(tab2).append('@');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -725,40 +728,35 @@ public class Textifier extends Printer {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
buf.setLength(0);
buf.append(ltab);
buf.append("FRAME ");
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- buf.append("FULL [");
- appendFrameTypes(nLocal, local);
- buf.append("] [");
- appendFrameTypes(nStack, stack);
- buf.append(']');
- break;
- case Opcodes.F_APPEND:
- buf.append("APPEND [");
- appendFrameTypes(nLocal, local);
- buf.append(']');
- break;
- case Opcodes.F_CHOP:
- buf.append("CHOP ").append(nLocal);
- break;
- case Opcodes.F_SAME:
- buf.append("SAME");
- break;
- case Opcodes.F_SAME1:
- buf.append("SAME1 ");
- appendFrameTypes(1, stack);
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ buf.append("FULL [");
+ appendFrameTypes(nLocal, local);
+ buf.append("] [");
+ appendFrameTypes(nStack, stack);
+ buf.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ buf.append("APPEND [");
+ appendFrameTypes(nLocal, local);
+ buf.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("CHOP ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ buf.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ buf.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
}
buf.append('\n');
text.add(buf.toString());
@@ -777,20 +775,15 @@ public class Textifier extends Printer {
buf.append(tab2)
.append(OPCODES[opcode])
.append(' ')
- .append(opcode == Opcodes.NEWARRAY
- ? TYPES[operand]
- : Integer.toString(operand))
- .append('\n');
+ .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+ .toString(operand)).append('\n');
text.add(buf.toString());
}
@Override
public void visitVarInsn(final int opcode, final int var) {
buf.setLength(0);
- buf.append(tab2)
- .append(OPCODES[opcode])
- .append(' ')
- .append(var)
+ buf.append(tab2).append(OPCODES[opcode]).append(' ').append(var)
.append('\n');
text.add(buf.toString());
}
@@ -805,12 +798,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
buf.setLength(0);
buf.append(tab2).append(OPCODES[opcode]).append(' ');
appendDescriptor(INTERNAL_NAME, owner);
@@ -820,13 +809,30 @@ public class Textifier extends Printer {
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)
- {
+ 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(tab2).append(OPCODES[opcode]).append(' ');
appendDescriptor(INTERNAL_NAME, owner);
@@ -837,37 +843,42 @@ public class Textifier extends Printer {
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
buf.setLength(0);
buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
buf.append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
buf.append(" [");
+ buf.append('\n');
+ buf.append(tab3);
appendHandle(bsm);
+ buf.append('\n');
buf.append(tab3).append("// arguments:");
- if(bsmArgs.length == 0) {
+ if (bsmArgs.length == 0) {
buf.append(" none");
} else {
- buf.append('\n').append(tab3);
- for(int i = 0; i < bsmArgs.length; i++) {
+ buf.append('\n');
+ for (int i = 0; i < bsmArgs.length; i++) {
+ buf.append(tab3);
Object cst = bsmArgs[i];
if (cst instanceof String) {
Printer.appendString(buf, (String) cst);
} else if (cst instanceof Type) {
- buf.append(((Type) cst).getDescriptor()).append(".class");
+ Type type = (Type) cst;
+ if(type.getSort() == Type.METHOD){
+ appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
+ } else {
+ buf.append(type.getDescriptor()).append(".class");
+ }
} else if (cst instanceof Handle) {
appendHandle((Handle) cst);
} else {
buf.append(cst);
}
- buf.append(", ");
+ buf.append(", \n");
}
- buf.setLength(buf.length() - 2);
+ buf.setLength(buf.length() - 3);
}
buf.append('\n');
buf.append(tab2).append("]\n");
@@ -910,22 +921,14 @@ public class Textifier extends Printer {
@Override
public void visitIincInsn(final int var, final int increment) {
buf.setLength(0);
- buf.append(tab2)
- .append("IINC ")
- .append(var)
- .append(' ')
- .append(increment)
- .append('\n');
+ buf.append(tab2).append("IINC ").append(var).append(' ')
+ .append(increment).append('\n');
text.add(buf.toString());
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
buf.setLength(0);
buf.append(tab2).append("TABLESWITCH\n");
for (int i = 0; i < labels.length; ++i) {
@@ -940,11 +943,8 @@ public class Textifier extends Printer {
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
buf.setLength(0);
buf.append(tab2).append("LOOKUPSWITCH\n");
for (int i = 0; i < labels.length; ++i) {
@@ -968,12 +968,14 @@ public class Textifier extends Printer {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public Printer visitInsnAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ return visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
buf.setLength(0);
buf.append(tab2).append("TRYCATCHBLOCK ");
appendLabel(start);
@@ -988,14 +990,28 @@ public class Textifier extends Printer {
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public Printer visitTryCatchAnnotation(int typeRef, TypePath typePath,
+ String desc, boolean visible) {
+ buf.setLength(0);
+ buf.append(tab2).append("TRYCATCHBLOCK @");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ buf.append(visible ? "\n" : " // invisible\n");
+ text.add(buf.toString());
+ return t;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
buf.setLength(0);
buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1012,12 +1028,37 @@ public class Textifier extends Printer {
TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
SignatureReader r = new SignatureReader(signature);
r.acceptType(sv);
- buf.append(tab2)
- .append("// declaration: ")
- .append(sv.getDeclaration())
- .append('\n');
+ buf.append(tab2).append("// declaration: ")
+ .append(sv.getDeclaration()).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(tab2).append("LOCALVARIABLE @");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ for (int i = 0; i < start.length; ++i) {
+ buf.append(" [ ");
+ appendLabel(start[i]);
+ buf.append(" - ");
+ appendLabel(end[i]);
+ buf.append(" - ").append(index[i]).append(" ]");
}
+ buf.append(visible ? "\n" : " // invisible\n");
text.add(buf.toString());
+ return t;
}
@Override
@@ -1051,14 +1092,13 @@ public class Textifier extends Printer {
/**
* Prints a disassembled view of the given annotation.
*
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values.
*/
- public Textifier visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public Textifier visitAnnotation(final String desc, final boolean visible) {
buf.setLength(0);
buf.append(tab).append('@');
appendDescriptor(FIELD_DESCRIPTOR, desc);
@@ -1071,9 +1111,43 @@ public class Textifier extends Printer {
}
/**
+ * Prints a disassembled view of the given type annotation.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public Textifier visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ buf.setLength(0);
+ buf.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ buf.setLength(0);
+ buf.append(") : ");
+ appendTypeReference(typeRef);
+ buf.append(", ").append(typePath);
+ buf.append(visible ? "\n" : " // invisible\n");
+ text.add(buf.toString());
+ return t;
+ }
+
+ /**
* Prints a disassembled view of the given attribute.
*
- * @param attr an attribute.
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(final Attribute attr) {
buf.setLength(0);
@@ -1106,15 +1180,16 @@ public class Textifier extends Printer {
* Appends an internal name, a type descriptor or a type signature to
* {@link #buf buf}.
*
- * @param type indicates if desc is an internal name, a field descriptor, a
- * method descriptor, a class signature, ...
- * @param desc an internal name, type descriptor, or type signature. May be
- * <tt>null</tt>.
+ * @param type
+ * indicates if desc is an internal name, a field descriptor, a
+ * method descriptor, a class signature, ...
+ * @param desc
+ * an internal name, type descriptor, or type signature. May be
+ * <tt>null</tt>.
*/
protected void appendDescriptor(final int type, final String desc) {
if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
- || type == METHOD_SIGNATURE)
- {
+ || type == METHOD_SIGNATURE) {
if (desc != null) {
buf.append("// signature ").append(desc).append('\n');
}
@@ -1127,7 +1202,8 @@ public class Textifier extends Printer {
* Appends the name of the given label to {@link #buf buf}. Creates a new
* label name if the given label does not yet have one.
*
- * @param l a label.
+ * @param l
+ * a label.
*/
protected void appendLabel(final Label l) {
if (labelNames == null) {
@@ -1144,56 +1220,68 @@ public class Textifier extends Printer {
/**
* Appends the information about the given handle to {@link #buf buf}.
*
- * @param h a handle, non null.
+ * @param h
+ * a handle, non null.
*/
protected void appendHandle(final Handle h) {
- buf.append('\n').append(tab3);
int tag = h.getTag();
- buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+ buf.append("// handle kind 0x").append(Integer.toHexString(tag))
+ .append(" : ");
+ boolean isMethodHandle = false;
switch (tag) {
- case Opcodes.H_GETFIELD:
- buf.append("GETFIELD");
- break;
- case Opcodes.H_GETSTATIC:
- buf.append("GETSTATIC");
- break;
- case Opcodes.H_PUTFIELD:
- buf.append("PUTFIELD");
- break;
- case Opcodes.H_PUTSTATIC:
- buf.append("PUTSTATIC");
- break;
- case Opcodes.H_INVOKEINTERFACE:
- buf.append("INVOKEINTERFACE");
- break;
- case Opcodes.H_INVOKESPECIAL:
- buf.append("INVOKESPECIAL");
- break;
- case Opcodes.H_INVOKESTATIC:
- buf.append("INVOKESTATIC");
- break;
- case Opcodes.H_INVOKEVIRTUAL:
- buf.append("INVOKEVIRTUAL");
- break;
- case Opcodes.H_NEWINVOKESPECIAL:
- buf.append("NEWINVOKESPECIAL");
- break;
+ case Opcodes.H_GETFIELD:
+ buf.append("GETFIELD");
+ break;
+ case Opcodes.H_GETSTATIC:
+ buf.append("GETSTATIC");
+ break;
+ case Opcodes.H_PUTFIELD:
+ buf.append("PUTFIELD");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ buf.append("PUTSTATIC");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ buf.append("INVOKEINTERFACE");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ buf.append("INVOKESPECIAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ buf.append("INVOKESTATIC");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ buf.append("INVOKEVIRTUAL");
+ isMethodHandle = true;
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ buf.append("NEWINVOKESPECIAL");
+ isMethodHandle = true;
+ break;
}
buf.append('\n');
buf.append(tab3);
appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.');
buf.append(h.getName());
- buf.append('(');
+ if(!isMethodHandle){
+ buf.append('(');
+ }
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
- buf.append(')').append('\n');
+ if(!isMethodHandle){
+ buf.append(')');
+ }
}
/**
- * Appends a string representation of the given access modifiers to {@link
- * #buf buf}.
+ * Appends a string representation of the given access modifiers to
+ * {@link #buf buf}.
*
- * @param access some access modifiers.
+ * @param access
+ * some access modifiers.
*/
private void appendAccess(final int access) {
if ((access & Opcodes.ACC_PUBLIC) != 0) {
@@ -1226,6 +1314,12 @@ public class Textifier extends Printer {
if ((access & Opcodes.ACC_STRICT) != 0) {
buf.append("strictfp ");
}
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ buf.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_MANDATED) != 0) {
+ buf.append("mandated ");
+ }
if ((access & Opcodes.ACC_ENUM) != 0) {
buf.append("enum ");
}
@@ -1237,6 +1331,90 @@ public class Textifier extends Printer {
}
}
+ private void appendTypeReference(final int typeRef) {
+ TypeReference ref = new TypeReference(typeRef);
+ switch (ref.getSort()) {
+ case TypeReference.CLASS_TYPE_PARAMETER:
+ buf.append("CLASS_TYPE_PARAMETER ").append(
+ ref.getTypeParameterIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER:
+ buf.append("METHOD_TYPE_PARAMETER ").append(
+ ref.getTypeParameterIndex());
+ break;
+ case TypeReference.CLASS_EXTENDS:
+ buf.append("CLASS_EXTENDS ").append(ref.getSuperTypeIndex());
+ break;
+ case TypeReference.CLASS_TYPE_PARAMETER_BOUND:
+ buf.append("CLASS_TYPE_PARAMETER_BOUND ")
+ .append(ref.getTypeParameterIndex()).append(", ")
+ .append(ref.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.METHOD_TYPE_PARAMETER_BOUND:
+ buf.append("METHOD_TYPE_PARAMETER_BOUND ")
+ .append(ref.getTypeParameterIndex()).append(", ")
+ .append(ref.getTypeParameterBoundIndex());
+ break;
+ case TypeReference.FIELD:
+ buf.append("FIELD");
+ break;
+ case TypeReference.METHOD_RETURN:
+ buf.append("METHOD_RETURN");
+ break;
+ case TypeReference.METHOD_RECEIVER:
+ buf.append("METHOD_RECEIVER");
+ break;
+ case TypeReference.METHOD_FORMAL_PARAMETER:
+ buf.append("METHOD_FORMAL_PARAMETER ").append(
+ ref.getFormalParameterIndex());
+ break;
+ case TypeReference.THROWS:
+ buf.append("THROWS ").append(ref.getExceptionIndex());
+ break;
+ case TypeReference.LOCAL_VARIABLE:
+ buf.append("LOCAL_VARIABLE");
+ break;
+ case TypeReference.RESOURCE_VARIABLE:
+ buf.append("RESOURCE_VARIABLE");
+ break;
+ case TypeReference.EXCEPTION_PARAMETER:
+ buf.append("EXCEPTION_PARAMETER ").append(
+ ref.getTryCatchBlockIndex());
+ break;
+ case TypeReference.INSTANCEOF:
+ buf.append("INSTANCEOF");
+ break;
+ case TypeReference.NEW:
+ buf.append("NEW");
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE:
+ buf.append("CONSTRUCTOR_REFERENCE");
+ break;
+ case TypeReference.METHOD_REFERENCE:
+ buf.append("METHOD_REFERENCE");
+ break;
+ case TypeReference.CAST:
+ buf.append("CAST ").append(ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
+ buf.append("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT:
+ buf.append("METHOD_INVOCATION_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
+ buf.append("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ case TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT:
+ buf.append("METHOD_REFERENCE_TYPE_ARGUMENT ").append(
+ ref.getTypeArgumentIndex());
+ break;
+ }
+ }
+
private void appendFrameTypes(final int n, final Object[] o) {
for (int i = 0; i < n; ++i) {
if (i > 0) {
@@ -1251,27 +1429,27 @@ public class Textifier extends Printer {
}
} else if (o[i] instanceof Integer) {
switch (((Integer) o[i]).intValue()) {
- case 0:
- appendDescriptor(FIELD_DESCRIPTOR, "T");
- break;
- case 1:
- appendDescriptor(FIELD_DESCRIPTOR, "I");
- break;
- case 2:
- appendDescriptor(FIELD_DESCRIPTOR, "F");
- break;
- case 3:
- appendDescriptor(FIELD_DESCRIPTOR, "D");
- break;
- case 4:
- appendDescriptor(FIELD_DESCRIPTOR, "J");
- break;
- case 5:
- appendDescriptor(FIELD_DESCRIPTOR, "N");
- break;
- case 6:
- appendDescriptor(FIELD_DESCRIPTOR, "U");
- break;
+ case 0:
+ appendDescriptor(FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(FIELD_DESCRIPTOR, "U");
+ break;
}
} else {
appendLabel((Label) o[i]);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
index 84b9750..3af500a 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceAnnotationVisitor.java
@@ -33,13 +33,12 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
/**
- * An {@link org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor} that prints the annotations it visits with a
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a
* {@link Printer}.
- *
+ *
* @author Eric Bruneton
*/
-public final class TraceAnnotationVisitor extends AnnotationVisitor
-{
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
private final Printer p;
@@ -48,7 +47,7 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
}
public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
- super(Opcodes.ASM4, av);
+ super(Opcodes.ASM5, av);
this.p = p;
}
@@ -59,33 +58,26 @@ public final class TraceAnnotationVisitor extends AnnotationVisitor
}
@Override
- public void visitEnum(
- final String name,
- final String desc,
- final String value)
- {
+ public void visitEnum(final String name, final String desc,
+ final String value) {
p.visitEnum(name, desc, value);
super.visitEnum(name, desc, value);
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String name,
- final String desc)
- {
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
Printer p = this.p.visitAnnotation(name, desc);
- AnnotationVisitor av = this.av == null
- ? null
- : this.av.visitAnnotation(name, desc);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitAnnotation(name, desc);
return new TraceAnnotationVisitor(av, p);
}
@Override
public AnnotationVisitor visitArray(final String name) {
Printer p = this.p.visitArray(name);
- AnnotationVisitor av = this.av == null
- ? null
- : this.av.visitArray(name);
+ AnnotationVisitor av = this.av == null ? null : this.av
+ .visitArray(name);
return new TraceAnnotationVisitor(av, p);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
index ae06852..7c6a775 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceClassVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,18 +29,28 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.io.PrintWriter;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A {@link ClassVisitor} that prints the classes it visits with a
* {@link Printer}. This class visitor can be used in the middle of a class
* visitor chain to trace the class that is visited at a given point in this
- * chain. This may be useful for debugging purposes. <p> The trace printed when
- * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ * chain. This may be useful for debugging purposes.
+ * <p>
+ * The trace printed when visiting the <tt>Hello</tt> class is the following:
+ * <p>
+ * <blockquote>
*
- * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello {
+ * <pre>
+ * // class version 49.0 (49) // access flags 0x21 public class Hello {
*
* // compiled from: Hello.java
*
@@ -51,14 +60,21 @@ import java.io.PrintWriter;
* // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
* java/lang/System out Ljava/io/PrintStream; LDC "hello"
* INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
- * MAXSTACK = 2 MAXLOCALS = 1 } </pre>
+ * MAXSTACK = 2 MAXLOCALS = 1 }
+ * </pre>
*
- * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ * </blockquote> where <tt>Hello</tt> is defined by:
+ * <p>
+ * <blockquote>
*
- * <pre> public class Hello {
+ * <pre>
+ * public class Hello {
*
- * public static void main(String[] args) {
- * System.out.println("hello"); } } </pre>
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
+ * }
+ * </pre>
*
* </blockquote>
*
@@ -80,7 +96,8 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param pw the print writer to be used to print the class.
+ * @param pw
+ * the print writer to be used to print the class.
*/
public TraceClassVisitor(final PrintWriter pw) {
this(null, pw);
@@ -89,9 +106,11 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
- * May be <tt>null</tt>.
- * @param pw the print writer to be used to print the class.
+ * @param cv
+ * the {@link ClassVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ * @param pw
+ * the print writer to be used to print the class.
*/
public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
this(cv, new Textifier(), pw);
@@ -100,32 +119,27 @@ public final class TraceClassVisitor extends ClassVisitor {
/**
* Constructs a new {@link TraceClassVisitor}.
*
- * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
- * May be <tt>null</tt>.
- * @param p the object that actually converts visit events into text.
- * @param pw the print writer to be used to print the class. May be null if
- * you simply want to use the result via
- * {@link Printer#getText()}, instead of printing it.
+ * @param cv
+ * the {@link ClassVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ * @param p
+ * the object that actually converts visit events into text.
+ * @param pw
+ * the print writer to be used to print the class. May be null if
+ * you simply want to use the result via
+ * {@link Printer#getText()}, instead of printing it.
*/
- public TraceClassVisitor(
- final ClassVisitor cv,
- final Printer p,
- final PrintWriter pw)
- {
- super(Opcodes.ASM4, cv);
+ public TraceClassVisitor(final ClassVisitor cv, final Printer p,
+ final PrintWriter pw) {
+ super(Opcodes.ASM5, cv);
this.pw = pw;
this.p = p;
}
@Override
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces)
- {
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
p.visit(version, access, name, signature, superName, interfaces);
super.visit(version, access, name, signature, superName, interfaces);
}
@@ -137,20 +151,15 @@ public final class TraceClassVisitor extends ClassVisitor {
}
@Override
- public void visitOuterClass(
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
p.visitOuterClass(owner, name, desc);
super.visitOuterClass(owner, name, desc);
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitClassAnnotation(desc, visible);
AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
visible);
@@ -158,61 +167,44 @@ public final class TraceClassVisitor extends ClassVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitClassTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = cv == null ? null : cv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitClassAttribute(attr);
super.visitAttribute(attr);
}
@Override
- public void visitInnerClass(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
p.visitInnerClass(name, outerName, innerName, access);
super.visitInnerClass(name, outerName, innerName, access);
}
@Override
- public FieldVisitor visitField(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- Printer p = this.p.visitField(access,
- name,
- desc,
- signature,
- value);
- FieldVisitor fv = cv == null ? null : cv.visitField(access,
- name,
- desc,
- signature,
- value);
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ Printer p = this.p.visitField(access, name, desc, signature, value);
+ FieldVisitor fv = cv == null ? null : cv.visitField(access, name, desc,
+ signature, value);
return new TraceFieldVisitor(fv, p);
}
@Override
- public MethodVisitor visitMethod(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- Printer p = this.p.visitMethod(access,
- name,
- desc,
- signature,
- exceptions);
- MethodVisitor mv = cv == null ? null : cv.visitMethod(access,
- name,
- desc,
- signature,
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ Printer p = this.p.visitMethod(access, name, desc, signature,
exceptions);
+ MethodVisitor mv = cv == null ? null : cv.visitMethod(access, name,
+ desc, signature, exceptions);
return new TraceMethodVisitor(mv, p);
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
index d75b04b..3fed39e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceFieldVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,15 +33,15 @@ import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
import org.apache.tapestry5.internal.plastic.asm.Attribute;
import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
- * A {@link org.apache.tapestry5.internal.plastic.asm.FieldVisitor} that prints the fields it visits with a
+ * A {@link FieldVisitor} that prints the fields it visits with a
* {@link Printer}.
*
* @author Eric Bruneton
*/
-public final class TraceFieldVisitor extends FieldVisitor
-{
+public final class TraceFieldVisitor extends FieldVisitor {
public final Printer p;
@@ -51,15 +50,13 @@ public final class TraceFieldVisitor extends FieldVisitor
}
public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
- super(Opcodes.ASM4, fv);
+ super(Opcodes.ASM5, fv);
this.p = p;
}
-
+
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitFieldAnnotation(desc, visible);
AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
visible);
@@ -67,6 +64,16 @@ public final class TraceFieldVisitor extends FieldVisitor
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitFieldTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = fv == null ? null : fv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitFieldAttribute(attr);
super.visitAttribute(attr);
[12/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.java
new file mode 100644
index 0000000..b907322
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassConstantsCollector.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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link ClassVisitor} that collects the {@link Constant}s of the classes it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassConstantsCollector extends ClassVisitor {
+
+ private final ConstantPool cp;
+
+ public ClassConstantsCollector(final ClassVisitor cv, final ConstantPool cp) {
+ super(Opcodes.ASM5, cv);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ cp.newClass(name);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (superName != null) {
+ cp.newClass(superName);
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ cp.newClass(interfaces[i]);
+ }
+ }
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ if (source != null) {
+ cp.newUTF8("SourceFile");
+ cp.newUTF8(source);
+ }
+ if (debug != null) {
+ cp.newUTF8("SourceDebugExtension");
+ }
+ cv.visitSource(source, debug);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ cp.newUTF8("EnclosingMethod");
+ cp.newClass(owner);
+ if (name != null && desc != null) {
+ cp.newNameType(name, desc);
+ }
+ cv.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(cv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // can do nothing
+ cv.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ cp.newUTF8("InnerClasses");
+ if (name != null) {
+ cp.newClass(name);
+ }
+ if (outerName != null) {
+ cp.newClass(outerName);
+ }
+ if (innerName != null) {
+ cp.newUTF8(innerName);
+ }
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (value != null) {
+ cp.newConst(value);
+ }
+ return new FieldConstantsCollector(cv.visitField(access, name, desc,
+ signature, value), cp);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ cp.newUTF8("Synthetic");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cp.newUTF8("Deprecated");
+ }
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ if (signature != null) {
+ cp.newUTF8("Signature");
+ cp.newUTF8(signature);
+ }
+ if (exceptions != null) {
+ cp.newUTF8("Exceptions");
+ for (int i = 0; i < exceptions.length; ++i) {
+ cp.newClass(exceptions[i]);
+ }
+ }
+ return new MethodConstantsCollector(cv.visitMethod(access, name, desc,
+ signature, exceptions), cp);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
new file mode 100644
index 0000000..f4a7a22
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ClassOptimizer.java
@@ -0,0 +1,260 @@
+/***
+ * 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.optimizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingClassAdapter;
+
+/**
+ * A {@link ClassVisitor} that renames fields and methods, and removes debug
+ * info.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassOptimizer extends RemappingClassAdapter {
+
+ private String pkgName;
+ String clsName;
+
+ boolean isInterface = false;
+ boolean hasClinitMethod = false;
+ List<String> syntheticClassFields = new ArrayList<String>();
+
+ public ClassOptimizer(final ClassVisitor cv, final Remapper remapper) {
+ super(Opcodes.ASM5, cv, remapper);
+ }
+
+ FieldVisitor syntheticFieldVisitor(final int access, final String name,
+ final String desc) {
+ return super.visitField(access, name, desc, null, null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ super.visit(Opcodes.V1_2, access, name, null, superName, interfaces);
+ int index = name.lastIndexOf('/');
+ if (index > 0) {
+ pkgName = name.substring(0, index);
+ } else {
+ pkgName = "";
+ }
+ clsName = name;
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ // remove debug info
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // remove non standard attributes
+ }
+
+ @Override
+ public void visitInnerClass(final String name, final String outerName,
+ final String innerName, final int access) {
+ // remove debug info
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ String s = remapper.mapFieldName(className, name, desc);
+ if ("-".equals(s)) {
+ return null;
+ }
+ if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+ if ((access & Opcodes.ACC_FINAL) != 0
+ && (access & Opcodes.ACC_STATIC) != 0 && desc.length() == 1) {
+ return null;
+ }
+ if ("org/objectweb/asm".equals(pkgName) && s.equals(name)) {
+ System.out.println("INFO: " + clsName + "." + s
+ + " could be renamed");
+ }
+ super.visitField(access, name, desc, null, value);
+ } else {
+ if (!s.equals(name)) {
+ throw new RuntimeException("The public or protected field "
+ + className + '.' + name + " must not be renamed.");
+ }
+ super.visitField(access, name, desc, null, value);
+ }
+ return null; // remove debug info
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ String s = remapper.mapMethodName(className, name, desc);
+ if ("-".equals(s)) {
+ return null;
+ }
+ if (name.equals("<clinit>") && !isInterface) {
+ hasClinitMethod = true;
+ MethodVisitor mv = super.visitMethod(access, name, desc, null,
+ exceptions);
+ return new MethodVisitor(Opcodes.ASM5, mv) {
+ @Override
+ public void visitCode() {
+ super.visitCode();
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName,
+ "_clinit_", "()V", false);
+ }
+ };
+ }
+
+ if ((access & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED)) == 0) {
+ if ("org/objectweb/asm".equals(pkgName) && !name.startsWith("<")
+ && s.equals(name)) {
+ System.out.println("INFO: " + clsName + "." + s
+ + " could be renamed");
+ }
+ return super.visitMethod(access, name, desc, null, exceptions);
+ } else {
+ if (!s.equals(name)) {
+ throw new RuntimeException("The public or protected method "
+ + className + '.' + name + desc
+ + " must not be renamed.");
+ }
+ return super.visitMethod(access, name, desc, null, exceptions);
+ }
+ }
+
+ @Override
+ protected MethodVisitor createRemappingMethodAdapter(int access,
+ String newDesc, MethodVisitor mv) {
+ return new MethodOptimizer(this, access, newDesc, mv, remapper);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (syntheticClassFields.isEmpty()) {
+ if (hasClinitMethod) {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "_clinit_", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(0, 0);
+ mv.visitEnd();
+ }
+ } else {
+ MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC
+ | Opcodes.ACC_SYNTHETIC, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
+ mv.visitCode();
+ Label l0 = new Label();
+ Label l1 = new Label();
+ Label l2 = new Label();
+ mv.visitTryCatchBlock(l0, l1, l2,
+ "java/lang/ClassNotFoundException");
+ mv.visitLabel(l0);
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Class",
+ "forName", "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitLabel(l1);
+ mv.visitInsn(Opcodes.ARETURN);
+ mv.visitLabel(l2);
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+ "java/lang/ClassNotFoundException", "getMessage",
+ "()Ljava/lang/String;", false);
+ mv.visitVarInsn(Opcodes.ASTORE, 1);
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/NoClassDefFoundError");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ALOAD, 1);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL,
+ "java/lang/NoClassDefFoundError", "<init>",
+ "(Ljava/lang/String;)V", false);
+ mv.visitInsn(Opcodes.ATHROW);
+ mv.visitMaxs(3, 2);
+ mv.visitEnd();
+
+ if (hasClinitMethod) {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE,
+ "_clinit_", "()V", null, null);
+ } else {
+ mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V",
+ null, null);
+ }
+ for (String ldcName : syntheticClassFields) {
+ String fieldName = "class$" + ldcName.replace('/', '$');
+ mv.visitLdcInsn(ldcName.replace('/', '.'));
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, clsName, "class$",
+ "(Ljava/lang/String;)Ljava/lang/Class;", false);
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, clsName, fieldName,
+ "Ljava/lang/Class;");
+ }
+ mv.visitInsn(Opcodes.RETURN);
+ mv.visitMaxs(1, 0);
+ mv.visitEnd();
+ }
+ super.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
new file mode 100644
index 0000000..9c1f306
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Constant.java
@@ -0,0 +1,323 @@
+/***
+ * 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.optimizer;
+
+import java.util.Arrays;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+
+/**
+ * A constant pool item.
+ *
+ * @author Eric Bruneton
+ */
+class Constant {
+
+ /**
+ * Type of this constant pool item. A single class is used to represent all
+ * constant pool item types, in order to minimize the bytecode size of this
+ * package. The value of this field is I, J, F, D, S, s, C, T, G, M, N, y,
+ * t, [h..p] (for Constant Integer, Long, Float, Double, STR, UTF8, Class,
+ * NameType, Fieldref, Methodref, InterfaceMethodref, InvokeDynamic,
+ * MethodType and MethodHandle constant pool items respectively).
+ *
+ * The 9 variable of MethodHandle constants are stored between h and p.
+ */
+ char type;
+
+ /**
+ * Value of this item, for an integer item.
+ */
+ int intVal;
+
+ /**
+ * Value of this item, for a long item.
+ */
+ long longVal;
+
+ /**
+ * Value of this item, for a float item.
+ */
+ float floatVal;
+
+ /**
+ * Value of this item, for a double item.
+ */
+ double doubleVal;
+
+ /**
+ * First part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal1;
+
+ /**
+ * Second part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal2;
+
+ /**
+ * Third part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ Object objVal3;
+
+ /**
+ * InvokeDynamic's constant values.
+ */
+ Object[] objVals;
+
+ /**
+ * The hash code value of this constant pool item.
+ */
+ int hashCode;
+
+ Constant() {
+ }
+
+ Constant(final Constant i) {
+ type = i.type;
+ intVal = i.intVal;
+ longVal = i.longVal;
+ floatVal = i.floatVal;
+ doubleVal = i.doubleVal;
+ strVal1 = i.strVal1;
+ strVal2 = i.strVal2;
+ objVal3 = i.objVal3;
+ objVals = i.objVals;
+ hashCode = i.hashCode;
+ }
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal
+ * the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = 'I';
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
+
+ /**
+ * Sets this item to a long item.
+ *
+ * @param longVal
+ * the value of this item.
+ */
+ void set(final long longVal) {
+ this.type = 'J';
+ this.longVal = longVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+ }
+
+ /**
+ * Sets this item to a float item.
+ *
+ * @param floatVal
+ * the value of this item.
+ */
+ void set(final float floatVal) {
+ this.type = 'F';
+ this.floatVal = floatVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+ }
+
+ /**
+ * Sets this item to a double item.
+ *
+ * @param doubleVal
+ * the value of this item.
+ */
+ void set(final double doubleVal) {
+ this.type = 'D';
+ this.doubleVal = doubleVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+ }
+
+ /**
+ * Sets this item to an item that do not hold a primitive value.
+ *
+ * @param type
+ * the type of this item.
+ * @param strVal1
+ * first part of the value of this item.
+ * @param strVal2
+ * second part of the value of this item.
+ * @param strVal3
+ * third part of the value of this item.
+ */
+ void set(final char type, final String strVal1, final String strVal2,
+ final String strVal3) {
+ this.type = type;
+ this.strVal1 = strVal1;
+ this.strVal2 = strVal2;
+ this.objVal3 = strVal3;
+ switch (type) {
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case 'T':
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ // case 'G':
+ // case 'M':
+ // case 'N':
+ // case 'h' ... 'p':
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
+ }
+ }
+
+ /**
+ * Set this item to an InvokeDynamic item.
+ *
+ * @param name
+ * invokedynamic's name.
+ * @param desc
+ * invokedynamic's descriptor.
+ * @param bsm
+ * bootstrap method.
+ * @param bsmArgs
+ * bootstrap method constant arguments.
+ */
+ void set(final String name, final String desc, final Handle bsm,
+ final Object[] bsmArgs) {
+ this.type = 'y';
+ this.strVal1 = name;
+ this.strVal2 = desc;
+ this.objVal3 = bsm;
+ this.objVals = bsmArgs;
+
+ int hashCode = 'y' + name.hashCode() * desc.hashCode() * bsm.hashCode();
+ for (int i = 0; i < bsmArgs.length; i++) {
+ hashCode *= bsmArgs[i].hashCode();
+ }
+ this.hashCode = 0x7FFFFFFF & hashCode;
+ }
+
+ void write(final ClassWriter cw) {
+ switch (type) {
+ case 'I':
+ cw.newConst(new Integer(intVal));
+ break;
+ case 'J':
+ cw.newConst(new Long(longVal));
+ break;
+ case 'F':
+ cw.newConst(new Float(floatVal));
+ break;
+ case 'D':
+ cw.newConst(new Double(doubleVal));
+ break;
+ case 'S':
+ cw.newConst(strVal1);
+ break;
+ case 's':
+ cw.newUTF8(strVal1);
+ break;
+ case 'C':
+ cw.newClass(strVal1);
+ break;
+ case 'T':
+ cw.newNameType(strVal1, strVal2);
+ break;
+ case 'G':
+ cw.newField(strVal1, strVal2, (String) objVal3);
+ break;
+ case 'M':
+ cw.newMethod(strVal1, strVal2, (String) objVal3, false);
+ break;
+ case 'N':
+ cw.newMethod(strVal1, strVal2, (String) objVal3, true);
+ break;
+ case 'y':
+ cw.newInvokeDynamic(strVal1, strVal2, (Handle) objVal3, objVals);
+ break;
+ case 't':
+ cw.newMethodType(strVal1);
+ break;
+ default: // 'h' ... 'p': handle
+ cw.newHandle(type - 'h' + 1, strVal1, strVal2, (String) objVal3);
+ }
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Constant)) {
+ return false;
+ }
+ Constant c = (Constant) o;
+ if (c.type == type) {
+ switch (type) {
+ case 'I':
+ return c.intVal == intVal;
+ case 'J':
+ return c.longVal == longVal;
+ case 'F':
+ return Float.compare(c.floatVal, floatVal) == 0;
+ case 'D':
+ return Double.compare(c.doubleVal, doubleVal) == 0;
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ return c.strVal1.equals(strVal1);
+ case 'T':
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2);
+ case 'y':
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+ && c.objVal3.equals(objVal3)
+ && Arrays.equals(c.objVals, objVals);
+ // case 'G':
+ // case 'M':
+ // case 'N':
+ // case 'h' ... 'p':
+ default:
+ return c.strVal1.equals(strVal1) && c.strVal2.equals(strVal2)
+ && c.objVal3.equals(objVal3);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
new file mode 100644
index 0000000..1901387
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/ConstantPool.java
@@ -0,0 +1,249 @@
+/***
+ * 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.optimizer;
+
+import java.util.HashMap;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A constant pool.
+ *
+ * @author Eric Bruneton
+ */
+public class ConstantPool extends HashMap<Constant, Constant> {
+
+ private final Constant key1 = new Constant();
+
+ private final Constant key2 = new Constant();
+
+ private final Constant key3 = new Constant();
+
+ private final Constant key4 = new Constant();
+
+ private final Constant key5 = new Constant();
+
+ public Constant newInteger(final int value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newFloat(final float value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newLong(final long value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newDouble(final double value) {
+ key1.set(value);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newUTF8(final String value) {
+ key1.set('s', value, null, null);
+ Constant result = get(key1);
+ if (result == null) {
+ result = new Constant(key1);
+ put(result);
+ }
+ return result;
+ }
+
+ private Constant newString(final String value) {
+ key2.set('S', value, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(value);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newClass(final String value) {
+ key2.set('C', value, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(value);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newMethodType(final String methodDescriptor) {
+ key2.set('t', methodDescriptor, null, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(methodDescriptor);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newHandle(final int tag, final String owner,
+ final String name, final String desc) {
+ key4.set((char) ('h' - 1 + tag), owner, name, desc);
+ Constant result = get(key4);
+ if (result == null) {
+ if (tag <= Opcodes.H_PUTSTATIC) {
+ newField(owner, name, desc);
+ } else {
+ newMethod(owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
+ }
+ result = new Constant(key4);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newConst(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ return newFloat(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ return newLong(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ return newDouble(val);
+ } else if (cst instanceof String) {
+ return newString((String) cst);
+ } else if (cst instanceof Type) {
+ Type t = (Type) cst;
+ int s = t.getSort();
+ if (s == Type.OBJECT) {
+ return newClass(t.getInternalName());
+ } else if (s == Type.METHOD) {
+ return newMethodType(t.getDescriptor());
+ } else { // s == primitive type or array
+ return newClass(t.getDescriptor());
+ }
+ } else if (cst instanceof Handle) {
+ Handle h = (Handle) cst;
+ return newHandle(h.getTag(), h.getOwner(), h.getName(), h.getDesc());
+ } else {
+ throw new IllegalArgumentException("value " + cst);
+ }
+ }
+
+ public Constant newField(final String owner, final String name,
+ final String desc) {
+ key3.set('G', owner, name, desc);
+ Constant result = get(key3);
+ if (result == null) {
+ newClass(owner);
+ newNameType(name, desc);
+ result = new Constant(key3);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newMethod(final String owner, final String name,
+ final String desc, final boolean itf) {
+ key3.set(itf ? 'N' : 'M', owner, name, desc);
+ Constant result = get(key3);
+ if (result == null) {
+ newClass(owner);
+ newNameType(name, desc);
+ result = new Constant(key3);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newInvokeDynamic(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ key5.set(name, desc, bsm, bsmArgs);
+ Constant result = get(key5);
+ if (result == null) {
+ newNameType(name, desc);
+ newHandle(bsm.getTag(), bsm.getOwner(), bsm.getName(),
+ bsm.getDesc());
+ for (int i = 0; i < bsmArgs.length; i++) {
+ newConst(bsmArgs[i]);
+ }
+ result = new Constant(key5);
+ put(result);
+ }
+ return result;
+ }
+
+ public Constant newNameType(final String name, final String desc) {
+ key2.set('T', name, desc, null);
+ Constant result = get(key2);
+ if (result == null) {
+ newUTF8(name);
+ newUTF8(desc);
+ result = new Constant(key2);
+ put(result);
+ }
+ return result;
+ }
+
+ private Constant get(final Constant key) {
+ return get((Object) key);
+ }
+
+ private void put(final Constant cst) {
+ put(cst, cst);
+ }
+}
\ 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/optimizer/FieldConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
new file mode 100644
index 0000000..63ca654
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/FieldConstantsCollector.java
@@ -0,0 +1,89 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * A {@link FieldVisitor} that collects the {@link Constant}s of the fields it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldConstantsCollector extends FieldVisitor {
+
+ private final ConstantPool cp;
+
+ public FieldConstantsCollector(final FieldVisitor fv, final ConstantPool cp) {
+ super(Opcodes.ASM5, fv);
+ this.cp = cp;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(fv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ // can do nothing
+ fv.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ fv.visitEnd();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
new file mode 100644
index 0000000..e7d93cf
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/JarOptimizer.java
@@ -0,0 +1,235 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
+/**
+ * A Jar file optimizer.
+ *
+ * @author Eric Bruneton
+ */
+public class JarOptimizer {
+
+ static final Set<String> API = new HashSet<String>();
+ static final Map<String, String> HIERARCHY = new HashMap<String, String>();
+ static boolean nodebug = false;
+
+ public static void main(final String[] args) throws IOException {
+ File f = new File(args[0]);
+ InputStream is = new GZIPInputStream(new FileInputStream(f));
+ BufferedReader lnr = new LineNumberReader(new InputStreamReader(is));
+ while (true) {
+ String line = lnr.readLine();
+ if (line != null) {
+ if (line.startsWith("class")) {
+ String c = line.substring(6, line.lastIndexOf(' '));
+ String sc = line.substring(line.lastIndexOf(' ') + 1);
+ HIERARCHY.put(c, sc);
+ } else {
+ API.add(line);
+ }
+ } else {
+ break;
+ }
+ }
+
+ int argIndex = 1;
+ if (args[argIndex].equals("-nodebug")) {
+ nodebug = true;
+ argIndex++;
+ }
+
+ optimize(new File(args[argIndex]));
+ }
+
+ static void optimize(final File f) throws IOException {
+ if (nodebug && f.getName().contains("debug")) {
+ return;
+ }
+
+ if (f.isDirectory()) {
+ File[] files = f.listFiles();
+ for (int i = 0; i < files.length; ++i) {
+ optimize(files[i]);
+ }
+ } else if (f.getName().endsWith(".jar")) {
+ File g = new File(f.getParentFile(), f.getName() + ".new");
+ ZipFile zf = new ZipFile(f);
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(g));
+ Enumeration<? extends ZipEntry> e = zf.entries();
+ byte[] buf = new byte[10000];
+ while (e.hasMoreElements()) {
+ ZipEntry ze = e.nextElement();
+ if (ze.isDirectory()) {
+ out.putNextEntry(ze);
+ continue;
+ }
+ out.putNextEntry(ze);
+ if (ze.getName().endsWith(".class")) {
+ ClassReader cr = new ClassReader(zf.getInputStream(ze));
+ // cr.accept(new ClassDump(), 0);
+ cr.accept(new ClassVerifier(), 0);
+ }
+ InputStream is = zf.getInputStream(ze);
+ int n;
+ do {
+ n = is.read(buf, 0, buf.length);
+ if (n != -1) {
+ out.write(buf, 0, n);
+ }
+ } while (n != -1);
+ out.closeEntry();
+ }
+ out.close();
+ zf.close();
+ if (!f.delete()) {
+ throw new IOException("Cannot delete file " + f);
+ }
+ if (!g.renameTo(f)) {
+ throw new IOException("Cannot rename file " + g);
+ }
+ }
+ }
+
+ static class ClassDump extends ClassVisitor {
+
+ String owner;
+
+ public ClassDump() {
+ super(Opcodes.ASM5);
+ }
+
+ @Override
+ public void visit(final int version, final int access,
+ final String name, final String signature,
+ final String superName, final String[] interfaces) {
+ owner = name;
+ if (owner.startsWith("java/")) {
+ System.out.println("class " + name + ' ' + superName);
+ }
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ if (owner.startsWith("java/")) {
+ System.out.println(owner + ' ' + name);
+ }
+ return null;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions) {
+ if (owner.startsWith("java/")) {
+ System.out.println(owner + ' ' + name + desc);
+ }
+ return null;
+ }
+ }
+
+ static class ClassVerifier extends ClassVisitor {
+
+ String owner;
+
+ String method;
+
+ public ClassVerifier() {
+ super(Opcodes.ASM5);
+ }
+
+ @Override
+ public void visit(final int version, final int access,
+ final String name, final String signature,
+ final String superName, final String[] interfaces) {
+ owner = name;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions) {
+ method = name + desc;
+ return new MethodVisitor(Opcodes.ASM5) {
+ @Override
+ public void visitFieldInsn(final int opcode,
+ final String owner, final String name, final String desc) {
+ check(owner, name);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode,
+ final String owner, final String name,
+ final String desc, final boolean itf) {
+ check(owner, name + desc);
+ }
+ };
+ }
+
+ void check(String owner, String member) {
+ if (owner.startsWith("java/")) {
+ String o = owner;
+ while (o != null) {
+ if (API.contains(o + ' ' + member)) {
+ return;
+ }
+ o = HIERARCHY.get(o);
+ }
+ System.out.println("WARNING: " + owner + ' ' + member
+ + " called in " + this.owner + ' ' + method
+ + " is not defined in JDK 1.3 API");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
new file mode 100644
index 0000000..54b3519
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodConstantsCollector.java
@@ -0,0 +1,224 @@
+/***
+ * 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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
+/**
+ * An {@link MethodVisitor} that collects the {@link Constant}s of the methods
+ * it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodConstantsCollector extends MethodVisitor {
+
+ private final ConstantPool cp;
+
+ public MethodConstantsCollector(final MethodVisitor mv,
+ final ConstantPool cp) {
+ super(Opcodes.ASM5, mv);
+ this.cp = cp;
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ cp.newUTF8("MethodParameters");
+ if (name != null) {
+ cp.newUTF8(name);
+ }
+ mv.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ cp.newUTF8("AnnotationDefault");
+ return new AnnotationConstantsCollector(mv.visitAnnotationDefault(), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitAnnotation(desc,
+ visible), cp);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleParameterAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleParameterAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitParameterAnnotation(
+ parameter, desc, visible), cp);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ cp.newClass(type);
+ mv.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ cp.newField(owner, name, desc);
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ cp.newMethod(owner, name, desc, itf);
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ cp.newInvokeDynamic(name, desc, bsm, bsmArgs);
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ cp.newConst(cst);
+ mv.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ cp.newClass(desc);
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitInsnAnnotation(typeRef,
+ typePath, desc, visible), cp);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ if (type != null) {
+ cp.newClass(type);
+ }
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(mv.visitTryCatchAnnotation(
+ typeRef, typePath, desc, visible), cp);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ if (signature != null) {
+ cp.newUTF8("LocalVariableTypeTable");
+ cp.newUTF8(name);
+ cp.newUTF8(signature);
+ }
+ cp.newUTF8("LocalVariableTable");
+ cp.newUTF8(name);
+ cp.newUTF8(desc);
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ cp.newUTF8(desc);
+ if (visible) {
+ cp.newUTF8("RuntimeVisibleTypeAnnotations");
+ } else {
+ cp.newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ return new AnnotationConstantsCollector(
+ mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, visible), cp);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ cp.newUTF8("LineNumberTable");
+ mv.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ cp.newUTF8("Code");
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.java
new file mode 100644
index 0000000..adad6b4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/MethodOptimizer.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.optimizer;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.RemappingMethodAdapter;
+
+/**
+ * A {@link MethodVisitor} that renames fields and methods, and removes debug
+ * info.
+ *
+ * @author Eugene Kuleshov
+ */
+public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
+
+ private final ClassOptimizer classOptimizer;
+
+ public MethodOptimizer(ClassOptimizer classOptimizer, int access,
+ String desc, MethodVisitor mv, Remapper remapper) {
+ super(Opcodes.ASM5, access, desc, mv, remapper);
+ this.classOptimizer = classOptimizer;
+ }
+
+ // ------------------------------------------------------------------------
+ // Overridden methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(String name, int access) {
+ // remove parameter info
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return null;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ // remove annotations
+ return null;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ // remove debug info
+ }
+
+ @Override
+ public void visitFrame(int type, int local, Object[] local2, int stack,
+ Object[] stack2) {
+ // remove frame info
+ }
+
+ @Override
+ public void visitAttribute(Attribute attr) {
+ // remove non standard attributes
+ }
+
+ @Override
+ public void visitLdcInsn(Object cst) {
+ if (!(cst instanceof Type)) {
+ super.visitLdcInsn(cst);
+ return;
+ }
+
+ // transform Foo.class for 1.2 compatibility
+ String ldcName = ((Type) cst).getInternalName();
+ String fieldName = "class$" + ldcName.replace('/', '$');
+ if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
+ classOptimizer.syntheticClassFields.add(ldcName);
+ FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
+ | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
+ fv.visitEnd();
+ }
+
+ String clsName = classOptimizer.clsName;
+ mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
new file mode 100644
index 0000000..70d74f7
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/NameMapping.java
@@ -0,0 +1,114 @@
+/***
+ * 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.optimizer;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A MAPPING from names to names, used to rename classes, fields and methods.
+ *
+ * @author Eric Bruneton
+ */
+public class NameMapping {
+
+ public final Properties mapping;
+
+ public final Set<Object> unused;
+
+ public NameMapping(final String file) throws IOException {
+ mapping = new Properties();
+ InputStream is = null;
+ try {
+ is = new BufferedInputStream(new FileInputStream(file));
+ mapping.load(is);
+ unused = new HashSet<Object>(mapping.keySet());
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+
+ public String map(final String name) {
+ String s = (String) mapping.get(name);
+ if (s == null) {
+ int p = name.indexOf('.');
+ if (p == -1) {
+ s = name;
+ } else {
+ int q = name.indexOf('(');
+ if (q == -1) {
+ s = name.substring(p + 1);
+ } else {
+ s = name.substring(p + 1, q);
+ }
+ }
+ } else {
+ unused.remove(name);
+ }
+ return s;
+ }
+
+ public String fix(final String desc) {
+ if (desc.startsWith("(")) {
+ Type[] arguments = Type.getArgumentTypes(desc);
+ Type result = Type.getReturnType(desc);
+ for (int i = 0; i < arguments.length; ++i) {
+ arguments[i] = fix(arguments[i]);
+ }
+ result = fix(result);
+ return Type.getMethodDescriptor(result, arguments);
+ } else {
+ return fix(Type.getType(desc)).getDescriptor();
+ }
+ }
+
+ private Type fix(final Type t) {
+ if (t.getSort() == Type.OBJECT) {
+ return Type.getObjectType(map(t.getInternalName()));
+ } else if (t.getSort() == Type.ARRAY) {
+ String s = fix(t.getElementType()).getDescriptor();
+ for (int i = 0; i < t.getDimensions(); ++i) {
+ s = '[' + s;
+ }
+ return Type.getType(s);
+ } else {
+ return t;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
new file mode 100644
index 0000000..e20cf5c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/Shrinker.java
@@ -0,0 +1,283 @@
+/***
+ * 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.optimizer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
+import org.apache.tapestry5.internal.plastic.asm.commons.SimpleRemapper;
+
+/**
+ * A class file shrinker utility.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Shrinker {
+
+ static final HashMap<String, String> MAPPING = new HashMap<String, String>();
+
+ public static void main(final String[] args) throws IOException {
+ Properties properties = new Properties();
+ int n = args.length - 1;
+ for (int i = 0; i < n - 1; ++i) {
+ properties.load(new FileInputStream(args[i]));
+ }
+
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+ MAPPING.put((String) entry.getKey(), (String) entry.getValue());
+ }
+
+ final Set<String> unused = new HashSet<String>(MAPPING.keySet());
+
+ File f = new File(args[n - 1]);
+ File d = new File(args[n]);
+
+ optimize(f, d, new SimpleRemapper(MAPPING) {
+ @Override
+ public String map(String key) {
+ String s = super.map(key);
+ if (s != null) {
+ unused.remove(key);
+ }
+ return s;
+ }
+ });
+
+ Iterator<String> i = unused.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (!s.endsWith("/remove")) {
+ System.out.println("INFO: unused mapping " + s);
+ }
+ }
+ }
+
+ static void optimize(final File f, final File d, final Remapper remapper)
+ throws IOException {
+ if (f.isDirectory()) {
+ File[] files = f.listFiles();
+ for (int i = 0; i < files.length; ++i) {
+ optimize(files[i], d, remapper);
+ }
+ } else if (f.getName().endsWith(".class")) {
+ ConstantPool cp = new ConstantPool();
+ ClassReader cr = new ClassReader(new FileInputStream(f));
+ ClassWriter cw = new ClassWriter(0);
+ ClassConstantsCollector ccc = new ClassConstantsCollector(cw, cp);
+ ClassOptimizer co = new ClassOptimizer(ccc, remapper);
+ cr.accept(co, ClassReader.SKIP_DEBUG);
+
+ Set<Constant> constants = new TreeSet<Constant>(
+ new ConstantComparator());
+ constants.addAll(cp.values());
+
+ cr = new ClassReader(cw.toByteArray());
+ cw = new ClassWriter(0);
+ Iterator<Constant> i = constants.iterator();
+ while (i.hasNext()) {
+ Constant c = i.next();
+ c.write(cw);
+ }
+ cr.accept(cw, ClassReader.SKIP_DEBUG);
+
+ if (MAPPING.get(cr.getClassName() + "/remove") != null) {
+ return;
+ }
+ String n = remapper.mapType(cr.getClassName());
+ File g = new File(d, n + ".class");
+ if (!g.exists() || g.lastModified() < f.lastModified()) {
+ if (!g.getParentFile().exists() && !g.getParentFile().mkdirs()) {
+ throw new IOException("Cannot create directory "
+ + g.getParentFile());
+ }
+ OutputStream os = new FileOutputStream(g);
+ try {
+ os.write(cw.toByteArray());
+ } finally {
+ os.close();
+ }
+ }
+ }
+ }
+
+ static class ConstantComparator implements Comparator<Constant> {
+
+ public int compare(final Constant c1, final Constant c2) {
+ int d = getSort(c1) - getSort(c2);
+ if (d == 0) {
+ switch (c1.type) {
+ case 'I':
+ return new Integer(c1.intVal).compareTo(new Integer(
+ c2.intVal));
+ case 'J':
+ return new Long(c1.longVal).compareTo(new Long(c2.longVal));
+ case 'F':
+ return new Float(c1.floatVal).compareTo(new Float(
+ c2.floatVal));
+ case 'D':
+ return new Double(c1.doubleVal).compareTo(new Double(
+ c2.doubleVal));
+ case 's':
+ case 'S':
+ case 'C':
+ case 't':
+ return c1.strVal1.compareTo(c2.strVal1);
+ case 'T':
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ }
+ break;
+ case 'y':
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ if (d == 0) {
+ Handle bsm1 = (Handle) c1.objVal3;
+ Handle bsm2 = (Handle) c2.objVal3;
+ d = compareHandle(bsm1, bsm2);
+ if (d == 0) {
+ d = compareObjects(c1.objVals, c2.objVals);
+ }
+ }
+ }
+ break;
+
+ default:
+ d = c1.strVal1.compareTo(c2.strVal1);
+ if (d == 0) {
+ d = c1.strVal2.compareTo(c2.strVal2);
+ if (d == 0) {
+ d = ((String) c1.objVal3)
+ .compareTo((String) c2.objVal3);
+ }
+ }
+ }
+ }
+ return d;
+ }
+
+ private static int compareHandle(Handle h1, Handle h2) {
+ int d = h1.getTag() - h2.getTag();
+ if (d == 0) {
+ d = h1.getOwner().compareTo(h2.getOwner());
+ if (d == 0) {
+ d = h1.getName().compareTo(h2.getName());
+ if (d == 0) {
+ d = h1.getDesc().compareTo(h2.getDesc());
+ }
+ }
+ }
+ return d;
+ }
+
+ private static int compareType(Type mtype1, Type mtype2) {
+ return mtype1.getDescriptor().compareTo(mtype2.getDescriptor());
+ }
+
+ private static int compareObjects(Object[] objVals1, Object[] objVals2) {
+ int length = objVals1.length;
+ int d = length - objVals2.length;
+ if (d == 0) {
+ for (int i = 0; i < length; i++) {
+ Object objVal1 = objVals1[i];
+ Object objVal2 = objVals2[i];
+ d = objVal1.getClass().getName()
+ .compareTo(objVal2.getClass().getName());
+ if (d == 0) {
+ if (objVal1 instanceof Type) {
+ d = compareType((Type) objVal1, (Type) objVal2);
+ } else if (objVal1 instanceof Handle) {
+ d = compareHandle((Handle) objVal1,
+ (Handle) objVal2);
+ } else {
+ d = ((Comparable) objVal1).compareTo(objVal2);
+ }
+ }
+
+ if (d != 0) {
+ return d;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private static int getSort(final Constant c) {
+ switch (c.type) {
+ case 'I':
+ return 0;
+ case 'J':
+ return 1;
+ case 'F':
+ return 2;
+ case 'D':
+ return 3;
+ case 's':
+ return 4;
+ case 'S':
+ return 5;
+ case 'C':
+ return 6;
+ case 'T':
+ return 7;
+ case 'G':
+ return 8;
+ case 'M':
+ return 9;
+ case 'N':
+ return 10;
+ case 'y':
+ return 11;
+ case 't':
+ return 12;
+ default:
+ return 100 + c.type - 'h';
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz
new file mode 100644
index 0000000..39cdf9d
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.2.2_017.txt.gz differ
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz
new file mode 100644
index 0000000..a3c7aa6
Binary files /dev/null and b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/jdk1.3.1_19.txt.gz differ
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
new file mode 100644
index 0000000..03fec2e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/optimizer/shrink-annotations.properties
@@ -0,0 +1,53 @@
+###############################################################################
+#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.
+###############################################################################
+
+# class mappings
+
+org/objectweb/asm/AnnotationWriter/remove=true
+
+# field mappings
+
+org/objectweb/asm/ClassWriter.anns=-
+org/objectweb/asm/ClassWriter.ianns=-
+
+org/objectweb/asm/FieldWriter.anns=-
+org/objectweb/asm/FieldWriter.ianns=-
+
+org/objectweb/asm/MethodWriter.annd=-
+org/objectweb/asm/MethodWriter.anns=-
+org/objectweb/asm/MethodWriter.ianns=-
+org/objectweb/asm/MethodWriter.panns=-
+org/objectweb/asm/MethodWriter.ipanns=-
+
+# method mappings
+
+org/objectweb/asm/ClassReader.readAnnotationValue(I[CLjava/lang/String;Lorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readAnnotationValues(I[CZLorg/objectweb/asm/AnnotationVisitor;)I=-
+org/objectweb/asm/ClassReader.readParameterAnnotations(I[CZLorg/objectweb/asm/MethodVisitor;)V=-
[02/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
new file mode 100644
index 0000000..6d5715c
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/Processor.java
@@ -0,0 +1,1044 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tapestry5.internal.plastic.asm.ClassReader;
+import org.apache.tapestry5.internal.plastic.asm.ClassWriter;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Processor is a command line tool that can be used for bytecode waving
+ * directed by XSL transformation.
+ * <p>
+ * In order to use a concrete XSLT engine, system property
+ * <tt>javax.xml.transform.TransformerFactory</tt> must be set to one of the
+ * following values.
+ *
+ * <blockquote>
+ * <table border="1" cellspacing="0" cellpadding="3">
+ * <tr>
+ * <td>jd.xslt</td>
+ * <td>jd.xml.xslt.trax.TransformerFactoryImpl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Saxon</td>
+ * <td>net.sf.saxon.TransformerFactoryImpl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Caucho</td>
+ * <td>com.caucho.xsl.Xsl</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Xalan interpeter</td>
+ * <td>org.apache.xalan.processor.TransformerFactory</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>Xalan xsltc</td>
+ * <td>org.apache.xalan.xsltc.trax.TransformerFactoryImpl</td>
+ * </tr>
+ * </table>
+ * </blockquote>
+ *
+ * @author Eugene Kuleshov
+ */
+public class Processor {
+
+ public static final int BYTECODE = 1;
+
+ public static final int MULTI_XML = 2;
+
+ public static final int SINGLE_XML = 3;
+
+ private static final String SINGLE_XML_NAME = "classes.xml";
+
+ private final int inRepresentation;
+
+ private final int outRepresentation;
+
+ private final InputStream input;
+
+ private final OutputStream output;
+
+ private final Source xslt;
+
+ private int n = 0;
+
+ public Processor(final int inRepresenation, final int outRepresentation,
+ final InputStream input, final OutputStream output,
+ final Source xslt) {
+ this.inRepresentation = inRepresenation;
+ this.outRepresentation = outRepresentation;
+ this.input = input;
+ this.output = output;
+ this.xslt = xslt;
+ }
+
+ public int process() throws TransformerException, IOException, SAXException {
+ ZipInputStream zis = new ZipInputStream(input);
+ final ZipOutputStream zos = new ZipOutputStream(output);
+ final OutputStreamWriter osw = new OutputStreamWriter(zos);
+
+ Thread.currentThread().setContextClassLoader(
+ getClass().getClassLoader());
+
+ TransformerFactory tf = TransformerFactory.newInstance();
+ if (!tf.getFeature(SAXSource.FEATURE)
+ || !tf.getFeature(SAXResult.FEATURE)) {
+ return 0;
+ }
+
+ SAXTransformerFactory saxtf = (SAXTransformerFactory) tf;
+ Templates templates = null;
+ if (xslt != null) {
+ templates = saxtf.newTemplates(xslt);
+ }
+
+ // configuring outHandlerFactory
+ // ///////////////////////////////////////////////////////
+
+ EntryElement entryElement = getEntryElement(zos);
+
+ ContentHandler outDocHandler = null;
+ switch (outRepresentation) {
+ case BYTECODE:
+ outDocHandler = new OutputSlicingHandler(
+ new ASMContentHandlerFactory(zos), entryElement, false);
+ break;
+
+ case MULTI_XML:
+ outDocHandler = new OutputSlicingHandler(new SAXWriterFactory(osw,
+ true), entryElement, true);
+ break;
+
+ case SINGLE_XML:
+ ZipEntry outputEntry = new ZipEntry(SINGLE_XML_NAME);
+ zos.putNextEntry(outputEntry);
+ outDocHandler = new SAXWriter(osw, false);
+ break;
+
+ }
+
+ // configuring inputDocHandlerFactory
+ // /////////////////////////////////////////////////
+ ContentHandler inDocHandler;
+ if (templates == null) {
+ inDocHandler = outDocHandler;
+ } else {
+ inDocHandler = new InputSlicingHandler("class", outDocHandler,
+ new TransformerHandlerFactory(saxtf, templates,
+ outDocHandler));
+ }
+ ContentHandlerFactory inDocHandlerFactory = new SubdocumentHandlerFactory(
+ inDocHandler);
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.startDocument();
+ inDocHandler.startElement("", "classes", "classes",
+ new AttributesImpl());
+ }
+
+ int i = 0;
+ ZipEntry ze;
+ while ((ze = zis.getNextEntry()) != null) {
+ update(ze.getName(), n++);
+ if (isClassEntry(ze)) {
+ processEntry(zis, ze, inDocHandlerFactory);
+ } else {
+ OutputStream os = entryElement.openEntry(getName(ze));
+ copyEntry(zis, os);
+ entryElement.closeEntry();
+ }
+
+ i++;
+ }
+
+ if (inDocHandler != null && inRepresentation != SINGLE_XML) {
+ inDocHandler.endElement("", "classes", "classes");
+ inDocHandler.endDocument();
+ }
+
+ if (outRepresentation == SINGLE_XML) {
+ zos.closeEntry();
+ }
+ zos.flush();
+ zos.close();
+
+ return i;
+ }
+
+ private void copyEntry(final InputStream is, final OutputStream os)
+ throws IOException {
+ if (outRepresentation == SINGLE_XML) {
+ return;
+ }
+
+ byte[] buff = new byte[2048];
+ int i;
+ while ((i = is.read(buff)) != -1) {
+ os.write(buff, 0, i);
+ }
+ }
+
+ private boolean isClassEntry(final ZipEntry ze) {
+ String name = ze.getName();
+ return inRepresentation == SINGLE_XML && name.equals(SINGLE_XML_NAME)
+ || name.endsWith(".class") || name.endsWith(".class.xml");
+ }
+
+ private void processEntry(final ZipInputStream zis, final ZipEntry ze,
+ final ContentHandlerFactory handlerFactory) {
+ ContentHandler handler = handlerFactory.createContentHandler();
+ try {
+
+ // if (CODE2ASM.equals(command)) { // read bytecode and process it
+ // // with TraceClassVisitor
+ // ClassReader cr = new ClassReader(readEntry(zis, ze));
+ // cr.accept(new TraceClassVisitor(null, new PrintWriter(os)),
+ // false);
+ // }
+
+ boolean singleInputDocument = inRepresentation == SINGLE_XML;
+ if (inRepresentation == BYTECODE) { // read bytecode and process it
+ // with handler
+ ClassReader cr = new ClassReader(readEntry(zis, ze));
+ cr.accept(new SAXClassAdapter(handler, singleInputDocument), 0);
+
+ } else { // read XML and process it with handler
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ reader.setContentHandler(handler);
+ reader.parse(new InputSource(
+ singleInputDocument ? (InputStream) new ProtectedInputStream(
+ zis) : new ByteArrayInputStream(readEntry(zis,
+ ze))));
+
+ }
+ } catch (Exception ex) {
+ update(ze.getName(), 0);
+ update(ex, 0);
+ }
+ }
+
+ private EntryElement getEntryElement(final ZipOutputStream zos) {
+ if (outRepresentation == SINGLE_XML) {
+ return new SingleDocElement(zos);
+ }
+ return new ZipEntryElement(zos);
+ }
+
+ // private ContentHandlerFactory getHandlerFactory(
+ // OutputStream os,
+ // SAXTransformerFactory saxtf,
+ // Templates templates)
+ // {
+ // ContentHandlerFactory factory = null;
+ // if (templates == null) {
+ // if (outputRepresentation == BYTECODE) { // factory used to write
+ // // bytecode
+ // factory = new ASMContentHandlerFactory(os, computeMax);
+ // } else { // factory used to write XML
+ // factory = new SAXWriterFactory(os, true);
+ // }
+ // } else {
+ // if (outputRepresentation == BYTECODE) { // factory used to transform
+ // // and then write bytecode
+ // factory = new ASMTransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // computeMax);
+ // } else { // factory used to transformand then write XML
+ // factory = new TransformerHandlerFactory(saxtf,
+ // templates,
+ // os,
+ // outputRepresentation == SINGLE_XML);
+ // }
+ // }
+ // return factory;
+ // }
+
+ private String getName(final ZipEntry ze) {
+ String name = ze.getName();
+ if (isClassEntry(ze)) {
+ if (inRepresentation != BYTECODE && outRepresentation == BYTECODE) {
+ name = name.substring(0, name.length() - 4); // .class.xml to
+ // .class
+ } else if (inRepresentation == BYTECODE
+ && outRepresentation != BYTECODE) {
+ name += ".xml"; // .class to .class.xml
+ }
+ // } else if( CODE2ASM.equals( command)) {
+ // name = name.substring( 0, name.length()-6).concat( ".asm");
+ }
+ return name;
+ }
+
+ private static byte[] readEntry(final InputStream zis, final ZipEntry ze)
+ throws IOException {
+ long size = ze.getSize();
+ if (size > -1) {
+ byte[] buff = new byte[(int) size];
+ int k = 0;
+ int n;
+ while ((n = zis.read(buff, k, buff.length - k)) > 0) {
+ k += n;
+ }
+ return buff;
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ byte[] buff = new byte[4096];
+ int i;
+ while ((i = zis.read(buff)) != -1) {
+ bos.write(buff, 0, i);
+ }
+ return bos.toByteArray();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+ */
+ protected void update(final Object arg, final int n) {
+ if (arg instanceof Throwable) {
+ ((Throwable) arg).printStackTrace();
+ } else {
+ if (n % 100 == 0) {
+ System.err.println(n + " " + arg);
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws Exception {
+ if (args.length < 2) {
+ showUsage();
+ return;
+ }
+
+ int inRepresentation = getRepresentation(args[0]);
+ int outRepresentation = getRepresentation(args[1]);
+
+ InputStream is = System.in;
+ OutputStream os = new BufferedOutputStream(System.out);
+
+ Source xslt = null;
+ // boolean computeMax = true;
+
+ for (int i = 2; i < args.length; i++) {
+ if ("-in".equals(args[i])) {
+ is = new FileInputStream(args[++i]);
+
+ } else if ("-out".equals(args[i])) {
+ os = new BufferedOutputStream(new FileOutputStream(args[++i]));
+
+ } else if ("-xslt".equals(args[i])) {
+ xslt = new StreamSource(new FileInputStream(args[++i]));
+
+ // } else if( "-computemax".equals( args[ i].toLowerCase())) {
+ // computeMax = true;
+
+ } else {
+ showUsage();
+ return;
+
+ }
+ }
+
+ if (inRepresentation == 0 || outRepresentation == 0) {
+ showUsage();
+ return;
+ }
+
+ Processor m = new Processor(inRepresentation, outRepresentation, is,
+ os, xslt);
+
+ long l1 = System.currentTimeMillis();
+ int n = m.process();
+ long l2 = System.currentTimeMillis();
+ System.err.println(n);
+ System.err.println((l2 - l1) + "ms " + 1000f * n / (l2 - l1)
+ + " resources/sec");
+ }
+
+ private static int getRepresentation(final String s) {
+ if ("code".equals(s)) {
+ return BYTECODE;
+ } else if ("xml".equals(s)) {
+ return MULTI_XML;
+ } else if ("singlexml".equals(s)) {
+ return SINGLE_XML;
+ }
+ return 0;
+ }
+
+ private static void showUsage() {
+ System.err
+ .println("Usage: Main <in format> <out format> [-in <input jar>] [-out <output jar>] [-xslt <xslt fiel>]");
+ System.err
+ .println(" when -in or -out is omitted sysin and sysout would be used");
+ System.err
+ .println(" <in format> and <out format> - code | xml | singlexml");
+ }
+
+ /**
+ * IputStream wrapper class used to protect input streams from being closed
+ * by some stupid XML parsers.
+ */
+ private static final class ProtectedInputStream extends InputStream {
+ private final InputStream is;
+
+ ProtectedInputStream(final InputStream is) {
+ this.is = is;
+ }
+
+ @Override
+ public final void close() throws IOException {
+ }
+
+ @Override
+ public final int read() throws IOException {
+ return is.read();
+ }
+
+ @Override
+ public final int read(final byte[] b, final int off, final int len)
+ throws IOException {
+ return is.read(b, off, len);
+ }
+
+ @Override
+ public final int available() throws IOException {
+ return is.available();
+ }
+ }
+
+ /**
+ * A {@link ContentHandlerFactory ContentHandlerFactory} is used to create
+ * {@link org.xml.sax.ContentHandler ContentHandler} instances for concrete
+ * context.
+ */
+ private static interface ContentHandlerFactory {
+
+ /**
+ * Creates an instance of the content handler.
+ *
+ * @return content handler
+ */
+ ContentHandler createContentHandler();
+
+ }
+
+ /**
+ * SAXWriterFactory
+ */
+ private static final class SAXWriterFactory implements
+ ContentHandlerFactory {
+ private final Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ SAXWriterFactory(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return new SAXWriter(w, optimizeEmptyElements);
+ }
+
+ }
+
+ /**
+ * ASMContentHandlerFactory
+ */
+ private static final class ASMContentHandlerFactory implements
+ ContentHandlerFactory {
+ final OutputStream os;
+
+ ASMContentHandlerFactory(final OutputStream os) {
+ this.os = os;
+ }
+
+ public final ContentHandler createContentHandler() {
+ final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ return new ASMContentHandler(cw) {
+ @Override
+ public void endDocument() throws SAXException {
+ try {
+ os.write(cw.toByteArray());
+ } catch (IOException e) {
+ throw new SAXException(e);
+ }
+ }
+ };
+ }
+
+ }
+
+ /**
+ * TransformerHandlerFactory
+ */
+ private static final class TransformerHandlerFactory implements
+ ContentHandlerFactory {
+ private SAXTransformerFactory saxtf;
+
+ private final Templates templates;
+
+ private ContentHandler outputHandler;
+
+ TransformerHandlerFactory(final SAXTransformerFactory saxtf,
+ final Templates templates, final ContentHandler outputHandler) {
+ this.saxtf = saxtf;
+ this.templates = templates;
+ this.outputHandler = outputHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ try {
+ TransformerHandler handler = saxtf
+ .newTransformerHandler(templates);
+ handler.setResult(new SAXResult(outputHandler));
+ return handler;
+ } catch (TransformerConfigurationException ex) {
+ throw new RuntimeException(ex.toString());
+ }
+ }
+ }
+
+ /**
+ * SubdocumentHandlerFactory
+ */
+ private static final class SubdocumentHandlerFactory implements
+ ContentHandlerFactory {
+ private final ContentHandler subdocumentHandler;
+
+ SubdocumentHandlerFactory(final ContentHandler subdocumentHandler) {
+ this.subdocumentHandler = subdocumentHandler;
+ }
+
+ public final ContentHandler createContentHandler() {
+ return subdocumentHandler;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} and
+ * {@link org.xml.sax.ext.LexicalHandler LexicalHandler} that serializes XML
+ * from SAX 2.0 events into {@link java.io.Writer Writer}.
+ *
+ * <i><blockquote> This implementation does not support namespaces, entity
+ * definitions (uncluding DTD), CDATA and text elements. </blockquote></i>
+ */
+ private static final class SAXWriter extends DefaultHandler implements
+ LexicalHandler {
+ private static final char[] OFF = " "
+ .toCharArray();
+
+ private Writer w;
+
+ private final boolean optimizeEmptyElements;
+
+ private boolean openElement = false;
+
+ private int ident = 0;
+
+ /**
+ * Creates <code>SAXWriter</code>.
+ *
+ * @param w
+ * writer
+ * @param optimizeEmptyElements
+ * if set to <code>true</code>, short XML syntax will be used
+ * for empty elements
+ */
+ SAXWriter(final Writer w, final boolean optimizeEmptyElements) {
+ this.w = w;
+ this.optimizeEmptyElements = optimizeEmptyElements;
+ }
+
+ @Override
+ public final void startElement(final String ns, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write('<' + qName);
+ if (atts != null && atts.getLength() > 0) {
+ writeAttributes(atts);
+ }
+
+ if (optimizeEmptyElements) {
+ openElement = true;
+ } else {
+ w.write(">\n");
+ }
+ ident += 2;
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endElement(final String ns, final String localName,
+ final String qName) throws SAXException {
+ ident -= 2;
+ try {
+ if (openElement) {
+ w.write("/>\n");
+ openElement = false;
+ } else {
+ writeIdent();
+ w.write("</" + qName + ">\n");
+ }
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ try {
+ w.flush();
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void comment(final char[] ch, final int off, final int len)
+ throws SAXException {
+ try {
+ closeElement();
+
+ writeIdent();
+ w.write("<!-- ");
+ w.write(ch, off, len);
+ w.write(" -->\n");
+
+ } catch (IOException ex) {
+ throw new SAXException(ex);
+
+ }
+ }
+
+ public final void startDTD(final String arg0, final String arg1,
+ final String arg2) throws SAXException {
+ }
+
+ public final void endDTD() throws SAXException {
+ }
+
+ public final void startEntity(final String arg0) throws SAXException {
+ }
+
+ public final void endEntity(final String arg0) throws SAXException {
+ }
+
+ public final void startCDATA() throws SAXException {
+ }
+
+ public final void endCDATA() throws SAXException {
+ }
+
+ private final void writeAttributes(final Attributes atts)
+ throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int len = atts.getLength();
+ for (int i = 0; i < len; i++) {
+ sb.append(' ').append(atts.getLocalName(i)).append("=\"")
+ .append(esc(atts.getValue(i))).append('\"');
+ }
+ w.write(sb.toString());
+ }
+
+ /**
+ * Encode string with escaping.
+ *
+ * @param str
+ * string to encode.
+ * @return encoded string
+ */
+ private static final String esc(final String str) {
+ StringBuffer sb = new StringBuffer(str.length());
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '&':
+ sb.append("&");
+ break;
+
+ case '<':
+ sb.append("<");
+ break;
+
+ case '>':
+ sb.append(">");
+ break;
+
+ case '\"':
+ sb.append(""");
+ break;
+
+ default:
+ if (ch > 0x7f) {
+ sb.append("&#").append(Integer.toString(ch))
+ .append(';');
+ } else {
+ sb.append(ch);
+ }
+
+ }
+ }
+ return sb.toString();
+ }
+
+ private final void writeIdent() throws IOException {
+ int n = ident;
+ while (n > 0) {
+ if (n > OFF.length) {
+ w.write(OFF);
+ n -= OFF.length;
+ } else {
+ w.write(OFF, 0, n);
+ n = 0;
+ }
+ }
+ }
+
+ private final void closeElement() throws IOException {
+ if (openElement) {
+ w.write(">\n");
+ }
+ openElement = false;
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ * <p>
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class InputSlicingHandler extends DefaultHandler {
+ private String subdocumentRoot;
+
+ private final ContentHandler rootHandler;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link InputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentRoot
+ * name/path to the root element of the subdocument
+ * @param rootHandler
+ * content handler for the entire document (subdocument
+ * envelope).
+ * @param subdocumentHandlerFactory
+ * a {@link ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link ContentHandler ContentHandler} instances
+ * for subdocuments.
+ */
+ InputSlicingHandler(final String subdocumentRoot,
+ final ContentHandler rootHandler,
+ final ContentHandlerFactory subdocumentHandlerFactory) {
+ this.subdocumentRoot = subdocumentRoot;
+ this.rootHandler = rootHandler;
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ } else if (rootHandler != null) {
+ rootHandler.startElement(namespaceURI, localName, qName, list);
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ }
+ } else if (rootHandler != null) {
+ rootHandler.endElement(namespaceURI, localName, qName);
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.startDocument();
+ }
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ if (rootHandler != null) {
+ rootHandler.endDocument();
+
+ }
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ } else if (rootHandler != null) {
+ rootHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ /**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that splits XML
+ * documents into smaller chunks. Each chunk is processed by the nested
+ * {@link org.xml.sax.ContentHandler ContentHandler} obtained from
+ * {@link java.net.ContentHandlerFactory ContentHandlerFactory}. This is
+ * useful for running XSLT engine against large XML document that will
+ * hardly fit into the memory all together.
+ *
+ * <p>
+ * TODO use complete path for subdocumentRoot
+ */
+ private static final class OutputSlicingHandler extends DefaultHandler {
+ private final String subdocumentRoot;
+
+ private ContentHandlerFactory subdocumentHandlerFactory;
+
+ private final EntryElement entryElement;
+
+ private boolean isXml;
+
+ private boolean subdocument = false;
+
+ private ContentHandler subdocumentHandler;
+
+ /**
+ * Constructs a new {@link OutputSlicingHandler SubdocumentHandler}
+ * object.
+ *
+ * @param subdocumentHandlerFactory
+ * a {@link ContentHandlerFactory ContentHandlerFactory} used
+ * to create {@link ContentHandler ContentHandler} instances
+ * for subdocuments.
+ * @param entryElement
+ * TODO.
+ * @param isXml
+ * TODO.
+ */
+ OutputSlicingHandler(
+ final ContentHandlerFactory subdocumentHandlerFactory,
+ final EntryElement entryElement, final boolean isXml) {
+ this.subdocumentRoot = "class";
+ this.subdocumentHandlerFactory = subdocumentHandlerFactory;
+ this.entryElement = entryElement;
+ this.isXml = isXml;
+ }
+
+ @Override
+ public final void startElement(final String namespaceURI,
+ final String localName, final String qName,
+ final Attributes list) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ } else if (localName.equals(subdocumentRoot)) {
+ String name = list.getValue("name");
+ if (name == null || name.length() == 0) {
+ throw new SAXException(
+ "Class element without name attribute.");
+ }
+ try {
+ entryElement.openEntry(isXml ? name + ".class.xml" : name
+ + ".class");
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ subdocumentHandler = subdocumentHandlerFactory
+ .createContentHandler();
+ subdocumentHandler.startDocument();
+ subdocumentHandler.startElement(namespaceURI, localName, qName,
+ list);
+ subdocument = true;
+ }
+ }
+
+ @Override
+ public final void endElement(final String namespaceURI,
+ final String localName, final String qName) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.endElement(namespaceURI, localName, qName);
+ if (localName.equals(subdocumentRoot)) {
+ subdocumentHandler.endDocument();
+ subdocument = false;
+ try {
+ entryElement.closeEntry();
+ } catch (IOException ex) {
+ throw new SAXException(ex.toString(), ex);
+ }
+ }
+ }
+ }
+
+ @Override
+ public final void startDocument() throws SAXException {
+ }
+
+ @Override
+ public final void endDocument() throws SAXException {
+ }
+
+ @Override
+ public final void characters(final char[] buff, final int offset,
+ final int size) throws SAXException {
+ if (subdocument) {
+ subdocumentHandler.characters(buff, offset, size);
+ }
+ }
+
+ }
+
+ private static interface EntryElement {
+
+ OutputStream openEntry(String name) throws IOException;
+
+ void closeEntry() throws IOException;
+
+ }
+
+ private static final class SingleDocElement implements EntryElement {
+ private final OutputStream os;
+
+ SingleDocElement(final OutputStream os) {
+ this.os = os;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ return os;
+ }
+
+ public void closeEntry() throws IOException {
+ os.flush();
+ }
+
+ }
+
+ private static final class ZipEntryElement implements EntryElement {
+ private ZipOutputStream zos;
+
+ ZipEntryElement(final ZipOutputStream zos) {
+ this.zos = zos;
+ }
+
+ public OutputStream openEntry(final String name) throws IOException {
+ ZipEntry entry = new ZipEntry(name);
+ zos.putNextEntry(entry);
+ return zos;
+ }
+
+ public void closeEntry() throws IOException {
+ zos.flush();
+ zos.closeEntry();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
new file mode 100644
index 0000000..2f49c24
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAdapter.java
@@ -0,0 +1,89 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * SAXAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public class SAXAdapter {
+
+ private final ContentHandler h;
+
+ protected SAXAdapter(final ContentHandler h) {
+ this.h = h;
+ }
+
+ protected ContentHandler getContentHandler() {
+ return h;
+ }
+
+ protected void addDocumentStart() {
+ try {
+ h.startDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected void addDocumentEnd() {
+ try {
+ h.endDocument();
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addStart(final String name, final Attributes attrs) {
+ try {
+ h.startElement("", name, name, attrs);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addEnd(final String name) {
+ try {
+ h.endElement("", name, name);
+ } catch (SAXException ex) {
+ throw new RuntimeException(ex.getMessage(), ex.getException());
+ }
+ }
+
+ protected final void addElement(final String name, final Attributes attrs) {
+ addStart(name, attrs);
+ addEnd(name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
new file mode 100644
index 0000000..491c57e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXAnnotationAdapter.java
@@ -0,0 +1,242 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * SAXAnnotationAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXAnnotationAdapter extends AnnotationVisitor {
+
+ SAXAdapter sa;
+
+ private final String elementName;
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, -1, null,
+ null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final int parameter, final String desc) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, null, parameter, -1,
+ null, null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc,
+ final int typeRef, final TypePath typePath) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+ typePath, null, null, null);
+ }
+
+ public SAXAnnotationAdapter(final SAXAdapter sa, final String elementName,
+ final int visible, final String name, final String desc,
+ int typeRef, TypePath typePath, final String[] start,
+ final String[] end, final int[] index) {
+ this(Opcodes.ASM5, sa, elementName, visible, desc, name, -1, typeRef,
+ typePath, start, end, index);
+ }
+
+ protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+ final String elementName, final int visible, final String desc,
+ final String name, final int parameter) {
+ this(api, sa, elementName, visible, desc, name, parameter, -1, null,
+ null, null, null);
+ }
+
+ protected SAXAnnotationAdapter(final int api, final SAXAdapter sa,
+ final String elementName, final int visible, final String desc,
+ final String name, final int parameter, final int typeRef,
+ final TypePath typePath, final String[] start, final String[] end,
+ final int[] index) {
+ super(api);
+ this.sa = sa;
+ this.elementName = elementName;
+
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (visible != 0) {
+ att.addAttribute("", "visible", "visible", "", visible > 0 ? "true"
+ : "false");
+ }
+ if (parameter != -1) {
+ att.addAttribute("", "parameter", "parameter", "",
+ Integer.toString(parameter));
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+ if (typeRef != -1) {
+ att.addAttribute("", "typeRef", "typeRef", "",
+ Integer.toString(typeRef));
+ }
+ if (typePath != null) {
+ att.addAttribute("", "typePath", "typePath", "",
+ typePath.toString());
+ }
+ if (start != null) {
+ StringBuffer value = new StringBuffer(start[0]);
+ for (int i = 1; i < start.length; ++i) {
+ value.append(" ").append(start[i]);
+ }
+ att.addAttribute("", "start", "start", "", value.toString());
+ }
+ if (end != null) {
+ StringBuffer value = new StringBuffer(end[0]);
+ for (int i = 1; i < end.length; ++i) {
+ value.append(" ").append(end[i]);
+ }
+ att.addAttribute("", "end", "end", "", value.toString());
+ }
+ if (index != null) {
+ StringBuffer value = new StringBuffer();
+ value.append(index[0]);
+ for (int i = 1; i < index.length; ++i) {
+ value.append(" ").append(index[i]);
+ }
+ att.addAttribute("", "index", "index", "", value.toString());
+ }
+
+ sa.addStart(elementName, att);
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ Class<?> c = value.getClass();
+ if (c.isArray()) {
+ AnnotationVisitor av = visitArray(name);
+ if (value instanceof byte[]) {
+ byte[] b = (byte[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Byte(b[i]));
+ }
+
+ } else if (value instanceof char[]) {
+ char[] b = (char[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Character(b[i]));
+ }
+
+ } else if (value instanceof short[]) {
+ short[] b = (short[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Short(b[i]));
+ }
+
+ } else if (value instanceof boolean[]) {
+ boolean[] b = (boolean[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, Boolean.valueOf(b[i]));
+ }
+
+ } else if (value instanceof int[]) {
+ int[] b = (int[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Integer(b[i]));
+ }
+
+ } else if (value instanceof long[]) {
+ long[] b = (long[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Long(b[i]));
+ }
+
+ } else if (value instanceof float[]) {
+ float[] b = (float[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Float(b[i]));
+ }
+
+ } else if (value instanceof double[]) {
+ double[] b = (double[]) value;
+ for (int i = 0; i < b.length; i++) {
+ av.visit(null, new Double(b[i]));
+ }
+
+ }
+ av.visitEnd();
+ } else {
+ addValueElement("annotationValue", name, Type.getDescriptor(c),
+ value.toString());
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ addValueElement("annotationValueEnum", name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ return new SAXAnnotationAdapter(sa, "annotationValueAnnotation", 0,
+ name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ return new SAXAnnotationAdapter(sa, "annotationValueArray", 0, name,
+ null);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd(elementName);
+ }
+
+ private void addValueElement(final String element, final String name,
+ final String desc, final String value) {
+ AttributesImpl att = new AttributesImpl();
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "",
+ SAXClassAdapter.encode(value));
+ }
+
+ sa.addElement(element, att);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
new file mode 100644
index 0000000..dc4cb66
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXClassAdapter.java
@@ -0,0 +1,335 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor ClassVisitor} that generates SAX 2.0
+ * events from the visited class. It can feed any kind of
+ * {@link org.xml.sax.ContentHandler ContentHandler}, e.g. XML serializer, XSLT
+ * or XQuery engines.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.ASMContentHandler
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXClassAdapter extends ClassVisitor {
+
+ SAXAdapter sa;
+
+ private final boolean singleDocument;
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * Constructs a new {@link SAXClassAdapter SAXClassAdapter} object.
+ *
+ * @param h
+ * content handler that will be used to send SAX 2.0 events.
+ * @param singleDocument
+ * if <tt>true</tt> adapter will not produce
+ * {@link ContentHandler#startDocument() startDocument()} and
+ * {@link ContentHandler#endDocument() endDocument()} events.
+ */
+ public SAXClassAdapter(final ContentHandler h, boolean singleDocument) {
+ super(Opcodes.ASM5);
+ this.sa = new SAXAdapter(h);
+ this.singleDocument = singleDocument;
+ if (!singleDocument) {
+ sa.addDocumentStart();
+ }
+ }
+
+ @Override
+ public void visitSource(final String source, final String debug) {
+ AttributesImpl att = new AttributesImpl();
+ if (source != null) {
+ att.addAttribute("", "file", "file", "", encode(source));
+ }
+ if (debug != null) {
+ att.addAttribute("", "debug", "debug", "", encode(debug));
+ }
+
+ sa.addElement("source", att);
+ }
+
+ @Override
+ public void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "owner", "owner", "", owner);
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (desc != null) {
+ att.addAttribute("", "desc", "desc", "", desc);
+ }
+
+ sa.addElement("outerclass", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name,
+ final String signature, final String superName,
+ final String[] interfaces) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_CLASS, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (superName != null) {
+ att.addAttribute("", "parent", "parent", "", superName);
+ }
+ att.addAttribute("", "major", "major", "",
+ Integer.toString(version & 0xFFFF));
+ att.addAttribute("", "minor", "minor", "",
+ Integer.toString(version >>> 16));
+ sa.addStart("class", att);
+
+ sa.addStart("interfaces", new AttributesImpl());
+ if (interfaces != null && interfaces.length > 0) {
+ for (int i = 0; i < interfaces.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", interfaces[i]);
+ sa.addElement("interface", att2);
+ }
+ }
+ sa.addEnd("interfaces");
+ }
+
+ @Override
+ public FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_FIELD, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "",
+ encode(signature));
+ }
+ if (value != null) {
+ att.addAttribute("", "value", "value", "", encode(value.toString()));
+ }
+
+ return new SAXFieldAdapter(sa, att);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ att.addAttribute("", "name", "name", "", name);
+ att.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ att.addAttribute("", "signature", "signature", "", signature);
+ }
+ sa.addStart("method", att);
+
+ sa.addStart("exceptions", new AttributesImpl());
+ if (exceptions != null && exceptions.length > 0) {
+ for (int i = 0; i < exceptions.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", exceptions[i]);
+ sa.addElement("exception", att2);
+ }
+ }
+ sa.addEnd("exceptions");
+
+ return new SAXCodeAdapter(sa, access);
+ }
+
+ @Override
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
+ StringBuffer sb = new StringBuffer();
+ appendAccess(access | ACCESS_INNER, sb);
+
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "access", "access", "", sb.toString());
+ if (name != null) {
+ att.addAttribute("", "name", "name", "", name);
+ }
+ if (outerName != null) {
+ att.addAttribute("", "outerName", "outerName", "", outerName);
+ }
+ if (innerName != null) {
+ att.addAttribute("", "innerName", "innerName", "", innerName);
+ }
+ sa.addElement("innerclass", att);
+ }
+
+ @Override
+ public final void visitEnd() {
+ sa.addEnd("class");
+ if (!singleDocument) {
+ sa.addDocumentEnd();
+ }
+ }
+
+ static final String encode(final String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ sb.append("\\\\");
+ } else if (c < 0x20 || c > 0x7f) {
+ sb.append("\\u");
+ if (c < 0x10) {
+ sb.append("000");
+ } else if (c < 0x100) {
+ sb.append("00");
+ } else if (c < 0x1000) {
+ sb.append('0');
+ }
+ sb.append(Integer.toString(c, 16));
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static void appendAccess(final int access, final StringBuffer sb) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ sb.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ sb.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ sb.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ sb.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ sb.append("static ");
+ }
+ if ((access & Opcodes.ACC_SUPER) != 0) {
+ if ((access & ACCESS_CLASS) == 0) {
+ sb.append("synchronized ");
+ } else {
+ sb.append("super ");
+ }
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("bridge ");
+ } else {
+ sb.append("volatile ");
+ }
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ if ((access & ACCESS_FIELD) == 0) {
+ sb.append("varargs ");
+ } else {
+ sb.append("transient ");
+ }
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ sb.append("native ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ sb.append("strict ");
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ sb.append("interface ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ sb.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ sb.append("synthetic ");
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ sb.append("annotation ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ sb.append("enum ");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ sb.append("deprecated ");
+ }
+ if ((access & Opcodes.ACC_MANDATED) != 0) {
+ sb.append("mandated ");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
new file mode 100644
index 0000000..3ed0a49
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXCodeAdapter.java
@@ -0,0 +1,415 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.util.Printer;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ * A {@link MethodVisitor} that generates SAX 2.0 events from the visited
+ * method.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXCodeAdapter extends MethodVisitor {
+
+ static final String[] TYPES = { "top", "int", "float", "double", "long",
+ "null", "uninitializedThis" };
+
+ SAXAdapter sa;
+
+ int access;
+
+ private final Map<Label, String> labelNames;
+
+ /**
+ * Constructs a new {@link SAXCodeAdapter SAXCodeAdapter} object.
+ *
+ * @param sa
+ * content handler that will be used to send SAX 2.0 events.
+ */
+ public SAXCodeAdapter(final SAXAdapter sa, final int access) {
+ super(Opcodes.ASM5);
+ this.sa = sa;
+ this.access = access;
+ this.labelNames = new HashMap<Label, String>();
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ AttributesImpl attrs = new AttributesImpl();
+ if (name != null) {
+ attrs.addAttribute("", "name", "name", "", name);
+ }
+ StringBuffer sb = new StringBuffer();
+ SAXClassAdapter.appendAccess(access, sb);
+ attrs.addAttribute("", "access", "access", "", sb.toString());
+ sa.addElement("parameter", attrs);
+ }
+
+ @Override
+ public final void visitCode() {
+ if ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_NATIVE)) == 0) {
+ sa.addStart("code", new AttributesImpl());
+ }
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ AttributesImpl attrs = new AttributesImpl();
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ if (type == Opcodes.F_NEW) {
+ attrs.addAttribute("", "type", "type", "", "NEW");
+ } else {
+ attrs.addAttribute("", "type", "type", "", "FULL");
+ }
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ appendFrameTypes(false, nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ attrs.addAttribute("", "type", "type", "", "APPEND");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(true, nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ attrs.addAttribute("", "type", "type", "", "CHOP");
+ attrs.addAttribute("", "count", "count", "",
+ Integer.toString(nLocal));
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME:
+ attrs.addAttribute("", "type", "type", "", "SAME");
+ sa.addStart("frame", attrs);
+ break;
+ case Opcodes.F_SAME1:
+ attrs.addAttribute("", "type", "type", "", "SAME1");
+ sa.addStart("frame", attrs);
+ appendFrameTypes(false, 1, stack);
+ break;
+ }
+ sa.addEnd("frame");
+ }
+
+ private void appendFrameTypes(final boolean local, final int n,
+ final Object[] types) {
+ for (int i = 0; i < n; ++i) {
+ Object type = types[i];
+ AttributesImpl attrs = new AttributesImpl();
+ if (type instanceof String) {
+ attrs.addAttribute("", "type", "type", "", (String) type);
+ } else if (type instanceof Integer) {
+ attrs.addAttribute("", "type", "type", "",
+ TYPES[((Integer) type).intValue()]);
+ } else {
+ attrs.addAttribute("", "type", "type", "", "uninitialized");
+ attrs.addAttribute("", "label", "label", "",
+ getLabel((Label) type));
+ }
+ sa.addElement(local ? "local" : "stack", attrs);
+ }
+ }
+
+ @Override
+ public final void visitInsn(final int opcode) {
+ sa.addElement(Printer.OPCODES[opcode], new AttributesImpl());
+ }
+
+ @Override
+ public final void visitIntInsn(final int opcode, final int operand) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "value", "value", "", Integer.toString(operand));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitVarInsn(final int opcode, final int var) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitTypeInsn(final int opcode, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", type);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "owner", "owner", "", owner);
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "itf", "itf", "", itf ? "true" : "false");
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "bsm", "bsm", "",
+ SAXClassAdapter.encode(bsm.toString()));
+ sa.addStart("INVOKEDYNAMIC", attrs);
+ for (int i = 0; i < bsmArgs.length; i++) {
+ sa.addElement("bsmArg", getConstantAttribute(bsmArgs[i]));
+ }
+ sa.addEnd("INVOKEDYNAMIC");
+ }
+
+ @Override
+ public final void visitJumpInsn(final int opcode, final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "label", "label", "", getLabel(label));
+ sa.addElement(Printer.OPCODES[opcode], attrs);
+ }
+
+ @Override
+ public final void visitLabel(final Label label) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", getLabel(label));
+ sa.addElement("Label", attrs);
+ }
+
+ @Override
+ public final void visitLdcInsn(final Object cst) {
+ sa.addElement(Printer.OPCODES[Opcodes.LDC], getConstantAttribute(cst));
+ }
+
+ private static AttributesImpl getConstantAttribute(final Object cst) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "cst", "cst", "",
+ SAXClassAdapter.encode(cst.toString()));
+ attrs.addAttribute("", "desc", "desc", "",
+ Type.getDescriptor(cst.getClass()));
+ return attrs;
+ }
+
+ @Override
+ public final void visitIincInsn(final int var, final int increment) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "var", "var", "", Integer.toString(var));
+ attrs.addAttribute("", "inc", "inc", "", Integer.toString(increment));
+ sa.addElement(Printer.OPCODES[Opcodes.IINC], attrs);
+ }
+
+ @Override
+ public final void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "min", "min", "", Integer.toString(min));
+ attrs.addAttribute("", "max", "max", "", Integer.toString(max));
+ attrs.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.TABLESWITCH];
+ sa.addStart(o, attrs);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ AttributesImpl att = new AttributesImpl();
+ att.addAttribute("", "dflt", "dflt", "", getLabel(dflt));
+ String o = Printer.OPCODES[Opcodes.LOOKUPSWITCH];
+ sa.addStart(o, att);
+ for (int i = 0; i < labels.length; i++) {
+ AttributesImpl att2 = new AttributesImpl();
+ att2.addAttribute("", "name", "name", "", getLabel(labels[i]));
+ att2.addAttribute("", "key", "key", "", Integer.toString(keys[i]));
+ sa.addElement("label", att2);
+ }
+ sa.addEnd(o);
+ }
+
+ @Override
+ public final void visitMultiANewArrayInsn(final String desc, final int dims) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ attrs.addAttribute("", "dims", "dims", "", Integer.toString(dims));
+ sa.addElement(Printer.OPCODES[Opcodes.MULTIANEWARRAY], attrs);
+ }
+
+ @Override
+ public final void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "handler", "handler", "", getLabel(handler));
+ if (type != null) {
+ attrs.addAttribute("", "type", "type", "", type);
+ }
+ sa.addElement("TryCatch", attrs);
+ }
+
+ @Override
+ public final void visitMaxs(final int maxStack, final int maxLocals) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "maxStack", "maxStack", "",
+ Integer.toString(maxStack));
+ attrs.addAttribute("", "maxLocals", "maxLocals", "",
+ Integer.toString(maxLocals));
+ sa.addElement("Max", attrs);
+
+ sa.addEnd("code");
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "name", "name", "", name);
+ attrs.addAttribute("", "desc", "desc", "", desc);
+ if (signature != null) {
+ attrs.addAttribute("", "signature", "signature", "",
+ SAXClassAdapter.encode(signature));
+ }
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ attrs.addAttribute("", "end", "end", "", getLabel(end));
+ attrs.addAttribute("", "var", "var", "", Integer.toString(index));
+ sa.addElement("LocalVar", attrs);
+ }
+
+ @Override
+ public final void visitLineNumber(final int line, final Label start) {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute("", "line", "line", "", Integer.toString(line));
+ attrs.addAttribute("", "start", "start", "", getLabel(start));
+ sa.addElement("LineNumber", attrs);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new SAXAnnotationAdapter(sa, "annotationDefault", 0, null, null);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "parameterAnnotation", visible ? 1
+ : -1, parameter, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "insnAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "tryCatchAnnotation", visible ? 1
+ : -1, null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ String[] s = new String[start.length];
+ String[] e = new String[end.length];
+ for (int i = 0; i < s.length; ++i) {
+ s[i] = getLabel(start[i]);
+ }
+ for (int i = 0; i < e.length; ++i) {
+ e[i] = getLabel(end[i]);
+ }
+ return new SAXAnnotationAdapter(sa, "localVariableAnnotation",
+ visible ? 1 : -1, null, desc, typeRef, typePath, s, e, index);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("method");
+ }
+
+ private final String getLabel(final Label label) {
+ String name = labelNames.get(label);
+ if (name == null) {
+ name = Integer.toString(labelNames.size());
+ labelNames.put(label, name);
+ }
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
new file mode 100644
index 0000000..4fbc2a5
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/SAXFieldAdapter.java
@@ -0,0 +1,71 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+
+/**
+ * SAXFieldAdapter
+ *
+ * @author Eugene Kuleshov
+ */
+public final class SAXFieldAdapter extends FieldVisitor {
+
+ SAXAdapter sa;
+
+ public SAXFieldAdapter(final SAXAdapter sa, final Attributes att) {
+ super(Opcodes.ASM5);
+ this.sa = sa;
+ sa.addStart("field", att);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ return new SAXAnnotationAdapter(sa, "annotation", visible ? 1 : -1,
+ null, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ return new SAXAnnotationAdapter(sa, "typeAnnotation", visible ? 1 : -1,
+ null, desc, typeRef, typePath);
+ }
+
+ @Override
+ public void visitEnd() {
+ sa.addEnd("field");
+ }
+}
[17/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
index ac7c671..d899c5e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Opcodes.java
@@ -37,7 +37,7 @@ package org.apache.tapestry5.internal.plastic.asm;
* opcodes are therefore not defined in this interface. Likewise for LDC,
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
* JSR_W.
- *
+ *
* @author Eric Bruneton
* @author Eugene Kuleshov
*/
@@ -46,6 +46,7 @@ public interface Opcodes {
// ASM API versions
int ASM4 = 4 << 16 | 0 << 8 | 0;
+ int ASM5 = 5 << 16 | 0 << 8 | 0;
// versions
@@ -56,6 +57,7 @@ public interface Opcodes {
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
+ int V1_8 = 0 << 16 | 52;
// access flags
@@ -63,7 +65,7 @@ public interface Opcodes {
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
- int ACC_FINAL = 0x0010; // class, field, method
+ int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_VOLATILE = 0x0040; // field
@@ -74,9 +76,10 @@ public interface Opcodes {
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
- int ACC_SYNTHETIC = 0x1000; // class, field, method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
+ int ACC_MANDATED = 0x8000; // parameter
// ASM specific pseudo access flags
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
index 6011aa4..0b526a0 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/Type.java
@@ -35,7 +35,7 @@ import java.lang.reflect.Method;
/**
* A Java field or method type. This class can be used to make it easier to
* manipulate type and method descriptors.
- *
+ *
* @author Eric Bruneton
* @author Chris Nokleberg
*/
@@ -189,14 +189,17 @@ public class Type {
/**
* Constructs a reference type.
- *
- * @param sort the sort of the reference type to be constructed.
- * @param buf a buffer containing the descriptor of the previous type.
- * @param off the offset of this descriptor in the previous buffer.
- * @param len the length of this descriptor.
- */
- private Type(final int sort, final char[] buf, final int off, final int len)
- {
+ *
+ * @param sort
+ * the sort of the reference type to be constructed.
+ * @param buf
+ * a buffer containing the descriptor of the previous type.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
+ * @param len
+ * the length of this descriptor.
+ */
+ private Type(final int sort, final char[] buf, final int off, final int len) {
this.sort = sort;
this.buf = buf;
this.off = off;
@@ -205,8 +208,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given type descriptor.
- *
- * @param typeDescriptor a field or method type descriptor.
+ *
+ * @param typeDescriptor
+ * a field or method type descriptor.
* @return the Java type corresponding to the given type descriptor.
*/
public static Type getType(final String typeDescriptor) {
@@ -215,8 +219,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given internal name.
- *
- * @param internalName an internal name.
+ *
+ * @param internalName
+ * an internal name.
* @return the Java type corresponding to the given internal name.
*/
public static Type getObjectType(final String internalName) {
@@ -227,8 +232,9 @@ public class Type {
/**
* Returns the Java type corresponding to the given method descriptor.
* Equivalent to <code>Type.getType(methodDescriptor)</code>.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java type corresponding to the given method descriptor.
*/
public static Type getMethodType(final String methodDescriptor) {
@@ -238,19 +244,24 @@ public class Type {
/**
* Returns the Java method type corresponding to the given argument and
* return types.
- *
- * @param returnType the return type of the method.
- * @param argumentTypes the argument types of the method.
- * @return the Java type corresponding to the given argument and return types.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
+ * @return the Java type corresponding to the given argument and return
+ * types.
*/
- public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
+ public static Type getMethodType(final Type returnType,
+ final Type... argumentTypes) {
return getType(getMethodDescriptor(returnType, argumentTypes));
}
/**
* Returns the Java type corresponding to the given class.
- *
- * @param c a class.
+ *
+ * @param c
+ * a class.
* @return the Java type corresponding to the given class.
*/
public static Type getType(final Class<?> c) {
@@ -281,8 +292,9 @@ public class Type {
/**
* Returns the Java method type corresponding to the given constructor.
- *
- * @param c a {@link Constructor Constructor} object.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
* @return the Java method type corresponding to the given constructor.
*/
public static Type getType(final Constructor<?> c) {
@@ -291,8 +303,9 @@ public class Type {
/**
* Returns the Java method type corresponding to the given method.
- *
- * @param m a {@link Method Method} object.
+ *
+ * @param m
+ * a {@link Method Method} object.
* @return the Java method type corresponding to the given method.
*/
public static Type getType(final Method m) {
@@ -302,8 +315,9 @@ public class Type {
/**
* Returns the Java types corresponding to the argument types of the given
* method descriptor.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java types corresponding to the argument types of the given
* method descriptor.
*/
@@ -337,8 +351,9 @@ public class Type {
/**
* Returns the Java types corresponding to the argument types of the given
* method.
- *
- * @param method a method.
+ *
+ * @param method
+ * a method.
* @return the Java types corresponding to the argument types of the given
* method.
*/
@@ -354,8 +369,9 @@ public class Type {
/**
* Returns the Java type corresponding to the return type of the given
* method descriptor.
- *
- * @param methodDescriptor a method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
* @return the Java type corresponding to the return type of the given
* method descriptor.
*/
@@ -367,8 +383,9 @@ public class Type {
/**
* Returns the Java type corresponding to the return type of the given
* method.
- *
- * @param method a method.
+ *
+ * @param method
+ * a method.
* @return the Java type corresponding to the return type of the given
* method.
*/
@@ -378,13 +395,14 @@ public class Type {
/**
* Computes the size of the arguments and of the return value of a method.
- *
- * @param desc the descriptor of a method.
+ *
+ * @param desc
+ * the descriptor of a method.
* @return the size of the arguments of the method (plus one for the
* implicit this argument), argSize, and the size of its return
* value, retSize, packed into a single int i =
- * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
- * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+ * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
+ * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
*/
public static int getArgumentsAndReturnSizes(final String desc) {
int n = 1;
@@ -418,53 +436,55 @@ public class Type {
* Returns the Java type corresponding to the given type descriptor. For
* method descriptors, buf is supposed to contain nothing more than the
* descriptor itself.
- *
- * @param buf a buffer containing a type descriptor.
- * @param off the offset of this descriptor in the previous buffer.
+ *
+ * @param buf
+ * a buffer containing a type descriptor.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
* @return the Java type corresponding to the given type descriptor.
*/
private static Type getType(final char[] buf, final int off) {
int len;
switch (buf[off]) {
- case 'V':
- return VOID_TYPE;
- case 'Z':
- return BOOLEAN_TYPE;
- case 'C':
- return CHAR_TYPE;
- case 'B':
- return BYTE_TYPE;
- case 'S':
- return SHORT_TYPE;
- case 'I':
- return INT_TYPE;
- case 'F':
- return FLOAT_TYPE;
- case 'J':
- return LONG_TYPE;
- case 'D':
- return DOUBLE_TYPE;
- case '[':
- len = 1;
- while (buf[off + len] == '[') {
- ++len;
- }
- if (buf[off + len] == 'L') {
- ++len;
- while (buf[off + len] != ';') {
- ++len;
- }
- }
- return new Type(ARRAY, buf, off, len + 1);
- case 'L':
- len = 1;
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ len = 1;
+ while (buf[off + len] == '[') {
+ ++len;
+ }
+ if (buf[off + len] == 'L') {
+ ++len;
while (buf[off + len] != ';') {
++len;
}
- return new Type(OBJECT, buf, off + 1, len - 1);
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ case 'L':
+ len = 1;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off + 1, len - 1);
// case '(':
- default:
- return new Type(METHOD, buf, 0, buf.length);
+ default:
+ return new Type(METHOD, buf, off, buf.length - off);
}
}
@@ -474,12 +494,12 @@ public class Type {
/**
* Returns the sort of this Java type.
- *
- * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
- * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
- * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
- * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY},
- * {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
+ * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
+ * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
+ * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
+ * METHOD}.
*/
public int getSort() {
return sort;
@@ -488,7 +508,7 @@ public class Type {
/**
* Returns the number of dimensions of this array type. This method should
* only be used for an array type.
- *
+ *
* @return the number of dimensions of this array type.
*/
public int getDimensions() {
@@ -502,7 +522,7 @@ public class Type {
/**
* Returns the type of the elements of this array type. This method should
* only be used for an array type.
- *
+ *
* @return Returns the type of the elements of this array type.
*/
public Type getElementType() {
@@ -512,39 +532,39 @@ public class Type {
/**
* Returns the binary name of the class corresponding to this type. This
* method must not be used on method types.
- *
+ *
* @return the binary name of the class corresponding to this type.
*/
public String getClassName() {
switch (sort) {
- case VOID:
- return "void";
- case BOOLEAN:
- return "boolean";
- case CHAR:
- return "char";
- case BYTE:
- return "byte";
- case SHORT:
- return "short";
- case INT:
- return "int";
- case FLOAT:
- return "float";
- case LONG:
- return "long";
- case DOUBLE:
- return "double";
- case ARRAY:
- StringBuffer b = new StringBuffer(getElementType().getClassName());
- for (int i = getDimensions(); i > 0; --i) {
- b.append("[]");
- }
- return b.toString();
- case OBJECT:
- return new String(buf, off, len).replace('/', '.');
- default:
- return null;
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ b.append("[]");
+ }
+ return b.toString();
+ case OBJECT:
+ return new String(buf, off, len).replace('/', '.');
+ default:
+ return null;
}
}
@@ -553,7 +573,7 @@ public class Type {
* array type. The internal name of a class is its fully qualified name (as
* returned by Class.getName(), where '.' are replaced by '/'. This method
* should only be used for an object or array type.
- *
+ *
* @return the internal name of the class corresponding to this object type.
*/
public String getInternalName() {
@@ -563,7 +583,7 @@ public class Type {
/**
* Returns the argument types of methods of this type. This method should
* only be used for method types.
- *
+ *
* @return the argument types of methods of this type.
*/
public Type[] getArgumentTypes() {
@@ -573,7 +593,7 @@ public class Type {
/**
* Returns the return type of methods of this type. This method should only
* be used for method types.
- *
+ *
* @return the return type of methods of this type.
*/
public Type getReturnType() {
@@ -583,12 +603,13 @@ public class Type {
/**
* Returns the size of the arguments and of the return value of methods of
* this type. This method should only be used for method types.
- *
+ *
* @return the size of the arguments (plus one for the implicit this
* argument), argSize, and the size of the return value, retSize,
- * packed into a single int i = <tt>(argSize << 2) | retSize</tt>
- * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
- * <tt>i & 0x03</tt>).
+ * packed into a single
+ * int i = <tt>(argSize << 2) | retSize</tt>
+ * (argSize is therefore equal to <tt>i >> 2</tt>,
+ * and retSize to <tt>i & 0x03</tt>).
*/
public int getArgumentsAndReturnSizes() {
return getArgumentsAndReturnSizes(getDescriptor());
@@ -600,7 +621,7 @@ public class Type {
/**
* Returns the descriptor corresponding to this Java type.
- *
+ *
* @return the descriptor corresponding to this Java type.
*/
public String getDescriptor() {
@@ -612,16 +633,16 @@ public class Type {
/**
* Returns the descriptor corresponding to the given argument and return
* types.
- *
- * @param returnType the return type of the method.
- * @param argumentTypes the argument types of the method.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
* @return the descriptor corresponding to the given argument and return
* types.
*/
- public static String getMethodDescriptor(
- final Type returnType,
- final Type... argumentTypes)
- {
+ public static String getMethodDescriptor(final Type returnType,
+ final Type... argumentTypes) {
StringBuffer buf = new StringBuffer();
buf.append('(');
for (int i = 0; i < argumentTypes.length; ++i) {
@@ -635,12 +656,14 @@ public class Type {
/**
* Appends the descriptor corresponding to this Java type to the given
* string buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
*/
private void getDescriptor(final StringBuffer buf) {
if (this.buf == null) {
- // descriptor is in byte 3 of 'off' for primitive types (buf == null)
+ // descriptor is in byte 3 of 'off' for primitive types (buf ==
+ // null)
buf.append((char) ((off & 0xFF000000) >>> 24));
} else if (sort == OBJECT) {
buf.append('L');
@@ -660,8 +683,9 @@ public class Type {
* Returns the internal name of the given class. The internal name of a
* class is its fully qualified name, as returned by Class.getName(), where
* '.' are replaced by '/'.
- *
- * @param c an object or array class.
+ *
+ * @param c
+ * an object or array class.
* @return the internal name of the given class.
*/
public static String getInternalName(final Class<?> c) {
@@ -670,8 +694,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given Java type.
- *
- * @param c an object class, a primitive class or an array class.
+ *
+ * @param c
+ * an object class, a primitive class or an array class.
* @return the descriptor corresponding to the given class.
*/
public static String getDescriptor(final Class<?> c) {
@@ -682,8 +707,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given constructor.
- *
- * @param c a {@link Constructor Constructor} object.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
* @return the descriptor of the given constructor.
*/
public static String getConstructorDescriptor(final Constructor<?> c) {
@@ -698,8 +724,9 @@ public class Type {
/**
* Returns the descriptor corresponding to the given method.
- *
- * @param m a {@link Method Method} object.
+ *
+ * @param m
+ * a {@link Method Method} object.
* @return the descriptor of the given method.
*/
public static String getMethodDescriptor(final Method m) {
@@ -716,9 +743,11 @@ public class Type {
/**
* Appends the descriptor of the given class to the given string buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
- * @param c the class whose descriptor must be computed.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
+ * @param c
+ * the class whose descriptor must be computed.
*/
private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
Class<?> d = c;
@@ -770,7 +799,7 @@ public class Type {
/**
* Returns the size of values of this type. This method must not be used for
* method types.
- *
+ *
* @return the size of values of this type, i.e., 2 for <tt>long</tt> and
* <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
*/
@@ -782,10 +811,11 @@ public class Type {
/**
* Returns a JVM instruction opcode adapted to this Java type. This method
* must not be used for method types.
- *
- * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
- * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
- * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ *
+ * @param opcode
+ * a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
+ * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
* @return an opcode that is similar to the given opcode, but adapted to
* this Java type. For example, if this type is <tt>float</tt> and
* <tt>opcode</tt> is IRETURN, this method returns FRETURN.
@@ -808,8 +838,9 @@ public class Type {
/**
* Tests if the given object is equal to this type.
- *
- * @param o the object to be compared to this type.
+ *
+ * @param o
+ * the object to be compared to this type.
* @return <tt>true</tt> if the given object is equal to this type.
*/
@Override
@@ -839,7 +870,7 @@ public class Type {
/**
* Returns a hash code value for this type.
- *
+ *
* @return a hash code value for this type.
*/
@Override
@@ -855,7 +886,7 @@ public class Type {
/**
* Returns a string representation of this type.
- *
+ *
* @return the descriptor of this type.
*/
@Override
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
new file mode 100644
index 0000000..b772d59
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypePath.java
@@ -0,0 +1,193 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static
+ * inner type within an enclosing type.
+ *
+ * @author Eric Bruneton
+ */
+public class TypePath {
+
+ /**
+ * A type path step that steps into the element type of an array type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int ARRAY_ELEMENT = 0;
+
+ /**
+ * A type path step that steps into the nested type of a class type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int INNER_TYPE = 1;
+
+ /**
+ * A type path step that steps into the bound of a wildcard type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int WILDCARD_BOUND = 2;
+
+ /**
+ * A type path step that steps into a type argument of a generic type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int TYPE_ARGUMENT = 3;
+
+ /**
+ * The byte array where the path is stored, in Java class file format.
+ */
+ byte[] b;
+
+ /**
+ * The offset of the first byte of the type path in 'b'.
+ */
+ int offset;
+
+ /**
+ * Creates a new type path.
+ *
+ * @param b
+ * the byte array containing the type path in Java class file
+ * format.
+ * @param offset
+ * the offset of the first byte of the type path in 'b'.
+ */
+ TypePath(byte[] b, int offset) {
+ this.b = b;
+ this.offset = offset;
+ }
+
+ /**
+ * Returns the length of this path.
+ *
+ * @return the length of this path.
+ */
+ public int getLength() {
+ return b[offset];
+ }
+
+ /**
+ * Returns the value of the given step of this path.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
+ * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ */
+ public int getStep(int index) {
+ return b[offset + 2 * index + 1];
+ }
+
+ /**
+ * Returns the index of the type argument that the given step is stepping
+ * into. This method should only be used for steps whose value is
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return the index of the type argument that the given step is stepping
+ * into.
+ */
+ public int getStepArgument(int index) {
+ return b[offset + 2 * index + 2];
+ }
+
+ /**
+ * Converts a type path in string form, in the format used by
+ * {@link #toString()}, into a TypePath object.
+ *
+ * @param typePath
+ * a type path in string form, in the format used by
+ * {@link #toString()}. May be null or empty.
+ * @return the corresponding TypePath object, or null if the path is empty.
+ */
+ public static TypePath fromString(final String typePath) {
+ if (typePath == null || typePath.length() == 0) {
+ return null;
+ }
+ int n = typePath.length();
+ ByteVector out = new ByteVector(n);
+ out.putByte(0);
+ for (int i = 0; i < n;) {
+ char c = typePath.charAt(i++);
+ if (c == '[') {
+ out.put11(ARRAY_ELEMENT, 0);
+ } else if (c == '.') {
+ out.put11(INNER_TYPE, 0);
+ } else if (c == '*') {
+ out.put11(WILDCARD_BOUND, 0);
+ } else if (c >= '0' && c <= '9') {
+ int typeArg = c - '0';
+ while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
+ typeArg = typeArg * 10 + c - '0';
+ i += 1;
+ }
+ out.put11(TYPE_ARGUMENT, typeArg);
+ }
+ }
+ out.data[0] = (byte) (out.length / 2);
+ return new TypePath(out.data, 0);
+ }
+
+ /**
+ * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
+ * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
+ * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
+ * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
+ * argument index in decimal form.
+ */
+ @Override
+ public String toString() {
+ int length = getLength();
+ StringBuilder result = new StringBuilder(length * 2);
+ for (int i = 0; i < length; ++i) {
+ switch (getStep(i)) {
+ case ARRAY_ELEMENT:
+ result.append('[');
+ break;
+ case INNER_TYPE:
+ result.append('.');
+ break;
+ case WILDCARD_BOUND:
+ result.append('*');
+ break;
+ case TYPE_ARGUMENT:
+ result.append(getStepArgument(i));
+ break;
+ default:
+ result.append('_');
+ }
+ }
+ return result.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
new file mode 100644
index 0000000..d518864
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/TypeReference.java
@@ -0,0 +1,452 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2013 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;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or
+ * on an instruction. Such a reference designates the part of the class where
+ * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
+ * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
+ * declaration, etc).
+ *
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER = 0x00;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER = 0x01;
+
+ /**
+ * The sort of type references that target the super class of a class or one
+ * of the interfaces it implements. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_EXTENDS = 0x10;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+ /**
+ * The sort of type references that target the type of a field. See
+ * {@link #getSort getSort}.
+ */
+ public final static int FIELD = 0x13;
+
+ /**
+ * The sort of type references that target the return type of a method. See
+ * {@link #getSort getSort}.
+ */
+ public final static int METHOD_RETURN = 0x14;
+
+ /**
+ * The sort of type references that target the receiver type of a method.
+ * See {@link #getSort getSort}.
+ */
+ public final static int METHOD_RECEIVER = 0x15;
+
+ /**
+ * The sort of type references that target the type of a formal parameter of
+ * a method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_FORMAL_PARAMETER = 0x16;
+
+ /**
+ * The sort of type references that target the type of an exception declared
+ * in the throws clause of a method. See {@link #getSort getSort}.
+ */
+ public final static int THROWS = 0x17;
+
+ /**
+ * The sort of type references that target the type of a local variable in a
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int LOCAL_VARIABLE = 0x40;
+
+ /**
+ * The sort of type references that target the type of a resource variable
+ * in a method. See {@link #getSort getSort}.
+ */
+ public final static int RESOURCE_VARIABLE = 0x41;
+
+ /**
+ * The sort of type references that target the type of the exception of a
+ * 'catch' clause in a method. See {@link #getSort getSort}.
+ */
+ public final static int EXCEPTION_PARAMETER = 0x42;
+
+ /**
+ * The sort of type references that target the type declared in an
+ * 'instanceof' instruction. See {@link #getSort getSort}.
+ */
+ public final static int INSTANCEOF = 0x43;
+
+ /**
+ * The sort of type references that target the type of the object created by
+ * a 'new' instruction. See {@link #getSort getSort}.
+ */
+ public final static int NEW = 0x44;
+
+ /**
+ * The sort of type references that target the receiver type of a
+ * constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE = 0x45;
+
+ /**
+ * The sort of type references that target the receiver type of a method
+ * reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE = 0x46;
+
+ /**
+ * The sort of type references that target the type declared in an explicit
+ * or implicit cast instruction. See {@link #getSort getSort}.
+ */
+ public final static int CAST = 0x47;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor call. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method call. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+ /**
+ * The type reference value in Java class file format.
+ */
+ private int value;
+
+ /**
+ * Creates a new TypeReference.
+ *
+ * @param typeRef
+ * the int encoded value of the type reference, as received in a
+ * visit method related to type annotations, like
+ * visitTypeAnnotation.
+ */
+ public TypeReference(int typeRef) {
+ this.value = typeRef;
+ }
+
+ /**
+ * Returns a type reference of the given sort.
+ *
+ * @param sort
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}.
+ * @return a type reference of the given sort.
+ */
+ public static TypeReference newTypeReference(int sort) {
+ return new TypeReference(sort << 24);
+ }
+
+ /**
+ * Returns a reference to a type parameter of a generic class or method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @return a reference to the given generic class or method type parameter.
+ */
+ public static TypeReference newTypeParameterReference(int sort,
+ int paramIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to a type parameter bound of a generic class or
+ * method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @param boundIndex
+ * the type bound index within the above type parameters.
+ * @return a reference to the given generic class or method type parameter
+ * bound.
+ */
+ public static TypeReference newTypeParameterBoundReference(int sort,
+ int paramIndex, int boundIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16)
+ | (boundIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the super class or to an interface of the
+ * 'implements' clause of a class.
+ *
+ * @param itfIndex
+ * the index of an interface in the 'implements' clause of a
+ * class, or -1 to reference the super class of the class.
+ * @return a reference to the given super type of a class.
+ */
+ public static TypeReference newSuperTypeReference(int itfIndex) {
+ itfIndex &= 0xFFFF;
+ return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a formal parameter of a method.
+ *
+ * @param paramIndex
+ * the formal parameter index.
+ *
+ * @return a reference to the type of the given method formal parameter.
+ */
+ public static TypeReference newFormalParameterReference(int paramIndex) {
+ return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
+ | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to the type of an exception, in a 'throws' clause of
+ * a method.
+ *
+ * @param exceptionIndex
+ * the index of an exception in a 'throws' clause of a method.
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newExceptionReference(int exceptionIndex) {
+ return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of the exception declared in a 'catch'
+ * clause of a method.
+ *
+ * @param tryCatchBlockIndex
+ * the index of a try catch block (using the order in which they
+ * are visited with visitTryCatchBlock).
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
+ return new TypeReference((EXCEPTION_PARAMETER << 24)
+ | (tryCatchBlockIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a type argument in a constructor or
+ * method call or reference.
+ *
+ * @param sort
+ * {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ * @param argIndex
+ * the type argument index.
+ *
+ * @return a reference to the type of the given type argument.
+ */
+ public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
+ return new TypeReference((sort << 24) | argIndex);
+ }
+
+ /**
+ * Returns the sort of this type reference.
+ *
+ * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_EXTENDS CLASS_EXTENDS},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
+ * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ */
+ public int getSort() {
+ return value >>> 24;
+ }
+
+ /**
+ * Returns the index of the type parameter referenced by this type
+ * reference. This method must only be used for type references whose sort
+ * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the type parameter bound, within the type parameter
+ * {@link #getTypeParameterIndex}, referenced by this type reference. This
+ * method must only be used for type references whose sort is
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter bound index.
+ */
+ public int getTypeParameterBoundIndex() {
+ return (value & 0x0000FF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the "super type" of a class that is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
+ *
+ * @return the index of an interface in the 'implements' clause of a class,
+ * or -1 if this type reference references the type of the super
+ * class.
+ */
+ public int getSuperTypeIndex() {
+ return (short) ((value & 0x00FFFF00) >> 8);
+ }
+
+ /**
+ * Returns the index of the formal parameter whose type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
+ *
+ * @return a formal parameter index.
+ */
+ public int getFormalParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the exception, in a 'throws' clause of a method,
+ * whose type is referenced by this type reference. This method must only be
+ * used for type references whose sort is {@link #THROWS THROWS}.
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getExceptionIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the try catch block (using the order in which they
+ * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getTryCatchBlockIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the type argument referenced by this type reference.
+ * This method must only be used for type references whose sort is
+ * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeArgumentIndex() {
+ return value & 0xFF;
+ }
+
+ /**
+ * Returns the int encoded value of this type reference, suitable for use in
+ * visit methods related to type annotations, like visitTypeAnnotation.
+ *
+ * @return the int encoded value of this type reference.
+ */
+ public int getValue() {
+ return value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
new file mode 100644
index 0000000..a53995b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/AdviceAdapter.java
@@ -0,0 +1,646 @@
+/***
+ * 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.commons;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} to insert before, after and around
+ * advices in methods and constructors.
+ * <p>
+ * The behavior for constructors is like this:
+ * <ol>
+ *
+ * <li>as long as the INVOKESPECIAL for the object initialization has not been
+ * reached, every bytecode instruction is dispatched in the ctor code visitor</li>
+ *
+ * <li>when this one is reached, it is only added in the ctor code visitor and a
+ * JP invoke is added</li>
+ *
+ * <li>after that, only the other code visitor receives the instructions</li>
+ *
+ * </ol>
+ *
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes {
+
+ private static final Object THIS = new Object();
+
+ private static final Object OTHER = new Object();
+
+ protected int methodAccess;
+
+ protected String methodDesc;
+
+ private boolean constructor;
+
+ private boolean superInitialized;
+
+ private List<Object> stackFrame;
+
+ private Map<Label, List<Object>> branches;
+
+ /**
+ * Creates a new {@link AdviceAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ protected AdviceAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc) {
+ super(api, mv, access, name, desc);
+ methodAccess = access;
+ methodDesc = desc;
+ constructor = "<init>".equals(name);
+ }
+
+ @Override
+ public void visitCode() {
+ mv.visitCode();
+ if (constructor) {
+ stackFrame = new ArrayList<Object>();
+ branches = new HashMap<Label, List<Object>>();
+ } else {
+ superInitialized = true;
+ onMethodEnter();
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ mv.visitLabel(label);
+ if (constructor && branches != null) {
+ List<Object> frame = branches.get(label);
+ if (frame != null) {
+ stackFrame = frame;
+ branches.remove(label);
+ }
+ }
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ if (constructor) {
+ int s;
+ switch (opcode) {
+ case RETURN: // empty stack
+ onMethodExit(opcode);
+ break;
+ case IRETURN: // 1 before n/a after
+ case FRETURN: // 1 before n/a after
+ case ARETURN: // 1 before n/a after
+ case ATHROW: // 1 before n/a after
+ popValue();
+ onMethodExit(opcode);
+ break;
+ case LRETURN: // 2 before n/a after
+ case DRETURN: // 2 before n/a after
+ popValue();
+ popValue();
+ onMethodExit(opcode);
+ break;
+ case NOP:
+ case LALOAD: // remove 2 add 2
+ case DALOAD: // remove 2 add 2
+ case LNEG:
+ case DNEG:
+ case FNEG:
+ case INEG:
+ case L2D:
+ case D2L:
+ case F2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ case I2F:
+ case ARRAYLENGTH:
+ break;
+ case ACONST_NULL:
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ case F2L: // 1 before 2 after
+ case F2D:
+ case I2L:
+ case I2D:
+ pushValue(OTHER);
+ break;
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case IALOAD: // remove 2 add 1
+ case FALOAD: // remove 2 add 1
+ case AALOAD: // remove 2 add 1
+ case BALOAD: // remove 2 add 1
+ case CALOAD: // remove 2 add 1
+ case SALOAD: // remove 2 add 1
+ case POP:
+ case IADD:
+ case FADD:
+ case ISUB:
+ case LSHL: // 3 before 2 after
+ case LSHR: // 3 before 2 after
+ case LUSHR: // 3 before 2 after
+ case L2I: // 2 before 1 after
+ case L2F: // 2 before 1 after
+ case D2I: // 2 before 1 after
+ case D2F: // 2 before 1 after
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL: // 2 before 1 after
+ case FCMPG: // 2 before 1 after
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case MONITORENTER:
+ case MONITOREXIT:
+ popValue();
+ break;
+ case POP2:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LADD:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case DADD:
+ case DMUL:
+ case DSUB:
+ case DDIV:
+ case DREM:
+ popValue();
+ popValue();
+ break;
+ case IASTORE:
+ case FASTORE:
+ case AASTORE:
+ case BASTORE:
+ case CASTORE:
+ case SASTORE:
+ case LCMP: // 4 before 1 after
+ case DCMPL:
+ case DCMPG:
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case LASTORE:
+ case DASTORE:
+ popValue();
+ popValue();
+ popValue();
+ popValue();
+ break;
+ case DUP:
+ pushValue(peekValue());
+ break;
+ case DUP_X1:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ break;
+ case DUP_X2:
+ s = stackFrame.size();
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ break;
+ case DUP2:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ break;
+ case DUP2_X1:
+ s = stackFrame.size();
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ stackFrame.add(s - 3, stackFrame.get(s - 1));
+ break;
+ case DUP2_X2:
+ s = stackFrame.size();
+ stackFrame.add(s - 4, stackFrame.get(s - 1));
+ stackFrame.add(s - 4, stackFrame.get(s - 1));
+ break;
+ case SWAP:
+ s = stackFrame.size();
+ stackFrame.add(s - 2, stackFrame.get(s - 1));
+ stackFrame.remove(s);
+ break;
+ }
+ } else {
+ switch (opcode) {
+ case RETURN:
+ case IRETURN:
+ case FRETURN:
+ case ARETURN:
+ case LRETURN:
+ case DRETURN:
+ case ATHROW:
+ onMethodExit(opcode);
+ break;
+ }
+ }
+ mv.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ super.visitVarInsn(opcode, var);
+ if (constructor) {
+ switch (opcode) {
+ case ILOAD:
+ case FLOAD:
+ pushValue(OTHER);
+ break;
+ case LLOAD:
+ case DLOAD:
+ pushValue(OTHER);
+ pushValue(OTHER);
+ break;
+ case ALOAD:
+ pushValue(var == 0 ? THIS : OTHER);
+ break;
+ case ASTORE:
+ case ISTORE:
+ case FSTORE:
+ popValue();
+ break;
+ case LSTORE:
+ case DSTORE:
+ popValue();
+ popValue();
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ if (constructor) {
+ char c = desc.charAt(0);
+ boolean longOrDouble = c == 'J' || c == 'D';
+ switch (opcode) {
+ case GETSTATIC:
+ pushValue(OTHER);
+ if (longOrDouble) {
+ pushValue(OTHER);
+ }
+ break;
+ case PUTSTATIC:
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ }
+ break;
+ case PUTFIELD:
+ popValue();
+ if (longOrDouble) {
+ popValue();
+ popValue();
+ }
+ break;
+ // case GETFIELD:
+ default:
+ if (longOrDouble) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ mv.visitIntInsn(opcode, operand);
+ if (constructor && opcode != NEWARRAY) {
+ pushValue(OTHER);
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ mv.visitLdcInsn(cst);
+ if (constructor) {
+ pushValue(OTHER);
+ if (cst instanceof Double || cst instanceof Long) {
+ pushValue(OTHER);
+ }
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ if (constructor) {
+ for (int i = 0; i < dims; i++) {
+ popValue();
+ }
+ pushValue(OTHER);
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ mv.visitTypeInsn(opcode, type);
+ // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack
+ if (constructor && opcode == NEW) {
+ pushValue(OTHER);
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (constructor) {
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; i++) {
+ popValue();
+ if (types[i].getSize() == 2) {
+ popValue();
+ }
+ }
+ switch (opcode) {
+ // case INVOKESTATIC:
+ // break;
+ case INVOKEINTERFACE:
+ case INVOKEVIRTUAL:
+ popValue(); // objectref
+ break;
+ case INVOKESPECIAL:
+ Object type = popValue(); // objectref
+ if (type == THIS && !superInitialized) {
+ onMethodEnter();
+ superInitialized = true;
+ // once super has been initialized it is no longer
+ // necessary to keep track of stack state
+ constructor = false;
+ }
+ break;
+ }
+
+ Type returnType = Type.getReturnType(desc);
+ if (returnType != Type.VOID_TYPE) {
+ pushValue(OTHER);
+ if (returnType.getSize() == 2) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ if (constructor) {
+ Type[] types = Type.getArgumentTypes(desc);
+ for (int i = 0; i < types.length; i++) {
+ popValue();
+ if (types[i].getSize() == 2) {
+ popValue();
+ }
+ }
+
+ Type returnType = Type.getReturnType(desc);
+ if (returnType != Type.VOID_TYPE) {
+ pushValue(OTHER);
+ if (returnType.getSize() == 2) {
+ pushValue(OTHER);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ mv.visitJumpInsn(opcode, label);
+ if (constructor) {
+ switch (opcode) {
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case IFNULL:
+ case IFNONNULL:
+ popValue();
+ break;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ popValue();
+ popValue();
+ break;
+ case JSR:
+ pushValue(OTHER);
+ break;
+ }
+ addBranch(label);
+ }
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ if (constructor) {
+ popValue();
+ addBranches(dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ if (constructor) {
+ popValue();
+ addBranches(dflt, labels);
+ }
+ }
+
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
+ super.visitTryCatchBlock(start, end, handler, type);
+ if (constructor && !branches.containsKey(handler)) {
+ List<Object> stackFrame = new ArrayList<Object>();
+ stackFrame.add(OTHER);
+ branches.put(handler, stackFrame);
+ }
+ }
+
+ private void addBranches(final Label dflt, final Label[] labels) {
+ addBranch(dflt);
+ for (int i = 0; i < labels.length; i++) {
+ addBranch(labels[i]);
+ }
+ }
+
+ private void addBranch(final Label label) {
+ if (branches.containsKey(label)) {
+ return;
+ }
+ branches.put(label, new ArrayList<Object>(stackFrame));
+ }
+
+ private Object popValue() {
+ return stackFrame.remove(stackFrame.size() - 1);
+ }
+
+ private Object peekValue() {
+ return stackFrame.get(stackFrame.size() - 1);
+ }
+
+ private void pushValue(final Object o) {
+ stackFrame.add(o);
+ }
+
+ /**
+ * Called at the beginning of the method or after super class class call in
+ * the constructor. <br>
+ * <br>
+ *
+ * <i>Custom code can use or change all the local variables, but should not
+ * change state of the stack.</i>
+ */
+ protected void onMethodEnter() {
+ }
+
+ /**
+ * Called before explicit exit from the method using either return or throw.
+ * Top element on the stack contains the return value or exception instance.
+ * For example:
+ *
+ * <pre>
+ * public void onMethodExit(int opcode) {
+ * if(opcode==RETURN) {
+ * visitInsn(ACONST_NULL);
+ * } else if(opcode==ARETURN || opcode==ATHROW) {
+ * dup();
+ * } else {
+ * if(opcode==LRETURN || opcode==DRETURN) {
+ * dup2();
+ * } else {
+ * dup();
+ * }
+ * box(Type.getReturnType(this.methodDesc));
+ * }
+ * visitIntInsn(SIPUSH, opcode);
+ * visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+ * }
+ *
+ * // an actual call back method
+ * public static void onExit(Object param, int opcode) {
+ * ...
+ * </pre>
+ *
+ * <br>
+ * <br>
+ *
+ * <i>Custom code can use or change all the local variables, but should not
+ * change state of the stack.</i>
+ *
+ * @param opcode
+ * one of the RETURN, IRETURN, FRETURN, ARETURN, LRETURN, DRETURN
+ * or ATHROW
+ *
+ */
+ protected void onMethodExit(int opcode) {
+ }
+
+ // TODO onException, onMethodCall
+}
[19/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
index f0676b7..4585e67 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/MethodVisitor.java
@@ -30,27 +30,33 @@
package org.apache.tapestry5.internal.plastic.asm;
/**
- * A visitor to visit a Java method. The methods of this class must be
- * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
- * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
- * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
- * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
- * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ]
- * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
- * and <tt>visitLabel</tt> methods must be called in the sequential order of
- * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
- * must be called <i>before</i> the labels passed as arguments have been
- * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
- * methods must be called <i>after</i> the labels passed as arguments have been
- * visited.
- *
+ * A visitor to visit a Java method. The methods of this class must be called in
+ * the following order: ( <tt>visitParameter</tt> )* [
+ * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* [
+ * <tt>visitCode</tt> ( <tt>visitFrame</tt> | <tt>visit<i>X</i>Insn</tt> |
+ * <tt>visitLabel</tt> | <tt>visitInsnAnnotation</tt> |
+ * <tt>visitTryCatchBlock</tt> | <tt>visitTryCatchBlockAnnotation</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLocalVariableAnnotation</tt> |
+ * <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In
+ * addition, the <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must
+ * be called in the sequential order of the bytecode instructions of the visited
+ * code, <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
+ * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
+ * corresponding try catch block has been visited, and the
+ * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
+ * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
+ * passed as arguments have been visited.
+ *
* @author Eric Bruneton
*/
public abstract class MethodVisitor {
/**
* The ASM API version implemented by this visitor. The value of this field
- * must be one of {@link Opcodes#ASM4}.
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
protected final int api;
@@ -62,9 +68,10 @@ public abstract class MethodVisitor {
/**
* Constructs a new {@link MethodVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodVisitor(final int api) {
this(api, null);
@@ -72,30 +79,51 @@ public abstract class MethodVisitor {
/**
* Constructs a new {@link MethodVisitor}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv the method visitor to which this visitor must delegate method
- * calls. May be null.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this visitor must delegate method
+ * calls. May be null.
*/
public MethodVisitor(final int api, final MethodVisitor mv) {
- /*if (api != Opcodes.ASM4) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
throw new IllegalArgumentException();
- }*/
+ }
this.api = api;
this.mv = mv;
}
// -------------------------------------------------------------------------
- // Annotations and non standard attributes
+ // Parameters, annotations and non standard attributes
// -------------------------------------------------------------------------
/**
+ * Visits a parameter of this method.
+ *
+ * @param name
+ * parameter name or null if none is provided.
+ * @param access
+ * the parameter's access flags, only <tt>ACC_FINAL</tt>,
+ * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
+ * allowed (see {@link Opcodes}).
+ */
+ public void visitParameter(String name, int access) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ mv.visitParameter(name, access);
+ }
+ }
+
+ /**
* Visits the default value of this annotation interface method.
- *
+ *
* @return a visitor to the visit the actual default value of this
- * annotation interface method, or <tt>null</tt> if this visitor
- * is not interested in visiting this default value. The 'name'
+ * annotation interface method, or <tt>null</tt> if this visitor is
+ * not interested in visiting this default value. The 'name'
* parameters passed to the methods of this annotation visitor are
* ignored. Moreover, exacly one visit method must be called on this
* annotation visitor, followed by visitEnd.
@@ -109,9 +137,11 @@ public abstract class MethodVisitor {
/**
* Visits an annotation of this method.
- *
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
@@ -123,19 +153,55 @@ public abstract class MethodVisitor {
}
/**
+ * Visits an annotation on a type in the method signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
+ * METHOD_TYPE_PARAMETER},
+ * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
+ * METHOD_TYPE_PARAMETER_BOUND},
+ * {@link TypeReference#METHOD_RETURN METHOD_RETURN},
+ * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link TypeReference#METHOD_FORMAL_PARAMETER
+ * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
+ * THROWS}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits an annotation of a parameter this method.
- *
- * @param parameter the parameter index.
- * @param desc the class descriptor of the annotation class.
- * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ *
+ * @param parameter
+ * the parameter index.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
- public AnnotationVisitor visitParameterAnnotation(
- int parameter,
- String desc,
- boolean visible)
- {
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
if (mv != null) {
return mv.visitParameterAnnotation(parameter, desc, visible);
}
@@ -144,8 +210,9 @@ public abstract class MethodVisitor {
/**
* Visits a non standard attribute of this method.
- *
- * @param attr an attribute.
+ *
+ * @param attr
+ * an attribute.
*/
public void visitAttribute(Attribute attr) {
if (mv != null) {
@@ -169,57 +236,76 @@ public abstract class MethodVisitor {
* such as GOTO or THROW, that is the target of a jump instruction, or that
* starts an exception handler block. The visited types must describe the
* values of the local variables and of the operand stack elements <i>just
- * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
- * for classes whose version is greater than or equal to
- * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
- * "deltas" from the state of the previous frame (very first frame is
- * implicitly defined by the method's parameters and access flags): <ul>
+ * before</i> <b>i</b> is executed.<br>
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or
+ * equal to {@link Opcodes#V1_6 V1_6}. <br>
+ * <br>
+ * The frames of a method must be given either in expanded form, or in
+ * compressed form (all frames must use the same format, i.e. you must not
+ * mix expanded and compressed frames within a single method):
+ * <ul>
+ * <li>In expanded form, all frames must have the F_NEW type.</li>
+ * <li>In compressed form, frames are basically "deltas" from the state of
+ * the previous frame:
+ * <ul>
* <li>{@link Opcodes#F_SAME} representing frame with exactly the same
- * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
- * representing frame with exactly the same locals as the previous frame and
- * with single value on the stack (<code>nStack</code> is 1 and
- * <code>stack[0]</code> contains value for the type of the stack item).</li>
+ * locals as the previous frame and with the empty stack.</li>
+ * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
+ * locals as the previous frame and with single value on the stack (
+ * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
+ * type of the stack item).</li>
* <li>{@link Opcodes#F_APPEND} representing frame with current locals are
* the same as the locals in the previous frame, except that additional
* locals are defined (<code>nLocal</code> is 1, 2 or 3 and
* <code>local</code> elements contains values representing added types).</li>
- * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
- * the same as the locals in the previous frame, except that the last 1-3
- * locals are absent and with the empty stack (<code>nLocals</code> is 1,
- * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
- * data.</li> </li> </ul>
- *
- * @param type the type of this stack map frame. Must be
- * {@link Opcodes#F_NEW} for expanded frames, or
- * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
- * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
- * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
- * frames.
- * @param nLocal the number of local variables in the visited frame.
- * @param local the local variable types in this frame. This array must not
- * be modified. Primitive types are represented by
- * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
- * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
- * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
- * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
- * represented by a single element). Reference types are represented
- * by String objects (representing internal names), and uninitialized
- * types by Label objects (this label designates the NEW instruction
- * that created this uninitialized value).
- * @param nStack the number of operand stack elements in the visited frame.
- * @param stack the operand stack types in this frame. This array must not
- * be modified. Its content has the same format as the "local" array.
- * @throws IllegalStateException if a frame is visited just after another
- * one, without any instruction between the two (unless this frame
- * is a Opcodes#F_SAME frame, in which case it is silently ignored).
- */
- public void visitFrame(
- int type,
- int nLocal,
- Object[] local,
- int nStack,
- Object[] stack)
- {
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
+ * same as the locals in the previous frame, except that the last 1-3 locals
+ * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
+ * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * <br>
+ * In both cases the first frame, corresponding to the method's parameters
+ * and access flags, is implicit and must not be visited. Also, it is
+ * illegal to visit two or more frames for the same code location (i.e., at
+ * least one instruction must be visited between two calls to visitFrame).
+ *
+ * @param type
+ * the type of this stack map frame. Must be
+ * {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
+ * compressed frames.
+ * @param nLocal
+ * the number of local variables in the visited frame.
+ * @param local
+ * the local variable types in this frame. This array must not be
+ * modified. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are
+ * represented by String objects (representing internal names),
+ * and uninitialized types by Label objects (this label
+ * designates the NEW instruction that created this uninitialized
+ * value).
+ * @param nStack
+ * the number of operand stack elements in the visited frame.
+ * @param stack
+ * the operand stack types in this frame. This array must not be
+ * modified. Its content has the same format as the "local"
+ * array.
+ * @throws IllegalStateException
+ * if a frame is visited just after another one, without any
+ * instruction between the two (unless this frame is a
+ * Opcodes#F_SAME frame, in which case it is silently ignored).
+ */
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+ Object[] stack) {
if (mv != null) {
mv.visitFrame(type, nLocal, local, nStack, stack);
}
@@ -231,21 +317,23 @@ public abstract class MethodVisitor {
/**
* Visits a zero operand instruction.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either 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, IALOAD, LALOAD, FALOAD,
- * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, 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,
- * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
- * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
- * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
- * MONITORENTER, or MONITOREXIT.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either 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, IALOAD,
+ * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+ * 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, I2L, I2F, I2D,
+ * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+ * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+ * or MONITOREXIT.
*/
public void visitInsn(int opcode) {
if (mv != null) {
@@ -255,18 +343,21 @@ public abstract class MethodVisitor {
/**
* Visits an instruction with a single int operand.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand the operand of the instruction to be visited.<br> When
- * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
- * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
- * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
- * opcode is NEWARRAY, operand value should be one of
- * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
- * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
- * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
- * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand
+ * the operand of the instruction to be visited.<br>
+ * When opcode is BIPUSH, operand value should be between
+ * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+ * When opcode is SIPUSH, operand value should be between
+ * Short.MIN_VALUE and Short.MAX_VALUE.<br>
+ * When opcode is NEWARRAY, operand value should be one of
+ * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+ * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+ * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+ * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
*/
public void visitIntInsn(int opcode, int operand) {
if (mv != null) {
@@ -277,12 +368,14 @@ public abstract class MethodVisitor {
/**
* Visits a local variable instruction. A local variable instruction is an
* instruction that loads or stores the value of a local variable.
- *
- * @param opcode the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
- * LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be visited. This operand is
- * the index of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be visited.
+ * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
+ * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be visited. This operand is
+ * the index of a local variable.
*/
public void visitVarInsn(int opcode, int var) {
if (mv != null) {
@@ -293,12 +386,14 @@ public abstract class MethodVisitor {
/**
* Visits a type instruction. A type instruction is an instruction that
* takes the internal name of a class as parameter.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param type the operand of the instruction to be visited. This operand
- * must be the internal name of an object or array class (see {@link
- * Type#getInternalName() getInternalName}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type
+ * the operand of the instruction to be visited. This operand
+ * must be the internal name of an object or array class (see
+ * {@link Type#getInternalName() getInternalName}).
*/
public void visitTypeInsn(int opcode, String type) {
if (mv != null) {
@@ -309,15 +404,20 @@ public abstract class MethodVisitor {
/**
* Visits a field instruction. A field instruction is an instruction that
* loads or stores the value of a field of an object.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner the internal name of the field's owner class (see {@link
- * Type#getInternalName() getInternalName}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- */
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner
+ * the internal name of the field's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ */
+ public void visitFieldInsn(int opcode, String owner, String name,
+ String desc) {
if (mv != null) {
mv.visitFieldInsn(opcode, owner, name, desc);
}
@@ -326,34 +426,83 @@ public abstract class MethodVisitor {
/**
* Visits a method instruction. A method instruction is an instruction that
* invokes a method.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
- * or INVOKEINTERFACE.
- * @param owner the internal name of the method's owner class (see {@link
- * Type#getInternalName() getInternalName}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- */
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ @Deprecated
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
if (mv != null) {
mv.visitMethodInsn(opcode, owner, name, desc);
}
}
/**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param itf
+ * if the method's owner class is an interface.
+ */
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ /**
* Visits an invokedynamic instruction.
- *
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param bsm the bootstrap method.
- * @param bsmArgs the bootstrap method constant arguments. Each argument
- * must be an {@link Integer}, {@link Float}, {@link Long},
- * {@link Double}, {@link String}, {@link Type} or {@link Handle}
- * value. This method is allowed to modify the content of the array
- * so a caller should expect that this array may change.
- */
- public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the
+ * array so a caller should expect that this array may change.
+ */
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
if (mv != null) {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
@@ -362,14 +511,16 @@ public abstract class MethodVisitor {
/**
* Visits a jump instruction. A jump instruction is an instruction that may
* jump to another instruction.
- *
- * @param opcode the opcode of the type instruction to be visited. This
- * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
- * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label the operand of the instruction to be visited. This operand
- * is a label that designates the instruction to which the jump
- * instruction may jump.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label
+ * the operand of the instruction to be visited. This operand is
+ * a label that designates the instruction to which the jump
+ * instruction may jump.
*/
public void visitJumpInsn(int opcode, Label label) {
if (mv != null) {
@@ -380,8 +531,9 @@ public abstract class MethodVisitor {
/**
* Visits a label. A label designates the instruction that will be visited
* just after it.
- *
- * @param label a {@link Label Label} object.
+ *
+ * @param label
+ * a {@link Label Label} object.
*/
public void visitLabel(Label label) {
if (mv != null) {
@@ -398,41 +550,44 @@ public abstract class MethodVisitor {
* future versions of the Java Virtual Machine. To easily detect new
* constant types, implementations of this method should check for
* unexpected constant types, like this:
+ *
* <pre>
* if (cst instanceof Integer) {
- * // ...
+ * // ...
* } else if (cst instanceof Float) {
- * // ...
+ * // ...
* } else if (cst instanceof Long) {
- * // ...
- * } else if (cst instanceof Double) {
- * // ...
- * } else if (cst instanceof String) {
- * // ...
- * } else if (cst instanceof Type) {
- * int sort = ((Type) cst).getSort();
- * if (sort == Type.OBJECT) {
* // ...
- * } else if (sort == Type.ARRAY) {
+ * } else if (cst instanceof Double) {
* // ...
- * } else if (sort == Type.METHOD) {
+ * } else if (cst instanceof String) {
* // ...
- * } else {
- * // throw an exception
- * }
+ * } else if (cst instanceof Type) {
+ * int sort = ((Type) cst).getSort();
+ * if (sort == Type.OBJECT) {
+ * // ...
+ * } else if (sort == Type.ARRAY) {
+ * // ...
+ * } else if (sort == Type.METHOD) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
* } else if (cst instanceof Handle) {
- * // ...
+ * // ...
* } else {
- * // throw an exception
- * }</pre>
- *
- * @param cst the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY
- * sort for <tt>.class</tt> constants, for classes whose version is
- * 49.0, a {@link Type} of METHOD sort or a {@link Handle} for
- * MethodType and MethodHandle constants, for classes whose version
- * is 51.0.
+ * // throw an exception
+ * }
+ * </pre>
+ *
+ * @param cst
+ * the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double}, a {@link String}, a {@link Type} of OBJECT or
+ * ARRAY sort for <tt>.class</tt> constants, for classes whose
+ * version is 49.0, a {@link Type} of METHOD sort or a
+ * {@link Handle} for MethodType and MethodHandle constants, for
+ * classes whose version is 51.0.
*/
public void visitLdcInsn(Object cst) {
if (mv != null) {
@@ -442,9 +597,11 @@ public abstract class MethodVisitor {
/**
* Visits an IINC instruction.
- *
- * @param var index of the local variable to be incremented.
- * @param increment amount to increment the local variable by.
+ *
+ * @param var
+ * index of the local variable to be incremented.
+ * @param increment
+ * amount to increment the local variable by.
*/
public void visitIincInsn(int var, int increment) {
if (mv != null) {
@@ -454,14 +611,19 @@ public abstract class MethodVisitor {
/**
* Visits a TABLESWITCH instruction.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>min + i</tt> key.
- */
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public void visitTableSwitchInsn(int min, int max, Label dflt,
+ Label... labels) {
if (mv != null) {
mv.visitTableSwitchInsn(min, max, dflt, labels);
}
@@ -469,11 +631,14 @@ public abstract class MethodVisitor {
/**
* Visits a LOOKUPSWITCH instruction.
- *
- * @param dflt beginning of the default handler block.
- * @param keys the values of the keys.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ *
+ * @param dflt
+ * beginning of the default handler block.
+ * @param keys
+ * the values of the keys.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>keys[i]</tt> key.
*/
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
if (mv != null) {
@@ -483,9 +648,11 @@ public abstract class MethodVisitor {
/**
* Visits a MULTIANEWARRAY instruction.
- *
- * @param desc an array type descriptor (see {@link Type Type}).
- * @param dims number of dimensions of the array to allocate.
+ *
+ * @param desc
+ * an array type descriptor (see {@link Type Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
*/
public void visitMultiANewArrayInsn(String desc, int dims) {
if (mv != null) {
@@ -493,68 +660,191 @@ public abstract class MethodVisitor {
}
}
+ /**
+ * Visits an annotation on an instruction. This method must be called just
+ * <i>after</i> the annotated instruction. It can be called several times
+ * for the same instruction.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
+ * {@link TypeReference#NEW NEW},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE
+ * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
+ * METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
+ * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
// -------------------------------------------------------------------------
// Exceptions table entries, debug information, max stack and max locals
// -------------------------------------------------------------------------
/**
* Visits a try catch block.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for "finally"
- * blocks).
- * @throws IllegalArgumentException if one of the labels has already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
- */
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
+ * @throws IllegalArgumentException
+ * if one of the labels has already been visited by this visitor
+ * (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
if (mv != null) {
mv.visitTryCatchBlock(start, end, handler, type);
}
}
/**
+ * Visits an annotation on an exception handler type. This method must be
+ * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
+ * exception handler. It can be called several times for the same exception
+ * handler.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#EXCEPTION_PARAMETER
+ * EXCEPTION_PARAMETER}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a local variable declaration.
- *
- * @param name the name of a local variable.
- * @param desc the type descriptor of this local variable.
- * @param signature the type signature of this local variable. May be
- * <tt>null</tt> if the local variable type does not use generic
- * types.
- * @param start the first instruction corresponding to the scope of this
- * local variable (inclusive).
- * @param end the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index the local variable's index.
- * @throws IllegalArgumentException if one of the labels has not already
- * been visited by this visitor (by the
- * {@link #visitLabel visitLabel} method).
- */
- public void visitLocalVariable(
- String name,
- String desc,
- String signature,
- Label start,
- Label end,
- int index)
- {
+ *
+ * @param name
+ * the name of a local variable.
+ * @param desc
+ * the type descriptor of this local variable.
+ * @param signature
+ * the type signature of this local variable. May be
+ * <tt>null</tt> if the local variable type does not use generic
+ * types.
+ * @param start
+ * the first instruction corresponding to the scope of this local
+ * variable (inclusive).
+ * @param end
+ * the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index
+ * the local variable's index.
+ * @throws IllegalArgumentException
+ * if one of the labels has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
if (mv != null) {
mv.visitLocalVariable(name, desc, signature, start, end, index);
}
}
/**
+ * Visits an annotation on a local variable type.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#LOCAL_VARIABLE
+ * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
+ * RESOURCE_VARIABLE}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
+ end, index, desc, visible);
+ }
+ return null;
+ }
+
+ /**
* Visits a line number declaration.
- *
- * @param line a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start the first instruction corresponding to this line number.
- * @throws IllegalArgumentException if <tt>start</tt> has not already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
+ *
+ * @param line
+ * a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start
+ * the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException
+ * if <tt>start</tt> has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
*/
public void visitLineNumber(int line, Label start) {
if (mv != null) {
@@ -565,9 +855,11 @@ public abstract class MethodVisitor {
/**
* Visits the maximum stack size and the maximum number of local variables
* of the method.
- *
- * @param maxStack maximum stack size of the method.
- * @param maxLocals maximum number of local variables for the method.
+ *
+ * @param maxStack
+ * maximum stack size of the method.
+ * @param maxLocals
+ * maximum number of local variables for the method.
*/
public void visitMaxs(int maxStack, int maxLocals) {
if (mv != null) {
[09/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
index d2d461c..ce959df 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,22 +29,29 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+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 node that represents a method.
- *
+ *
* @author Eric Bruneton
*/
-public class MethodNode extends MethodVisitor
-{
+public class MethodNode extends MethodVisitor {
/**
- * The method's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also
+ * The method's access flags (see {@link Opcodes}). This field also
* indicates if the method is synthetic and/or deprecated.
*/
public int access;
@@ -56,7 +62,7 @@ public class MethodNode extends MethodVisitor
public String name;
/**
- * The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * The method's descriptor (see {@link Type}).
*/
public String desc;
@@ -67,16 +73,21 @@ public class MethodNode extends MethodVisitor
/**
* The internal names of the method's exception classes (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). This list is a list of
+ * {@link Type#getInternalName() getInternalName}). This list is a list of
* {@link String} objects.
*/
public List<String> exceptions;
/**
+ * The method parameter info (access flags and name)
+ */
+ public List<ParameterNode> parameters;
+
+ /**
* The runtime visible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -84,17 +95,35 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this method. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this method. This list is a
+ * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this method. This list is a list of
- * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
@@ -102,7 +131,7 @@ public class MethodNode extends MethodVisitor
* The default value of this annotation interface method. This field must be
* a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer}, {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an two elements String array (for
+ * {@link String} or {@link Type}, or an two elements String array (for
* enumeration values), a {@link AnnotationNode}, or a {@link List} of
* values of one of the preceding types. May be <tt>null</tt>.
*/
@@ -111,8 +140,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime visible parameter annotations of this method. These lists are
* lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible parameters
*/
public List<AnnotationNode>[] visibleParameterAnnotations;
@@ -120,8 +149,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible parameter annotations of this method. These lists
* are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible parameters
*/
public List<AnnotationNode>[] invisibleParameterAnnotations;
@@ -129,8 +158,8 @@ public class MethodNode extends MethodVisitor
/**
* The instructions of this method. This list is a list of
* {@link AbstractInsnNode} objects.
- *
- * @associates AbstractInsnNode
+ *
+ * @associates org.objectweb.asm.tree.AbstractInsnNode
* @label instructions
*/
public InsnList instructions;
@@ -138,8 +167,8 @@ public class MethodNode extends MethodVisitor
/**
* The try catch blocks of this method. This list is a list of
* {@link TryCatchBlockNode} objects.
- *
- * @associates TryCatchBlockNode
+ *
+ * @associates org.objectweb.asm.tree.TryCatchBlockNode
*/
public List<TryCatchBlockNode> tryCatchBlocks;
@@ -156,30 +185,53 @@ public class MethodNode extends MethodVisitor
/**
* The local variables of this method. This list is a list of
* {@link LocalVariableNode} objects. May be <tt>null</tt>
- *
- * @associates LocalVariableNode
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableNode
*/
public List<LocalVariableNode> localVariables;
/**
+ * The visible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
+
+ /**
+ * The invisible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
+
+ /**
* If the accept method has been called on this object.
*/
private boolean visited;
-
+
/**
* Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
* use this constructor</i>. Instead, they must use the
* {@link #MethodNode(int)} version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public MethodNode() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs an uninitialized {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodNode(final int api) {
super(api);
@@ -190,57 +242,61 @@ public class MethodNode extends MethodVisitor
* Constructs a new {@link MethodNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #MethodNode(int, int, String, String, String, String[])} version.
- *
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public MethodNode(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- this(Opcodes.ASM4, access, name, desc, signature, exceptions);
+ public MethodNode(final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ this(Opcodes.ASM5, access, name, desc, signature, exceptions);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- public MethodNode(
- final int api,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ public MethodNode(final int api, final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
super(api);
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
- this.exceptions = new ArrayList<String>(exceptions == null
- ? 0
+ this.exceptions = new ArrayList<String>(exceptions == null ? 0
: exceptions.length);
boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
if (!isAbstract) {
@@ -258,6 +314,14 @@ public class MethodNode extends MethodVisitor
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(String name, int access) {
+ if (parameters == null) {
+ parameters = new ArrayList<ParameterNode>(5);
+ }
+ parameters.add(new ParameterNode(name, access));
+ }
+
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
return new AnnotationNode(new ArrayList<Object>(0) {
@Override
@@ -269,10 +333,8 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -289,28 +351,45 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (visibleParameterAnnotations[parameter] == null) {
- visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
visibleParameterAnnotations[parameter].add(an);
} else {
if (invisibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (invisibleParameterAnnotations[parameter] == null) {
- invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
invisibleParameterAnnotations[parameter].add(an);
}
@@ -330,17 +409,10 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
- instructions.add(new FrameNode(type, nLocal, local == null
- ? null
- : getLabelNodes(local), nStack, stack == null
- ? null
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ instructions.add(new FrameNode(type, nLocal, local == null ? null
+ : getLabelNodes(local), nStack, stack == null ? null
: getLabelNodes(stack)));
}
@@ -365,32 +437,35 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
instructions.add(new FieldInsnNode(opcode, owner, name, desc));
}
+ @Deprecated
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
instructions.add(new MethodInsnNode(opcode, owner, name, desc));
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
}
@@ -415,26 +490,16 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
- instructions.add(new TableSwitchInsnNode(min,
- max,
- getLabelNode(dflt),
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
getLabelNodes(labels)));
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
- instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
- keys,
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
getLabelNodes(labels)));
}
@@ -444,33 +509,89 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ // Finds the last real instruction, i.e. the instruction targeted by
+ // this annotation.
+ AbstractInsnNode insn = instructions.getLast();
+ while (insn.getOpcode() == -1) {
+ insn = insn.getPrevious();
+ }
+ // Adds the annotation to this instruction.
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (insn.visibleTypeAnnotations == null) {
+ insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.visibleTypeAnnotations.add(an);
+ } else {
+ if (insn.invisibleTypeAnnotations == null) {
+ insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
- getLabelNode(end),
- getLabelNode(handler),
- type));
+ getLabelNode(end), getLabelNode(handler), type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (tcb.visibleTypeAnnotations == null) {
+ tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.visibleTypeAnnotations.add(an);
+ } else {
+ if (tcb.invisibleTypeAnnotations == null) {
+ tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.invisibleTypeAnnotations.add(an);
+ }
+ return an;
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
- localVariables.add(new LocalVariableNode(name,
- desc,
- signature,
- getLabelNode(start),
- getLabelNode(end),
- index));
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ localVariables.add(new LocalVariableNode(name, desc, signature,
+ getLabelNode(start), getLabelNode(end), index));
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
+ typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
+ index, desc);
+ if (visible) {
+ if (visibleLocalVariableAnnotations == null) {
+ visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ visibleLocalVariableAnnotations.add(an);
+ } else {
+ if (invisibleLocalVariableAnnotations == null) {
+ invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ invisibleLocalVariableAnnotations.add(an);
+ }
+ return an;
}
@Override
@@ -493,13 +614,14 @@ public class MethodNode extends MethodVisitor
* LabelNode if necessary. The default implementation of this method uses
* the {@link Label#info} field to store associations between labels and
* label nodes.
- *
- * @param l a Label.
+ *
+ * @param l
+ * a Label.
* @return the LabelNode corresponding to l.
*/
protected LabelNode getLabelNode(final Label l) {
if (!(l.info instanceof LabelNode)) {
- l.info = new LabelNode(l);
+ l.info = new LabelNode();
}
return (LabelNode) l.info;
}
@@ -533,25 +655,71 @@ public class MethodNode extends MethodVisitor
* version. This methods checks that this node, and all its nodes
* recursively, do not contain elements that were introduced in more recent
* versions of the ASM API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
+ for (int i = 0; i < n; ++i) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get(i);
+ if (tcb.visibleTypeAnnotations != null
+ && tcb.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (tcb.invisibleTypeAnnotations != null
+ && tcb.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
+ for (int i = 0; i < instructions.size(); ++i) {
+ AbstractInsnNode insn = instructions.get(i);
+ if (insn.visibleTypeAnnotations != null
+ && insn.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn.invisibleTypeAnnotations != null
+ && insn.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn instanceof MethodInsnNode) {
+ boolean itf = ((MethodInsnNode) insn).itf;
+ if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new RuntimeException();
+ }
+ }
+ }
+ if (visibleLocalVariableAnnotations != null
+ && visibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleLocalVariableAnnotations != null
+ && invisibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
}
/**
* Makes the given class visitor visit this method.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
String[] exceptions = new String[this.exceptions.size()];
this.exceptions.toArray(exceptions);
- MethodVisitor mv = cv.visitMethod(access,
- name,
- desc,
- signature,
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
exceptions);
if (mv != null) {
accept(mv);
@@ -560,12 +728,19 @@ public class MethodNode extends MethodVisitor
/**
* Makes the given method visitor visit this method.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- // visits the method attributes
+ // visits the method parameters
int i, j, n;
+ n = parameters == null ? 0 : parameters.size();
+ for (i = 0; i < n; i++) {
+ ParameterNode parameter = parameters.get(i);
+ mv.visitParameter(parameter.name, parameter.access);
+ }
+ // visits the method attributes
if (annotationDefault != null) {
AnnotationVisitor av = mv.visitAnnotationDefault();
AnnotationNode.accept(av, null, annotationDefault);
@@ -583,8 +758,20 @@ public class MethodNode extends MethodVisitor
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(mv.visitAnnotation(an.desc, false));
}
- n = visibleParameterAnnotations == null
- ? 0
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
+ n = visibleParameterAnnotations == null ? 0
: visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = visibleParameterAnnotations[i];
@@ -596,8 +783,7 @@ public class MethodNode extends MethodVisitor
an.accept(mv.visitParameterAnnotation(i, an.desc, true));
}
}
- n = invisibleParameterAnnotations == null
- ? 0
+ n = invisibleParameterAnnotations == null ? 0
: invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = invisibleParameterAnnotations[i];
@@ -622,6 +808,7 @@ public class MethodNode extends MethodVisitor
// visits try catch blocks
n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
for (i = 0; i < n; ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
tryCatchBlocks.get(i).accept(mv);
}
// visits instructions
@@ -631,6 +818,17 @@ public class MethodNode extends MethodVisitor
for (i = 0; i < n; ++i) {
localVariables.get(i).accept(mv);
}
+ // visits local variable annotations
+ n = visibleLocalVariableAnnotations == null ? 0
+ : visibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ visibleLocalVariableAnnotations.get(i).accept(mv, true);
+ }
+ n = invisibleLocalVariableAnnotations == null ? 0
+ : invisibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ invisibleLocalVariableAnnotations.get(i).accept(mv, false);
+ }
// visits maxs
mv.visitMaxs(maxStack, maxLocals);
visited = true;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
index d27837d..f0d2b6b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents a MULTIANEWARRAY instruction.
- *
+ *
* @author Eric Bruneton
*/
public class MultiANewArrayInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link MultiANewArrayInsnNode}.
- *
- * @param desc an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param dims number of dimensions of the array to allocate.
+ *
+ * @param desc
+ * an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
*/
public MultiANewArrayInsnNode(final String desc, final int dims) {
super(Opcodes.MULTIANEWARRAY);
@@ -71,11 +73,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitMultiANewArrayInsn(desc, dims);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MultiANewArrayInsnNode(desc, dims);
+ return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
}
}
\ 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/ParameterNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
new file mode 100644
index 0000000..d5435de
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
+/**
+ * A node that represents a parameter access and name.
+ *
+ * @author Remi Forax
+ */
+public class ParameterNode {
+ /**
+ * The parameter's name.
+ */
+ public String name;
+
+ /**
+ * The parameter's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
+ * <tt>ACC_MANDATED</tt>.
+ */
+ public int access;
+
+ /**
+ * Constructs a new {@link ParameterNode}.
+ *
+ * @param access
+ * The parameter's access flags. Valid values are
+ * <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
+ * <tt>ACC_MANDATED</tt> (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * @param name
+ * the parameter's name.
+ */
+ public ParameterNode(final String name, final int access) {
+ this.name = name;
+ this.access = access;
+ }
+
+ /**
+ * Makes the given visitor visit this parameter declaration.
+ *
+ * @param mv
+ * a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitParameter(name, access);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
index 17ad4ec..e9ef6f2 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
@@ -29,18 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a TABLESWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class TableSwitchInsnNode extends AbstractInsnNode {
@@ -68,19 +68,19 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TableSwitchInsnNode}.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>min + i</tt> key.
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
*/
- public TableSwitchInsnNode(
- final int min,
- final int max,
- final LabelNode dflt,
- final LabelNode... labels)
- {
+ public TableSwitchInsnNode(final int min, final int max,
+ final LabelNode dflt, final LabelNode... labels) {
super(Opcodes.TABLESWITCH);
this.min = min;
this.max = max;
@@ -103,13 +103,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TableSwitchInsnNode(min,
- max,
- clone(dflt, labels),
- clone(this.labels, labels));
+ return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
+ this.labels, labels)).cloneAnnotations(this);
}
}
\ 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/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
index 52ea45f..a4c8dde 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
@@ -29,11 +29,13 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a try catch block.
- *
+ *
* @author Eric Bruneton
*/
public class TryCatchBlockNode {
@@ -60,21 +62,41 @@ public class TryCatchBlockNode {
public String type;
/**
+ * The runtime visible type annotations on the exception handler type. This
+ * list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations on the exception handler type.
+ * This list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* Constructs a new {@link TryCatchBlockNode}.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for "finally"
- * blocks).
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
*/
- public TryCatchBlockNode(
- final LabelNode start,
- final LabelNode end,
- final LabelNode handler,
- final String type)
- {
+ public TryCatchBlockNode(final LabelNode start, final LabelNode end,
+ final LabelNode handler, final String type) {
this.start = start;
this.end = end;
this.handler = handler;
@@ -82,13 +104,50 @@ public class TryCatchBlockNode {
}
/**
+ * Updates the index of this try catch block in the method's list of try
+ * catch block nodes. This index maybe stored in the 'target' field of the
+ * type annotations of this block.
+ *
+ * @param index
+ * the new index of this try catch block in the method's list of
+ * try catch block nodes.
+ */
+ public void updateIndex(final int index) {
+ int newTypeRef = 0x42000000 | (index << 8);
+ if (visibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : visibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ }
+
+ /**
* Makes the given visitor visit this try catch block.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
- ? null
- : handler.getLabel(), type);
+ mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
+ handler == null ? null : handler.getLabel(), type);
+ int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, false));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
new file mode 100644
index 0000000..66ec2d3
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotationn.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeAnnotationNode extends AnnotationNode {
+
+ /**
+ * A reference to the annotated type. See {@link TypeReference}.
+ */
+ public int typeRef;
+
+ /**
+ * The path to the annotated type argument, wildcard bound, array element
+ * type, or static outer type within the referenced type. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ */
+ public TypePath typePath;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public TypeAnnotationNode(final int typeRef, final TypePath typePath,
+ final String desc) {
+ this(Opcodes.ASM5, typeRef, typePath, desc);
+ if (getClass() != TypeAnnotationNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public TypeAnnotationNode(final int api, final int typeRef,
+ final TypePath typePath, final String desc) {
+ super(api, desc);
+ this.typeRef = typeRef;
+ this.typePath = typePath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
index e5bc30e..b4572e5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a type instruction. A type instruction is an
* instruction that takes a type descriptor as parameter.
- *
+ *
* @author Eric Bruneton
*/
public class TypeInsnNode extends AbstractInsnNode {
@@ -49,11 +49,13 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TypeInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param desc the operand of the instruction to be constructed. This
- * operand is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param desc
+ * the operand of the instruction to be constructed. This operand
+ * is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
*/
public TypeInsnNode(final int opcode, final String desc) {
super(opcode);
@@ -62,9 +64,10 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be NEW,
- * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -78,10 +81,11 @@ public class TypeInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitTypeInsn(opcode, desc);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TypeInsnNode(opcode, desc);
+ return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
}
}
\ 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/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
index 3819d31..58552de 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
@@ -1,6 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
-` * Copyright (c) 2000-2011 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,15 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a local variable instruction. A local variable
* instruction is an instruction that loads or stores the value of a local
* variable.
- *
+ *
* @author Eric Bruneton
*/
public class VarInsnNode extends AbstractInsnNode {
@@ -50,12 +50,14 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link VarInsnNode}.
- *
- * @param opcode the opcode of the local variable instruction to be
- * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
- * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be constructed. This operand
- * is the index of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be
+ * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be constructed. This operand
+ * is the index of a local variable.
*/
public VarInsnNode(final int opcode, final int var) {
super(opcode);
@@ -64,10 +66,11 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be ILOAD,
- * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
- * or RET.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be ILOAD, LLOAD,
+ * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
+ * RET.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -81,10 +84,11 @@ public class VarInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitVarInsn(opcode, var);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new VarInsnNode(opcode, var);
+ return new VarInsnNode(opcode, var).cloneAnnotations(this);
}
}
\ 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/Analyzer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..a78fff4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+ private final Interpreter<V> interpreter;
+
+ private int n;
+
+ private InsnList insns;
+
+ private List<TryCatchBlockNode>[] handlers;
+
+ private Frame<V>[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter
+ * the interpreter to be used to symbolically interpret the
+ * bytecode instructions.
+ */
+ public Analyzer(final Interpreter<V> interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException
+ * if a problem occurs during the analysis.
+ */
+ public Frame<V>[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException {
+ if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = (Frame<V>[]) new Frame<?>[0];
+ return frames;
+ }
+ n = m.instructions.size();
+ insns = m.instructions;
+ handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
+ frames = (Frame<V>[]) new Frame<?>[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+ int begin = insns.indexOf(tcb.start);
+ int end = insns.indexOf(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List<TryCatchBlockNode> insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList<TryCatchBlockNode>();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // computes the subroutine for each instruction:
+ Subroutine main = new Subroutine(null, m.maxLocals, null);
+ List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+ Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+ findSubroutine(0, main, subroutineCalls);
+ while (!subroutineCalls.isEmpty()) {
+ JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+ Subroutine sub = subroutineHeads.get(jsr.label);
+ if (sub == null) {
+ sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+ subroutineHeads.put(jsr.label, sub);
+ findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ } else {
+ sub.callers.add(jsr);
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+ Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+ current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getObjectType(owner);
+ current.setLocal(local++, interpreter.newValue(ctype));
+ }
+ for (int i = 0; i < args.length; ++i) {
+ current.setLocal(local++, interpreter.newValue(args[i]));
+ if (args[i].getSize() == 2) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ }
+ while (local < m.maxLocals) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ merge(0, current, null);
+
+ init(owner, m);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame<V> f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ AbstractInsnNode insnNode = null;
+ try {
+ insnNode = m.instructions.get(insn);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME) {
+ merge(insn + 1, f, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ } else {
+ current.init(f).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : subroutine.copy();
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode j = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ int jump = insns.indexOf(j.label);
+ if (insnOpcode == JSR) {
+ merge(jump, current, new Subroutine(j.label,
+ m.maxLocals, j));
+ } else {
+ merge(jump, current, subroutine);
+ }
+ newControlFlowEdge(insn, jump);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(lsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ LabelNode label = lsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(tsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ LabelNode label = tsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException(insnNode,
+ "RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ int call = insns.indexOf(caller);
+ if (frames[call] != null) {
+ merge(call + 1, frames[call], current,
+ subroutines[call], subroutine.access);
+ newControlFlowEdge(insn, call + 1);
+ }
+ }
+ } else if (insnOpcode != ATHROW
+ && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ if (insnOpcode == LLOAD || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE) {
+ subroutine.access[var + 1] = true;
+ }
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ }
+ }
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ }
+
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getObjectType("java/lang/Throwable");
+ } else {
+ type = Type.getObjectType(tcb.type);
+ }
+ int jump = insns.indexOf(tcb.handler);
+ if (newControlFlowExceptionEdge(insn, tcb)) {
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(jump, handler, subroutine);
+ }
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException(e.node, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw new AnalyzerException(insnNode, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ private void findSubroutine(int insn, final Subroutine sub,
+ final List<AbstractInsnNode> calls) throws AnalyzerException {
+ while (true) {
+ if (insn < 0 || insn >= n) {
+ throw new AnalyzerException(null,
+ "Execution can fall off end of the code");
+ }
+ if (subroutines[insn] != null) {
+ return;
+ }
+ subroutines[insn] = sub.copy();
+ AbstractInsnNode node = insns.get(insn);
+
+ // calls findSubroutine recursively on normal successors
+ if (node instanceof JumpInsnNode) {
+ if (node.getOpcode() == JSR) {
+ // do not follow a JSR, it leads to another subroutine!
+ calls.add(node);
+ } else {
+ JumpInsnNode jnode = (JumpInsnNode) node;
+ findSubroutine(insns.indexOf(jnode.label), sub, calls);
+ }
+ } else if (node instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+ for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = tsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ } else if (node instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+ for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = lsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ }
+
+ // calls findSubroutine recursively on exception handler successors
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+ }
+ }
+
+ // if insn does not falls through to the next instruction, return.
+ switch (node.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ return;
+ }
+ insn++;
+ }
+ }
+
+ /**
+ * Returns the symbolic stack frame for each instruction of the last
+ * recently analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if the corresponding instruction
+ * cannot be reached, or if an error occured during the analysis of
+ * the method.
+ */
+ public Frame<V>[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insn
+ * the index of an instruction of the last recently analyzed
+ * method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List<TryCatchBlockNode> getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * Initializes this analyzer. This method is called just before the
+ * execution of control flow analysis loop in #analyze. The default
+ * implementation of this method does nothing.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @throws AnalyzerException
+ * if a problem occurs.
+ */
+ protected void init(String owner, MethodNode m) throws AnalyzerException {
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals
+ * the maximum number of local variables of the frame.
+ * @param nStack
+ * the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final int nLocals, final int nStack) {
+ return new Frame<V>(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src
+ * a frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final Frame<? extends V> src) {
+ return new Frame<V>(src);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this
+ * method does nothing. It can be overriden in order to construct the
+ * control flow graph of a method (this method is called by the
+ * {@link #analyze analyze} method during its visit of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insn, final int successor) {
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method does nothing. It can be
+ * overridden in order to construct the control flow graph of a method (this
+ * method is called by the {@link #analyze analyze} method during its visit
+ * of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method always returns true.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final int successor) {
+ return true;
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+ * construct the control flow graph of a method (this method is called by
+ * the {@link #analyze analyze} method during its visit of the method's
+ * code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param tcb
+ * TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final TryCatchBlockNode tcb) {
+ return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(final int insn, final Frame<V> frame,
+ final Subroutine subroutine) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(frame, interpreter);
+ }
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(final int insn, final Frame<V> beforeJSR,
+ final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(afterRET, interpreter);
+ }
+
+ if (oldSubroutine != null && subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR);
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..66c9df9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,61 @@
+/***
+ * 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 org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public final AbstractInsnNode node;
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg) {
+ super(msg);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Throwable exception) {
+ super(msg, exception);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Object expected, final Value encountered) {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ this.node = node;
+ }
+}
[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?"
Posted by ka...@apache.org.
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] <binary class name or class file name>
+ *
+ * @param args
+ * the command line arguments.
+ *
+ * @throws Exception
+ * if the class cannot be found, or if an IO exception occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err
+ .println("Prints the ASM code to generate the given class.");
+ System.err.println("Usage: ASMifier [-debug] "
+ + "<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");
+ }
+ }
+}
[14/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
new file mode 100644
index 0000000..fe8400a
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/InstructionAdapter.java
@@ -0,0 +1,1170 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link MethodVisitor} providing a more detailed API to generate and
+ * transform instructions.
+ *
+ * @author Eric Bruneton
+ */
+public class InstructionAdapter extends MethodVisitor {
+
+ public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
+
+ /**
+ * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #InstructionAdapter(int, MethodVisitor)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public InstructionAdapter(final MethodVisitor mv) {
+ this(Opcodes.ASM5, mv);
+ if (getClass() != InstructionAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link InstructionAdapter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ protected InstructionAdapter(final int api, final MethodVisitor mv) {
+ super(api, mv);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ switch (opcode) {
+ case Opcodes.NOP:
+ nop();
+ break;
+ case Opcodes.ACONST_NULL:
+ aconst(null);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ iconst(opcode - Opcodes.ICONST_0);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ lconst(opcode - Opcodes.LCONST_0);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ fconst(opcode - Opcodes.FCONST_0);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ dconst(opcode - Opcodes.DCONST_0);
+ break;
+ case Opcodes.IALOAD:
+ aload(Type.INT_TYPE);
+ break;
+ case Opcodes.LALOAD:
+ aload(Type.LONG_TYPE);
+ break;
+ case Opcodes.FALOAD:
+ aload(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DALOAD:
+ aload(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AALOAD:
+ aload(OBJECT_TYPE);
+ break;
+ case Opcodes.BALOAD:
+ aload(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CALOAD:
+ aload(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SALOAD:
+ aload(Type.SHORT_TYPE);
+ break;
+ case Opcodes.IASTORE:
+ astore(Type.INT_TYPE);
+ break;
+ case Opcodes.LASTORE:
+ astore(Type.LONG_TYPE);
+ break;
+ case Opcodes.FASTORE:
+ astore(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DASTORE:
+ astore(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.AASTORE:
+ astore(OBJECT_TYPE);
+ break;
+ case Opcodes.BASTORE:
+ astore(Type.BYTE_TYPE);
+ break;
+ case Opcodes.CASTORE:
+ astore(Type.CHAR_TYPE);
+ break;
+ case Opcodes.SASTORE:
+ astore(Type.SHORT_TYPE);
+ break;
+ case Opcodes.POP:
+ pop();
+ break;
+ case Opcodes.POP2:
+ pop2();
+ break;
+ case Opcodes.DUP:
+ dup();
+ break;
+ case Opcodes.DUP_X1:
+ dupX1();
+ break;
+ case Opcodes.DUP_X2:
+ dupX2();
+ break;
+ case Opcodes.DUP2:
+ dup2();
+ break;
+ case Opcodes.DUP2_X1:
+ dup2X1();
+ break;
+ case Opcodes.DUP2_X2:
+ dup2X2();
+ break;
+ case Opcodes.SWAP:
+ swap();
+ break;
+ case Opcodes.IADD:
+ add(Type.INT_TYPE);
+ break;
+ case Opcodes.LADD:
+ add(Type.LONG_TYPE);
+ break;
+ case Opcodes.FADD:
+ add(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DADD:
+ add(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISUB:
+ sub(Type.INT_TYPE);
+ break;
+ case Opcodes.LSUB:
+ sub(Type.LONG_TYPE);
+ break;
+ case Opcodes.FSUB:
+ sub(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSUB:
+ sub(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IMUL:
+ mul(Type.INT_TYPE);
+ break;
+ case Opcodes.LMUL:
+ mul(Type.LONG_TYPE);
+ break;
+ case Opcodes.FMUL:
+ mul(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DMUL:
+ mul(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IDIV:
+ div(Type.INT_TYPE);
+ break;
+ case Opcodes.LDIV:
+ div(Type.LONG_TYPE);
+ break;
+ case Opcodes.FDIV:
+ div(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DDIV:
+ div(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IREM:
+ rem(Type.INT_TYPE);
+ break;
+ case Opcodes.LREM:
+ rem(Type.LONG_TYPE);
+ break;
+ case Opcodes.FREM:
+ rem(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DREM:
+ rem(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.INEG:
+ neg(Type.INT_TYPE);
+ break;
+ case Opcodes.LNEG:
+ neg(Type.LONG_TYPE);
+ break;
+ case Opcodes.FNEG:
+ neg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DNEG:
+ neg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ISHL:
+ shl(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHL:
+ shl(Type.LONG_TYPE);
+ break;
+ case Opcodes.ISHR:
+ shr(Type.INT_TYPE);
+ break;
+ case Opcodes.LSHR:
+ shr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IUSHR:
+ ushr(Type.INT_TYPE);
+ break;
+ case Opcodes.LUSHR:
+ ushr(Type.LONG_TYPE);
+ break;
+ case Opcodes.IAND:
+ and(Type.INT_TYPE);
+ break;
+ case Opcodes.LAND:
+ and(Type.LONG_TYPE);
+ break;
+ case Opcodes.IOR:
+ or(Type.INT_TYPE);
+ break;
+ case Opcodes.LOR:
+ or(Type.LONG_TYPE);
+ break;
+ case Opcodes.IXOR:
+ xor(Type.INT_TYPE);
+ break;
+ case Opcodes.LXOR:
+ xor(Type.LONG_TYPE);
+ break;
+ case Opcodes.I2L:
+ cast(Type.INT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.I2F:
+ cast(Type.INT_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2D:
+ cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.L2I:
+ cast(Type.LONG_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.L2F:
+ cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.L2D:
+ cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.F2I:
+ cast(Type.FLOAT_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.F2L:
+ cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.F2D:
+ cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.D2I:
+ cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
+ break;
+ case Opcodes.D2L:
+ cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
+ break;
+ case Opcodes.D2F:
+ cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.I2B:
+ cast(Type.INT_TYPE, Type.BYTE_TYPE);
+ break;
+ case Opcodes.I2C:
+ cast(Type.INT_TYPE, Type.CHAR_TYPE);
+ break;
+ case Opcodes.I2S:
+ cast(Type.INT_TYPE, Type.SHORT_TYPE);
+ break;
+ case Opcodes.LCMP:
+ lcmp();
+ break;
+ case Opcodes.FCMPL:
+ cmpl(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.FCMPG:
+ cmpg(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DCMPL:
+ cmpl(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.DCMPG:
+ cmpg(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.IRETURN:
+ areturn(Type.INT_TYPE);
+ break;
+ case Opcodes.LRETURN:
+ areturn(Type.LONG_TYPE);
+ break;
+ case Opcodes.FRETURN:
+ areturn(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DRETURN:
+ areturn(Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ARETURN:
+ areturn(OBJECT_TYPE);
+ break;
+ case Opcodes.RETURN:
+ areturn(Type.VOID_TYPE);
+ break;
+ case Opcodes.ARRAYLENGTH:
+ arraylength();
+ break;
+ case Opcodes.ATHROW:
+ athrow();
+ break;
+ case Opcodes.MONITORENTER:
+ monitorenter();
+ break;
+ case Opcodes.MONITOREXIT:
+ monitorexit();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.SIPUSH:
+ iconst(operand);
+ break;
+ case Opcodes.NEWARRAY:
+ switch (operand) {
+ case Opcodes.T_BOOLEAN:
+ newarray(Type.BOOLEAN_TYPE);
+ break;
+ case Opcodes.T_CHAR:
+ newarray(Type.CHAR_TYPE);
+ break;
+ case Opcodes.T_BYTE:
+ newarray(Type.BYTE_TYPE);
+ break;
+ case Opcodes.T_SHORT:
+ newarray(Type.SHORT_TYPE);
+ break;
+ case Opcodes.T_INT:
+ newarray(Type.INT_TYPE);
+ break;
+ case Opcodes.T_FLOAT:
+ newarray(Type.FLOAT_TYPE);
+ break;
+ case Opcodes.T_LONG:
+ newarray(Type.LONG_TYPE);
+ break;
+ case Opcodes.T_DOUBLE:
+ newarray(Type.DOUBLE_TYPE);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ switch (opcode) {
+ case Opcodes.ILOAD:
+ load(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LLOAD:
+ load(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FLOAD:
+ load(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DLOAD:
+ load(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ALOAD:
+ load(var, OBJECT_TYPE);
+ break;
+ case Opcodes.ISTORE:
+ store(var, Type.INT_TYPE);
+ break;
+ case Opcodes.LSTORE:
+ store(var, Type.LONG_TYPE);
+ break;
+ case Opcodes.FSTORE:
+ store(var, Type.FLOAT_TYPE);
+ break;
+ case Opcodes.DSTORE:
+ store(var, Type.DOUBLE_TYPE);
+ break;
+ case Opcodes.ASTORE:
+ store(var, OBJECT_TYPE);
+ break;
+ case Opcodes.RET:
+ ret(var);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ Type t = Type.getObjectType(type);
+ switch (opcode) {
+ case Opcodes.NEW:
+ anew(t);
+ break;
+ case Opcodes.ANEWARRAY:
+ newarray(t);
+ break;
+ case Opcodes.CHECKCAST:
+ checkcast(t);
+ break;
+ case Opcodes.INSTANCEOF:
+ instanceOf(t);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ getstatic(owner, name, desc);
+ break;
+ case Opcodes.PUTSTATIC:
+ putstatic(owner, name, desc);
+ break;
+ case Opcodes.GETFIELD:
+ getfield(owner, name, desc);
+ break;
+ case Opcodes.PUTFIELD:
+ putfield(owner, name, desc);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @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(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ switch (opcode) {
+ case Opcodes.INVOKESPECIAL:
+ invokespecial(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ invokevirtual(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKESTATIC:
+ invokestatic(owner, name, desc, itf);
+ break;
+ case Opcodes.INVOKEINTERFACE:
+ invokeinterface(owner, name, desc);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ invokedynamic(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ switch (opcode) {
+ case Opcodes.IFEQ:
+ ifeq(label);
+ break;
+ case Opcodes.IFNE:
+ ifne(label);
+ break;
+ case Opcodes.IFLT:
+ iflt(label);
+ break;
+ case Opcodes.IFGE:
+ ifge(label);
+ break;
+ case Opcodes.IFGT:
+ ifgt(label);
+ break;
+ case Opcodes.IFLE:
+ ifle(label);
+ break;
+ case Opcodes.IF_ICMPEQ:
+ ificmpeq(label);
+ break;
+ case Opcodes.IF_ICMPNE:
+ ificmpne(label);
+ break;
+ case Opcodes.IF_ICMPLT:
+ ificmplt(label);
+ break;
+ case Opcodes.IF_ICMPGE:
+ ificmpge(label);
+ break;
+ case Opcodes.IF_ICMPGT:
+ ificmpgt(label);
+ break;
+ case Opcodes.IF_ICMPLE:
+ ificmple(label);
+ break;
+ case Opcodes.IF_ACMPEQ:
+ ifacmpeq(label);
+ break;
+ case Opcodes.IF_ACMPNE:
+ ifacmpne(label);
+ break;
+ case Opcodes.GOTO:
+ goTo(label);
+ break;
+ case Opcodes.JSR:
+ jsr(label);
+ break;
+ case Opcodes.IFNULL:
+ ifnull(label);
+ break;
+ case Opcodes.IFNONNULL:
+ ifnonnull(label);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ mark(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Byte) {
+ int val = ((Byte) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Character) {
+ int val = ((Character) cst).charValue();
+ iconst(val);
+ } else if (cst instanceof Short) {
+ int val = ((Short) cst).intValue();
+ iconst(val);
+ } else if (cst instanceof Boolean) {
+ int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+ iconst(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ fconst(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ lconst(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ dconst(val);
+ } else if (cst instanceof String) {
+ aconst(cst);
+ } else if (cst instanceof Type) {
+ tconst((Type) cst);
+ } else if (cst instanceof Handle) {
+ hconst((Handle) cst);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ iinc(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ tableswitch(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ lookupswitch(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ multianewarray(desc, dims);
+ }
+
+ // -----------------------------------------------------------------------
+
+ public void nop() {
+ mv.visitInsn(Opcodes.NOP);
+ }
+
+ public void aconst(final Object cst) {
+ if (cst == null) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ public void iconst(final int cst) {
+ if (cst >= -1 && cst <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + cst);
+ } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.BIPUSH, cst);
+ } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Opcodes.SIPUSH, cst);
+ } else {
+ mv.visitLdcInsn(new Integer(cst));
+ }
+ }
+
+ public void lconst(final long cst) {
+ if (cst == 0L || cst == 1L) {
+ mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Long(cst));
+ }
+ }
+
+ public void fconst(final float cst) {
+ int bits = Float.floatToIntBits(cst);
+ if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+ mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Float(cst));
+ }
+ }
+
+ public void dconst(final double cst) {
+ long bits = Double.doubleToLongBits(cst);
+ if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+ mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
+ } else {
+ mv.visitLdcInsn(new Double(cst));
+ }
+ }
+
+ public void tconst(final Type type) {
+ mv.visitLdcInsn(type);
+ }
+
+ public void hconst(final Handle handle) {
+ mv.visitLdcInsn(handle);
+ }
+
+ public void load(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
+ }
+
+ public void aload(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
+ }
+
+ public void store(final int var, final Type type) {
+ mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
+ }
+
+ public void astore(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
+ }
+
+ public void pop() {
+ mv.visitInsn(Opcodes.POP);
+ }
+
+ public void pop2() {
+ mv.visitInsn(Opcodes.POP2);
+ }
+
+ public void dup() {
+ mv.visitInsn(Opcodes.DUP);
+ }
+
+ public void dup2() {
+ mv.visitInsn(Opcodes.DUP2);
+ }
+
+ public void dupX1() {
+ mv.visitInsn(Opcodes.DUP_X1);
+ }
+
+ public void dupX2() {
+ mv.visitInsn(Opcodes.DUP_X2);
+ }
+
+ public void dup2X1() {
+ mv.visitInsn(Opcodes.DUP2_X1);
+ }
+
+ public void dup2X2() {
+ mv.visitInsn(Opcodes.DUP2_X2);
+ }
+
+ public void swap() {
+ mv.visitInsn(Opcodes.SWAP);
+ }
+
+ public void add(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IADD));
+ }
+
+ public void sub(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISUB));
+ }
+
+ public void mul(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IMUL));
+ }
+
+ public void div(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IDIV));
+ }
+
+ public void rem(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IREM));
+ }
+
+ public void neg(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.INEG));
+ }
+
+ public void shl(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHL));
+ }
+
+ public void shr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.ISHR));
+ }
+
+ public void ushr(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
+ }
+
+ public void and(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IAND));
+ }
+
+ public void or(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IOR));
+ }
+
+ public void xor(final Type type) {
+ mv.visitInsn(type.getOpcode(Opcodes.IXOR));
+ }
+
+ public void iinc(final int var, final int increment) {
+ mv.visitIincInsn(var, increment);
+ }
+
+ public void cast(final Type from, final Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.D2L);
+ } else {
+ mv.visitInsn(Opcodes.D2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.F2L);
+ } else {
+ mv.visitInsn(Opcodes.F2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.L2F);
+ } else {
+ mv.visitInsn(Opcodes.L2I);
+ cast(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Opcodes.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Opcodes.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Opcodes.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Opcodes.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Opcodes.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Opcodes.I2S);
+ }
+ }
+ }
+ }
+
+ public void lcmp() {
+ mv.visitInsn(Opcodes.LCMP);
+ }
+
+ public void cmpl(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
+ }
+
+ public void cmpg(final Type type) {
+ mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
+ }
+
+ public void ifeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFEQ, label);
+ }
+
+ public void ifne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNE, label);
+ }
+
+ public void iflt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLT, label);
+ }
+
+ public void ifge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGE, label);
+ }
+
+ public void ifgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFGT, label);
+ }
+
+ public void ifle(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFLE, label);
+ }
+
+ public void ificmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
+ }
+
+ public void ificmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
+ }
+
+ public void ificmplt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
+ }
+
+ public void ificmpge(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
+ }
+
+ public void ificmpgt(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
+ }
+
+ public void ificmple(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
+ }
+
+ public void ifacmpeq(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
+ }
+
+ public void ifacmpne(final Label label) {
+ mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
+ }
+
+ public void goTo(final Label label) {
+ mv.visitJumpInsn(Opcodes.GOTO, label);
+ }
+
+ public void jsr(final Label label) {
+ mv.visitJumpInsn(Opcodes.JSR, label);
+ }
+
+ public void ret(final int var) {
+ mv.visitVarInsn(Opcodes.RET, var);
+ }
+
+ public void tableswitch(final int min, final int max, final Label dflt,
+ final Label... labels) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void lookupswitch(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void areturn(final Type t) {
+ mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
+ }
+
+ public void getstatic(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
+ }
+
+ public void putstatic(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
+ }
+
+ public void getfield(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
+ }
+
+ public void putfield(final String owner, final String name,
+ final String desc) {
+ mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
+ }
+
+ @Deprecated
+ public void invokevirtual(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokevirtual(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
+ }
+
+ public void invokevirtual(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKEVIRTUAL on interfaces require ASM 5");
+ }
+ invokevirtual(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
+ }
+
+ @Deprecated
+ public void invokespecial(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokespecial(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
+ }
+
+ public void invokespecial(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL on interfaces require ASM 5");
+ }
+ invokespecial(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
+ }
+
+ @Deprecated
+ public void invokestatic(final String owner, final String name,
+ final String desc) {
+ if (api >= Opcodes.ASM5) {
+ invokestatic(owner, name, desc, false);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
+ }
+
+ public void invokestatic(final String owner, final String name,
+ final String desc, final boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf) {
+ throw new IllegalArgumentException(
+ "INVOKESTATIC on interfaces require ASM 5");
+ }
+ invokestatic(owner, name, desc);
+ return;
+ }
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
+ }
+
+ public void invokeinterface(final String owner, final String name,
+ final String desc) {
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
+ }
+
+ public void invokedynamic(String name, String desc, Handle bsm,
+ Object[] bsmArgs) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ public void anew(final Type type) {
+ mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
+ }
+
+ public void newarray(final Type type) {
+ int typ;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ typ = Opcodes.T_BOOLEAN;
+ break;
+ case Type.CHAR:
+ typ = Opcodes.T_CHAR;
+ break;
+ case Type.BYTE:
+ typ = Opcodes.T_BYTE;
+ break;
+ case Type.SHORT:
+ typ = Opcodes.T_SHORT;
+ break;
+ case Type.INT:
+ typ = Opcodes.T_INT;
+ break;
+ case Type.FLOAT:
+ typ = Opcodes.T_FLOAT;
+ break;
+ case Type.LONG:
+ typ = Opcodes.T_LONG;
+ break;
+ case Type.DOUBLE:
+ typ = Opcodes.T_DOUBLE;
+ break;
+ default:
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
+ return;
+ }
+ mv.visitIntInsn(Opcodes.NEWARRAY, typ);
+ }
+
+ public void arraylength() {
+ mv.visitInsn(Opcodes.ARRAYLENGTH);
+ }
+
+ public void athrow() {
+ mv.visitInsn(Opcodes.ATHROW);
+ }
+
+ public void checkcast(final Type type) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
+ }
+
+ public void instanceOf(final Type type) {
+ mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
+ }
+
+ public void monitorenter() {
+ mv.visitInsn(Opcodes.MONITORENTER);
+ }
+
+ public void monitorexit() {
+ mv.visitInsn(Opcodes.MONITOREXIT);
+ }
+
+ public void multianewarray(final String desc, final int dims) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public void ifnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNULL, label);
+ }
+
+ public void ifnonnull(final Label label) {
+ mv.visitJumpInsn(Opcodes.IFNONNULL, label);
+ }
+
+ public void mark(final Label label) {
+ mv.visitLabel(label);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
index 21f1d68..08e1f3c 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/JSRInlinerAdapter.java
@@ -29,32 +29,47 @@
*/
package org.apache.tapestry5.internal.plastic.asm.commons;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.Type;
-import org.apache.tapestry5.internal.plastic.asm.tree.*;
-
-import java.util.*;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LocalVariableNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
/**
* A {@link org.apache.tapestry5.internal.plastic.asm.MethodVisitor} that removes JSR instructions and
* inlines the referenced subroutines.
- *
+ *
* <b>Explanation of how it works</b> TODO
- *
+ *
* @author Niko Matsakis
*/
-public class JSRInlinerAdapter extends MethodNode implements Opcodes
-{
+public class JSRInlinerAdapter extends MethodNode implements Opcodes {
private static final boolean LOGGING = false;
/**
- * For each label that is jumped to by a JSR, we create a BitSet
- * instance.
+ * For each label that is jumped to by a JSR, we create a BitSet instance.
*/
- private final Map<LabelNode,BitSet> subroutineHeads = new HashMap<LabelNode,BitSet>();
+ private final Map<LabelNode, BitSet> subroutineHeads = new HashMap<LabelNode, BitSet>();
/**
* This subroutine instance denotes the line of execution that is not
@@ -72,58 +87,65 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Creates a new JSRInliner. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
- * {@link #JSRInlinerAdapter(int, org.apache.tapestry5.internal.plastic.asm.MethodVisitor, int, String, String, String, String[])}
+ * {@link #JSRInlinerAdapter(int, MethodVisitor, int, String, String, String, String[])}
* version.
- *
- * @param mv the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param mv
+ * the <code>MethodVisitor</code> to send the resulting inlined
+ * method code to (use <code>null</code> for none).
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public JSRInlinerAdapter(
- final MethodVisitor mv,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- this(Opcodes.ASM4, mv, access, name, desc, signature, exceptions);
+ public JSRInlinerAdapter(final MethodVisitor mv, final int access,
+ final String name, final String desc, final String signature,
+ final String[] exceptions) {
+ this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions);
+ if (getClass() != JSRInlinerAdapter.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Creates a new JSRInliner.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param mv the <code>MethodVisitor</code> to send the resulting inlined
- * method code to (use <code>null</code> for none).
- * @param access the method's access flags (see {@link Opcodes}). This
- * parameter also indicates if the method is synthetic and/or
- * deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type}).
- * @param signature the method's signature. May be <tt>null</tt>.
- * @param exceptions the internal names of the method's exception classes
- * (see {@link Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the <code>MethodVisitor</code> to send the resulting inlined
+ * method code to (use <code>null</code> for none).
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
- protected JSRInlinerAdapter(
- final int api,
- final MethodVisitor mv,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ protected JSRInlinerAdapter(final int api, final MethodVisitor mv,
+ final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
super(api, access, name, desc, signature, exceptions);
this.mv = mv;
}
@@ -179,9 +201,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
// Go through the head of each subroutine and find any nodes reachable
// to that subroutine without following any JSR links.
- for (Iterator<Map.Entry<LabelNode,BitSet>> it = subroutineHeads.entrySet().iterator(); it.hasNext();)
- {
- Map.Entry<LabelNode,BitSet> entry = it.next();
+ for (Iterator<Map.Entry<LabelNode, BitSet>> it = subroutineHeads
+ .entrySet().iterator(); it.hasNext();) {
+ Map.Entry<LabelNode, BitSet> entry = it.next();
LabelNode lab = entry.getKey();
BitSet sub = entry.getValue();
int index = instructions.indexOf(lab);
@@ -191,24 +213,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Performs a depth first search walking the normal byte code path starting
- * at <code>index</code>, and adding each instruction encountered into
- * the subroutine <code>sub</code>. After this walk is complete, iterates
- * over the exception handlers to ensure that we also include those byte
- * codes which are reachable through an exception that may be thrown during
- * the execution of the subroutine. Invoked from
- * <code>markSubroutines()</code>.
- *
- * @param sub the subroutine whose instructions must be computed.
- * @param index an instruction of this subroutine.
- * @param anyvisited indexes of the already visited instructions, i.e.
- * marked as part of this subroutine or any previously computed
- * subroutine.
+ * at <code>index</code>, and adding each instruction encountered into the
+ * subroutine <code>sub</code>. After this walk is complete, iterates over
+ * the exception handlers to ensure that we also include those byte codes
+ * which are reachable through an exception that may be thrown during the
+ * execution of the subroutine. Invoked from <code>markSubroutines()</code>.
+ *
+ * @param sub
+ * the subroutine whose instructions must be computed.
+ * @param index
+ * an instruction of this subroutine.
+ * @param anyvisited
+ * indexes of the already visited instructions, i.e. marked as
+ * part of this subroutine or any previously computed subroutine.
*/
- private void markSubroutineWalk(
- final BitSet sub,
- final int index,
- final BitSet anyvisited)
- {
+ private void markSubroutineWalk(final BitSet sub, final int index,
+ final BitSet anyvisited) {
if (LOGGING) {
log("markSubroutineWalk: sub=" + sub + " index=" + index);
}
@@ -220,7 +240,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
boolean loop = true;
while (loop) {
loop = false;
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+ for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+ .hasNext();) {
TryCatchBlockNode trycatch = it.next();
if (LOGGING) {
@@ -252,20 +273,19 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Performs a simple DFS of the instructions, assigning each to the
- * subroutine <code>sub</code>. Starts from <code>index</code>.
- * Invoked only by <code>markSubroutineWalk()</code>.
- *
- * @param sub the subroutine whose instructions must be computed.
- * @param index an instruction of this subroutine.
- * @param anyvisited indexes of the already visited instructions, i.e.
- * marked as part of this subroutine or any previously computed
- * subroutine.
+ * subroutine <code>sub</code>. Starts from <code>index</code>. Invoked only
+ * by <code>markSubroutineWalk()</code>.
+ *
+ * @param sub
+ * the subroutine whose instructions must be computed.
+ * @param index
+ * an instruction of this subroutine.
+ * @param anyvisited
+ * indexes of the already visited instructions, i.e. marked as
+ * part of this subroutine or any previously computed subroutine.
*/
- private void markSubroutineWalkDFS(
- final BitSet sub,
- int index,
- final BitSet anyvisited)
- {
+ private void markSubroutineWalkDFS(final BitSet sub, int index,
+ final BitSet anyvisited) {
while (true) {
AbstractInsnNode node = instructions.get(index);
@@ -285,8 +305,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
anyvisited.set(index);
if (node.getType() == AbstractInsnNode.JUMP_INSN
- && node.getOpcode() != JSR)
- {
+ && node.getOpcode() != JSR) {
// we do not follow recursively called subroutines here; but any
// other sort of branch we do follow
JumpInsnNode jnode = (JumpInsnNode) node;
@@ -317,27 +336,38 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
// check to see if this opcode falls through to the next instruction
// or not; if not, return.
switch (instructions.get(index).getOpcode()) {
- case GOTO:
- case RET:
- case TABLESWITCH:
- case LOOKUPSWITCH:
- case IRETURN:
- case LRETURN:
- case FRETURN:
- case DRETURN:
- case ARETURN:
- case RETURN:
- case ATHROW:
- /*
- * note: this either returns from this subroutine, or a
- * parent subroutine which invoked it
- */
- return;
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ /*
+ * note: this either returns from this subroutine, or a parent
+ * subroutine which invoked it
+ */
+ return;
}
// Use tail recursion here in the form of an outer while loop to
// avoid our stack growing needlessly:
index++;
+
+ // We implicitly assumed above that execution can always fall
+ // through to the next instruction after a JSR. But a subroutine may
+ // never return, in which case the code after the JSR is unreachable
+ // and can be anything. In particular, it can seem to fall off the
+ // end of the method, so we must handle this case here (we could
+ // instead detect whether execution can return or not from a JSR,
+ // but this is more complicated).
+ if (index >= instructions.size()) {
+ return;
+ }
}
}
@@ -358,10 +388,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>();
while (!worklist.isEmpty()) {
Instantiation inst = worklist.removeFirst();
- emitSubroutine(inst,
- worklist,
- newInstructions,
- newTryCatchBlocks,
+ emitSubroutine(inst, worklist, newInstructions, newTryCatchBlocks,
newLocalVariables);
}
instructions = newInstructions;
@@ -371,24 +398,25 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
/**
* Emits one instantiation of one subroutine, specified by
- * <code>instant</code>. May add new instantiations that are invoked by
- * this one to the <code>worklist</code> parameter, and new try/catch
- * blocks to <code>newTryCatchBlocks</code>.
- *
- * @param instant the instantiation that must be performed.
- * @param worklist list of the instantiations that remain to be done.
- * @param newInstructions the instruction list to which the instantiated
- * code must be appended.
- * @param newTryCatchBlocks the exception handler list to which the
- * instantiated handlers must be appended.
+ * <code>instant</code>. May add new instantiations that are invoked by this
+ * one to the <code>worklist</code> parameter, and new try/catch blocks to
+ * <code>newTryCatchBlocks</code>.
+ *
+ * @param instant
+ * the instantiation that must be performed.
+ * @param worklist
+ * list of the instantiations that remain to be done.
+ * @param newInstructions
+ * the instruction list to which the instantiated code must be
+ * appended.
+ * @param newTryCatchBlocks
+ * the exception handler list to which the instantiated handlers
+ * must be appended.
*/
- private void emitSubroutine(
- final Instantiation instant,
- final List<Instantiation> worklist,
- final InsnList newInstructions,
- final List<TryCatchBlockNode> newTryCatchBlocks,
- final List<LocalVariableNode> newLocalVariables)
- {
+ private void emitSubroutine(final Instantiation instant,
+ final List<Instantiation> worklist, final InsnList newInstructions,
+ final List<TryCatchBlockNode> newTryCatchBlocks,
+ final List<LocalVariableNode> newLocalVariables) {
LabelNode duplbl = null;
if (LOGGING) {
@@ -485,7 +513,8 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
}
// Emit try/catch blocks that are relevant to this method.
- for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it.hasNext();) {
+ for (Iterator<TryCatchBlockNode> it = tryCatchBlocks.iterator(); it
+ .hasNext();) {
TryCatchBlockNode trycatch = it.next();
if (LOGGING) {
@@ -517,13 +546,12 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
throw new RuntimeException("Internal error!");
}
- newTryCatchBlocks.add(new TryCatchBlockNode(start,
- end,
- handler,
+ newTryCatchBlocks.add(new TryCatchBlockNode(start, end, handler,
trycatch.type));
}
- for (Iterator<LocalVariableNode> it = localVariables.iterator(); it.hasNext();) {
+ for (Iterator<LocalVariableNode> it = localVariables.iterator(); it
+ .hasNext();) {
LocalVariableNode lvnode = it.next();
if (LOGGING) {
log("local var " + lvnode.name);
@@ -537,11 +565,7 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
continue;
}
newLocalVariables.add(new LocalVariableNode(lvnode.name,
- lvnode.desc,
- lvnode.signature,
- start,
- end,
- lvnode.index));
+ lvnode.desc, lvnode.signature, start, end, lvnode.index));
}
}
@@ -574,14 +598,14 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* This table maps Labels from the original source to Labels pointing at
* code specific to this instantiation, for use in remapping try/catch
* blocks,as well as gotos.
- *
+ *
* Note that in the presence of dual citizens instructions, that is,
* instructions which belong to more than one subroutine due to the
* merging of control flow without a RET instruction, we will map the
* target label of a GOTO to the label used by the instantiation lowest
* on the stack. This avoids code duplication during inlining in most
* cases.
- *
+ *
* @see #findOwner(int)
*/
public final Map<LabelNode, LabelNode> rangeTable = new HashMap<LabelNode, LabelNode>();
@@ -644,21 +668,22 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* Returns the "owner" of a particular instruction relative to this
* instantiation: the owner referes to the Instantiation which will emit
* the version of this instruction that we will execute.
- *
+ *
* Typically, the return value is either <code>this</code> or
* <code>null</code>. <code>this</code> indicates that this
* instantiation will generate the version of this instruction that we
- * will execute, and <code>null</code> indicates that this
- * instantiation never executes the given instruction.
- *
+ * will execute, and <code>null</code> indicates that this instantiation
+ * never executes the given instruction.
+ *
* Sometimes, however, an instruction can belong to multiple
* subroutines; this is called a "dual citizen" instruction (though it
* may belong to more than 2 subroutines), and occurs when multiple
* subroutines branch to common points of control. In this case, the
* owner is the subroutine that appears lowest on the stack, and which
* also owns the instruction in question.
- *
- * @param i the index of the instruction in the original code
+ *
+ * @param i
+ * the index of the instruction in the original code
* @return the "owner" of a particular instruction relative to this
* instantiation.
*/
@@ -679,12 +704,13 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
}
/**
- * Looks up the label <code>l</code> in the <code>gotoTable</code>,
- * thus translating it from a Label in the original code, to a Label in
- * the inlined code that is appropriate for use by an instruction that
+ * Looks up the label <code>l</code> in the <code>gotoTable</code>, thus
+ * translating it from a Label in the original code, to a Label in the
+ * inlined code that is appropriate for use by an instruction that
* branched to the original label.
- *
- * @param l The label we will be translating
+ *
+ * @param l
+ * The label we will be translating
* @return a label for use by a branch instruction in the inlined code
* @see #rangeLabel
*/
@@ -700,8 +726,9 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes
* thus translating it from a Label in the original code, to a Label in
* the inlined code that is appropriate for use by an try/catch or
* variable use annotation.
- *
- * @param l The label we will be translating
+ *
+ * @param l
+ * The label we will be translating
* @return a label for use by a try/catch or variable annotation in the
* original code
* @see #rangeTable
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
new file mode 100644
index 0000000..3a21047
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/LocalVariablesSorter.java
@@ -0,0 +1,381 @@
+/***
+ * 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.commons;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+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 MethodVisitor} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ *
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodVisitor {
+
+ private static final Type OBJECT_TYPE = Type
+ .getObjectType("java/lang/Object");
+
+ /**
+ * Mapping from old to new local variable indexes. A local variable at index
+ * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+ * index i of size 2 is remapped to 'mapping[2*i+1]'.
+ */
+ private int[] mapping = new int[40];
+
+ /**
+ * Array used to store stack map local variable types after remapping.
+ */
+ private Object[] newLocals = new Object[20];
+
+ /**
+ * Index of the first local variable, after formal parameters.
+ */
+ protected final int firstLocal;
+
+ /**
+ * Index of the next local variable to be created by {@link #newLocal}.
+ */
+ protected int nextLocal;
+
+ /**
+ * Indicates if at least one local variable has moved due to remapping.
+ */
+ private boolean changed;
+
+ /**
+ * Creates a new {@link LocalVariablesSorter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #LocalVariablesSorter(int, int, String, MethodVisitor)} version.
+ *
+ * @param access
+ * access flags of the adapted method.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public LocalVariablesSorter(final int access, final String desc,
+ final MethodVisitor mv) {
+ this(Opcodes.ASM5, access, desc, mv);
+ if (getClass() != LocalVariablesSorter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Creates a new {@link LocalVariablesSorter}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * access flags of the adapted method.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param mv
+ * the method visitor to which this adapter delegates calls.
+ */
+ protected LocalVariablesSorter(final int api, final int access,
+ final String desc, final MethodVisitor mv) {
+ super(api, mv);
+ Type[] args = Type.getArgumentTypes(desc);
+ nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+ for (int i = 0; i < args.length; i++) {
+ nextLocal += args[i].getSize();
+ }
+ firstLocal = nextLocal;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ Type type;
+ switch (opcode) {
+ case Opcodes.LLOAD:
+ case Opcodes.LSTORE:
+ type = Type.LONG_TYPE;
+ break;
+
+ case Opcodes.DLOAD:
+ case Opcodes.DSTORE:
+ type = Type.DOUBLE_TYPE;
+ break;
+
+ case Opcodes.FLOAD:
+ case Opcodes.FSTORE:
+ type = Type.FLOAT_TYPE;
+ break;
+
+ case Opcodes.ILOAD:
+ case Opcodes.ISTORE:
+ type = Type.INT_TYPE;
+ break;
+
+ default:
+ // case Opcodes.ALOAD:
+ // case Opcodes.ASTORE:
+ // case RET:
+ type = OBJECT_TYPE;
+ break;
+ }
+ mv.visitVarInsn(opcode, remap(var, type));
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ mv.visitMaxs(maxStack, nextLocal);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ int newIndex = remap(index, Type.getType(desc));
+ mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ Type t = Type.getType(desc);
+ int[] newIndex = new int[index.length];
+ for (int i = 0; i < newIndex.length; ++i) {
+ newIndex[i] = remap(index[i], t);
+ }
+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ newIndex, desc, visible);
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (type != Opcodes.F_NEW) { // uncompressed frame
+ throw new IllegalStateException(
+ "ClassReader.accept() should be called with EXPAND_FRAMES flag");
+ }
+
+ if (!changed) { // optimization for the case where mapping = identity
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ return;
+ }
+
+ // creates a copy of newLocals
+ Object[] oldLocals = new Object[newLocals.length];
+ System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+ updateNewLocals(newLocals);
+
+ // copies types from 'local' to 'newLocals'
+ // 'newLocals' already contains the variables added with 'newLocal'
+
+ int index = 0; // old local variable index
+ int number = 0; // old local variable number
+ for (; number < nLocal; ++number) {
+ Object t = local[number];
+ int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+ if (t != Opcodes.TOP) {
+ Type typ = OBJECT_TYPE;
+ if (t == Opcodes.INTEGER) {
+ typ = Type.INT_TYPE;
+ } else if (t == Opcodes.FLOAT) {
+ typ = Type.FLOAT_TYPE;
+ } else if (t == Opcodes.LONG) {
+ typ = Type.LONG_TYPE;
+ } else if (t == Opcodes.DOUBLE) {
+ typ = Type.DOUBLE_TYPE;
+ } else if (t instanceof String) {
+ typ = Type.getObjectType((String) t);
+ }
+ setFrameLocal(remap(index, typ), t);
+ }
+ index += size;
+ }
+
+ // removes TOP after long and double types as well as trailing TOPs
+
+ index = 0;
+ number = 0;
+ for (int i = 0; index < newLocals.length; ++i) {
+ Object t = newLocals[index++];
+ if (t != null && t != Opcodes.TOP) {
+ newLocals[i] = t;
+ number = i + 1;
+ if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+ index += 1;
+ }
+ } else {
+ newLocals[i] = Opcodes.TOP;
+ }
+ }
+
+ // visits remapped frame
+ mv.visitFrame(type, number, newLocals, nStack, stack);
+
+ // restores original value of 'newLocals'
+ newLocals = oldLocals;
+ }
+
+ // -------------
+
+ /**
+ * Creates a new local variable of the given type.
+ *
+ * @param type
+ * the type of the local variable to be created.
+ * @return the identifier of the newly created local variable.
+ */
+ public int newLocal(final Type type) {
+ Object t;
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ t = Opcodes.INTEGER;
+ break;
+ case Type.FLOAT:
+ t = Opcodes.FLOAT;
+ break;
+ case Type.LONG:
+ t = Opcodes.LONG;
+ break;
+ case Type.DOUBLE:
+ t = Opcodes.DOUBLE;
+ break;
+ case Type.ARRAY:
+ t = type.getDescriptor();
+ break;
+ // case Type.OBJECT:
+ default:
+ t = type.getInternalName();
+ break;
+ }
+ int local = newLocalMapping(type);
+ setLocalType(local, type);
+ setFrameLocal(local, t);
+ changed = true;
+ return local;
+ }
+
+ /**
+ * Notifies subclasses that a new stack map frame is being visited. The
+ * array argument contains the stack map frame types corresponding to the
+ * local variables added with {@link #newLocal}. This method can update
+ * these types in place for the stack map frame being visited. The default
+ * implementation of this method does nothing, i.e. a local variable added
+ * with {@link #newLocal} will have the same type in all stack map frames.
+ * But this behavior is not always the desired one, for instance if a local
+ * variable is added in the middle of a try/catch block: the frame for the
+ * exception handler should have a TOP type for this new local.
+ *
+ * @param newLocals
+ * the stack map frame types corresponding to the local variables
+ * added with {@link #newLocal} (and null for the others). The
+ * format of this array is the same as in
+ * {@link MethodVisitor#visitFrame}, except that long and double
+ * types use two slots. The types for the current stack map frame
+ * must be updated in place in this array.
+ */
+ protected void updateNewLocals(Object[] newLocals) {
+ }
+
+ /**
+ * Notifies subclasses that a local variable has been added or remapped. The
+ * default implementation of this method does nothing.
+ *
+ * @param local
+ * a local variable identifier, as returned by {@link #newLocal
+ * newLocal()}.
+ * @param type
+ * the type of the value being stored in the local variable.
+ */
+ protected void setLocalType(final int local, final Type type) {
+ }
+
+ private void setFrameLocal(final int local, final Object type) {
+ int l = newLocals.length;
+ if (local >= l) {
+ Object[] a = new Object[Math.max(2 * l, local + 1)];
+ System.arraycopy(newLocals, 0, a, 0, l);
+ newLocals = a;
+ }
+ newLocals[local] = type;
+ }
+
+ private int remap(final int var, final Type type) {
+ if (var + type.getSize() <= firstLocal) {
+ return var;
+ }
+ int key = 2 * var + type.getSize() - 1;
+ int size = mapping.length;
+ if (key >= size) {
+ int[] newMapping = new int[Math.max(2 * size, key + 1)];
+ System.arraycopy(mapping, 0, newMapping, 0, size);
+ mapping = newMapping;
+ }
+ int value = mapping[key];
+ if (value == 0) {
+ value = newLocalMapping(type);
+ setLocalType(value, type);
+ mapping[key] = value + 1;
+ } else {
+ value--;
+ }
+ if (value != var) {
+ changed = true;
+ }
+ return value;
+ }
+
+ protected int newLocalMapping(final Type type) {
+ int local = nextLocal;
+ nextLocal += type.getSize();
+ return local;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
new file mode 100644
index 0000000..73c3e96
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/commons/Method.java
@@ -0,0 +1,282 @@
+/***
+ * 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.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A named method descriptor.
+ *
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+ /**
+ * The method name.
+ */
+ private final String name;
+
+ /**
+ * The method descriptor.
+ */
+ private final String desc;
+
+ /**
+ * Maps primitive Java type names to their descriptors.
+ */
+ private static final Map<String, String> DESCRIPTORS;
+
+ static {
+ DESCRIPTORS = new HashMap<String, String>();
+ DESCRIPTORS.put("void", "V");
+ DESCRIPTORS.put("byte", "B");
+ DESCRIPTORS.put("char", "C");
+ DESCRIPTORS.put("double", "D");
+ DESCRIPTORS.put("float", "F");
+ DESCRIPTORS.put("int", "I");
+ DESCRIPTORS.put("long", "J");
+ DESCRIPTORS.put("short", "S");
+ DESCRIPTORS.put("boolean", "Z");
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ */
+ public Method(final String name, final String desc) {
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param name
+ * the method's name.
+ * @param returnType
+ * the method's return type.
+ * @param argumentTypes
+ * the method's argument types.
+ */
+ public Method(final String name, final Type returnType,
+ final Type[] argumentTypes) {
+ this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param m
+ * a java.lang.reflect method descriptor
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ */
+ public static Method getMethod(java.lang.reflect.Method m) {
+ return new Method(m.getName(), Type.getMethodDescriptor(m));
+ }
+
+ /**
+ * Creates a new {@link Method}.
+ *
+ * @param c
+ * a java.lang.reflect constructor descriptor
+ * @return a {@link Method} corresponding to the given Java constructor
+ * declaration.
+ */
+ public static Method getMethod(java.lang.reflect.Constructor<?> c) {
+ return new Method("<init>", Type.getConstructorDescriptor(c));
+ }
+
+ /**
+ * Returns a {@link Method} corresponding to the given Java method
+ * declaration.
+ *
+ * @param method
+ * a Java method declaration, without argument names, of the form
+ * "returnType name (argumentType1, ... argumentTypeN)", where
+ * the types are in plain Java (e.g. "int", "float",
+ * "java.util.List", ...). Classes of the java.lang package can
+ * be specified by their unqualified name; all other classes
+ * names must be fully qualified.
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ * @throws IllegalArgumentException
+ * if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method)
+ throws IllegalArgumentException {
+ return getMethod(method, false);
+ }
+
+ /**
+ * Returns a {@link Method} corresponding to the given Java method
+ * declaration.
+ *
+ * @param method
+ * a Java method declaration, without argument names, of the form
+ * "returnType name (argumentType1, ... argumentTypeN)", where
+ * the types are in plain Java (e.g. "int", "float",
+ * "java.util.List", ...). Classes of the java.lang package may
+ * be specified by their unqualified name, depending on the
+ * defaultPackage argument; all other classes names must be fully
+ * qualified.
+ * @param defaultPackage
+ * true if unqualified class names belong to the default package,
+ * or false if they correspond to java.lang classes. For instance
+ * "Object" means "Object" if this option is true, or
+ * "java.lang.Object" otherwise.
+ * @return a {@link Method} corresponding to the given Java method
+ * declaration.
+ * @throws IllegalArgumentException
+ * if <code>method</code> could not get parsed.
+ */
+ public static Method getMethod(final String method,
+ final boolean defaultPackage) throws IllegalArgumentException {
+ int space = method.indexOf(' ');
+ int start = method.indexOf('(', space) + 1;
+ int end = method.indexOf(')', start);
+ if (space == -1 || start == -1 || end == -1) {
+ throw new IllegalArgumentException();
+ }
+ String returnType = method.substring(0, space);
+ String methodName = method.substring(space + 1, start - 1).trim();
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ int p;
+ do {
+ String s;
+ p = method.indexOf(',', start);
+ if (p == -1) {
+ s = map(method.substring(start, end).trim(), defaultPackage);
+ } else {
+ s = map(method.substring(start, p).trim(), defaultPackage);
+ start = p + 1;
+ }
+ sb.append(s);
+ } while (p != -1);
+ sb.append(')');
+ sb.append(map(returnType, defaultPackage));
+ return new Method(methodName, sb.toString());
+ }
+
+ private static String map(final String type, final boolean defaultPackage) {
+ if ("".equals(type)) {
+ return type;
+ }
+
+ StringBuffer sb = new StringBuffer();
+ int index = 0;
+ while ((index = type.indexOf("[]", index) + 1) > 0) {
+ sb.append('[');
+ }
+
+ String t = type.substring(0, type.length() - sb.length() * 2);
+ String desc = DESCRIPTORS.get(t);
+ if (desc != null) {
+ sb.append(desc);
+ } else {
+ sb.append('L');
+ if (t.indexOf('.') < 0) {
+ if (!defaultPackage) {
+ sb.append("java/lang/");
+ }
+ sb.append(t);
+ } else {
+ sb.append(t.replace('.', '/'));
+ }
+ sb.append(';');
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns the name of the method described by this object.
+ *
+ * @return the name of the method described by this object.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the descriptor of the method described by this object.
+ *
+ * @return the descriptor of the method described by this object.
+ */
+ public String getDescriptor() {
+ return desc;
+ }
+
+ /**
+ * Returns the return type of the method described by this object.
+ *
+ * @return the return type of the method described by this object.
+ */
+ public Type getReturnType() {
+ return Type.getReturnType(desc);
+ }
+
+ /**
+ * Returns the argument types of the method described by this object.
+ *
+ * @return the argument types of the method described by this object.
+ */
+ public Type[] getArgumentTypes() {
+ return Type.getArgumentTypes(desc);
+ }
+
+ @Override
+ public String toString() {
+ return name + desc;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (!(o instanceof Method)) {
+ return false;
+ }
+ Method other = (Method) o;
+ return name.equals(other.name) && desc.equals(other.desc);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode() ^ desc.hashCode();
+ }
+}
\ No newline at end of file
[03/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
index 0d7fe3f..859a8d1 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceMethodVisitor.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,12 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.util;
-import org.apache.tapestry5.internal.plastic.asm.*;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
/**
* A {@link MethodVisitor} that prints the methods it visits with a
* {@link Printer}.
- *
+ *
* @author Eric Bruneton
*/
public final class TraceMethodVisitor extends MethodVisitor {
@@ -47,15 +52,19 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
- super(Opcodes.ASM4, mv);
+ super(Opcodes.ASM5, mv);
this.p = p;
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public void visitParameter(String name, int access) {
+ p.visitParameter(name, access);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
Printer p = this.p.visitMethodAnnotation(desc, visible);
AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
visible);
@@ -63,6 +72,16 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitMethodTypeAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitTypeAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
p.visitMethodAttribute(attr);
super.visitAttribute(attr);
@@ -76,17 +95,11 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
- Printer p = this.p.visitParameterAnnotation(parameter,
- desc,
- visible);
- AnnotationVisitor av = mv == null
- ? null
- : mv.visitParameterAnnotation(parameter, desc, visible);
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ Printer p = this.p.visitParameterAnnotation(parameter, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitParameterAnnotation(
+ parameter, desc, visible);
return new TraceAnnotationVisitor(av, p);
}
@@ -97,13 +110,8 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
p.visitFrame(type, nLocal, local, nStack, stack);
super.visitFrame(type, nLocal, local, nStack, stack);
}
@@ -133,34 +141,42 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
p.visitFieldInsn(opcode, owner, name, desc);
super.visitFieldInsn(opcode, owner, name, desc);
}
+ @Deprecated
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
p.visitMethodInsn(opcode, owner, name, desc);
- super.visitMethodInsn(opcode, owner, name, desc);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ p.visitMethodInsn(opcode, owner, name, desc, itf);
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
@@ -190,22 +206,15 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
p.visitTableSwitchInsn(min, max, dflt, labels);
super.visitTableSwitchInsn(min, max, dflt, labels);
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
p.visitLookupSwitchInsn(dflt, keys, labels);
super.visitLookupSwitchInsn(dflt, keys, labels);
}
@@ -217,30 +226,53 @@ public final class TraceMethodVisitor extends MethodVisitor {
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p
+ .visitInsnAnnotation(typeRef, typePath, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitInsnAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
p.visitTryCatchBlock(start, end, handler, type);
super.visitTryCatchBlock(start, end, handler, type);
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ Printer p = this.p.visitTryCatchAnnotation(typeRef, typePath, desc,
+ visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitTryCatchAnnotation(
+ typeRef, typePath, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
p.visitLocalVariable(name, desc, signature, start, end, index);
super.visitLocalVariable(name, desc, signature, start, end, index);
}
@Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ Printer p = this.p.visitLocalVariableAnnotation(typeRef, typePath,
+ start, end, index, desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv
+ .visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
public void visitLineNumber(final int line, final Label start) {
p.visitLineNumber(line, start);
super.visitLineNumber(line, start);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
index 3b0a178..1e2c9a3 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/TraceSignatureVisitor.java
@@ -33,14 +33,13 @@ import org.apache.tapestry5.internal.plastic.asm.Opcodes;
import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
/**
- * A {@link org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor} that prints a disassembled view of the signature
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
* it visits.
- *
+ *
* @author Eugene Kuleshov
* @author Eric Bruneton
*/
-public final class TraceSignatureVisitor extends SignatureVisitor
-{
+public final class TraceSignatureVisitor extends SignatureVisitor {
private final StringBuffer declaration;
@@ -76,13 +75,13 @@ public final class TraceSignatureVisitor extends SignatureVisitor
private String separator = "";
public TraceSignatureVisitor(final int access) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
this.declaration = new StringBuffer();
}
private TraceSignatureVisitor(final StringBuffer buf) {
- super(Opcodes.ASM4);
+ super(Opcodes.ASM5);
this.declaration = buf;
}
@@ -118,8 +117,7 @@ public final class TraceSignatureVisitor extends SignatureVisitor
@Override
public SignatureVisitor visitInterface() {
- separator = seenInterface ? ", " : isInterface
- ? " extends "
+ separator = seenInterface ? ", " : isInterface ? " extends "
: " implements ";
seenInterface = true;
startType();
@@ -166,34 +164,34 @@ public final class TraceSignatureVisitor extends SignatureVisitor
@Override
public void visitBaseType(final char descriptor) {
switch (descriptor) {
- case 'V':
- declaration.append("void");
- break;
- case 'B':
- declaration.append("byte");
- break;
- case 'J':
- declaration.append("long");
- break;
- case 'Z':
- declaration.append("boolean");
- break;
- case 'I':
- declaration.append("int");
- break;
- case 'S':
- declaration.append("short");
- break;
- case 'C':
- declaration.append("char");
- break;
- case 'F':
- declaration.append("float");
- break;
- // case 'D':
- default:
- declaration.append("double");
- break;
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ // case 'D':
+ default:
+ declaration.append("double");
+ break;
}
endType();
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
new file mode 100644
index 0000000..88dab5e
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/xml/ASMContentHandler.java
@@ -0,0 +1,1453 @@
+/***
+ * ASM XML Adapter
+ * Copyright (c) 2004-2011, Eugene Kuleshov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * A {@link org.xml.sax.ContentHandler ContentHandler} that transforms XML
+ * document into Java class file. This class can be feeded by any kind of SAX
+ * 2.0 event producers, e.g. XML parser, XSLT or XPath engines, or custom code.
+ *
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.SAXClassAdapter
+ * @see org.apache.tapestry5.internal.plastic.asm.xml.Processor
+ *
+ * @author Eugene Kuleshov
+ */
+public class ASMContentHandler extends DefaultHandler implements Opcodes {
+
+ /**
+ * Stack of the intermediate processing contexts.
+ */
+ private final ArrayList<Object> stack = new ArrayList<Object>();
+
+ /**
+ * Complete name of the current element.
+ */
+ String match = "";
+
+ /**
+ * Current instance of the {@link ClassVisitor ClassVisitor} used to visit
+ * classfile bytecode.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Map of the active {@link Label Label} instances for current method.
+ */
+ protected Map<Object, Label> labels;
+
+ private static final String BASE = "class";
+
+ private final RuleSet RULES = new RuleSet();
+ {
+ RULES.add(BASE, new ClassRule());
+ RULES.add(BASE + "/interfaces/interface", new InterfaceRule());
+ RULES.add(BASE + "/interfaces", new InterfacesRule());
+ RULES.add(BASE + "/outerclass", new OuterClassRule());
+ RULES.add(BASE + "/innerclass", new InnerClassRule());
+ RULES.add(BASE + "/source", new SourceRule());
+ RULES.add(BASE + "/field", new FieldRule());
+
+ RULES.add(BASE + "/method", new MethodRule());
+ RULES.add(BASE + "/method/exceptions/exception", new ExceptionRule());
+ RULES.add(BASE + "/method/exceptions", new ExceptionsRule());
+
+ RULES.add(BASE + "/method/parameter", new MethodParameterRule());
+ RULES.add(BASE + "/method/annotationDefault",
+ new AnnotationDefaultRule());
+
+ RULES.add(BASE + "/method/code/*", new OpcodesRule()); // opcodes
+
+ RULES.add(BASE + "/method/code/frame", new FrameRule());
+ RULES.add(BASE + "/method/code/frame/local", new FrameTypeRule());
+ RULES.add(BASE + "/method/code/frame/stack", new FrameTypeRule());
+
+ RULES.add(BASE + "/method/code/TABLESWITCH", new TableSwitchRule());
+ RULES.add(BASE + "/method/code/TABLESWITCH/label",
+ new TableSwitchLabelRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH", new LookupSwitchRule());
+ RULES.add(BASE + "/method/code/LOOKUPSWITCH/label",
+ new LookupSwitchLabelRule());
+
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC", new InvokeDynamicRule());
+ RULES.add(BASE + "/method/code/INVOKEDYNAMIC/bsmArg",
+ new InvokeDynamicBsmArgumentsRule());
+
+ RULES.add(BASE + "/method/code/Label", new LabelRule());
+ RULES.add(BASE + "/method/code/TryCatch", new TryCatchRule());
+ RULES.add(BASE + "/method/code/LineNumber", new LineNumberRule());
+ RULES.add(BASE + "/method/code/LocalVar", new LocalVarRule());
+ RULES.add(BASE + "/method/code/Max", new MaxRule());
+
+ RULES.add("*/annotation", new AnnotationRule());
+ RULES.add("*/typeAnnotation", new TypeAnnotationRule());
+ RULES.add("*/parameterAnnotation", new AnnotationParameterRule());
+ RULES.add("*/insnAnnotation", new InsnAnnotationRule());
+ RULES.add("*/tryCatchAnnotation", new TryCatchAnnotationRule());
+ RULES.add("*/localVariableAnnotation",
+ new LocalVariableAnnotationRule());
+ RULES.add("*/annotationValue", new AnnotationValueRule());
+ RULES.add("*/annotationValueAnnotation",
+ new AnnotationValueAnnotationRule());
+ RULES.add("*/annotationValueEnum", new AnnotationValueEnumRule());
+ RULES.add("*/annotationValueArray", new AnnotationValueArrayRule());
+ }
+
+ private static interface OpcodeGroup {
+ public static final int INSN = 0;
+ public static final int INSN_INT = 1;
+ public static final int INSN_VAR = 2;
+ public static final int INSN_TYPE = 3;
+ public static final int INSN_FIELD = 4;
+ public static final int INSN_METHOD = 5;
+ public static final int INSN_JUMP = 6;
+ public static final int INSN_LDC = 7;
+ public static final int INSN_IINC = 8;
+ public static final int INSN_MULTIANEWARRAY = 9;
+ }
+
+ /**
+ * Map of the opcode names to opcode and opcode group
+ */
+ static final HashMap<String, Opcode> OPCODES = new HashMap<String, Opcode>();
+ static {
+ addOpcode("NOP", NOP, OpcodeGroup.INSN);
+ addOpcode("ACONST_NULL", ACONST_NULL, OpcodeGroup.INSN);
+ addOpcode("ICONST_M1", ICONST_M1, OpcodeGroup.INSN);
+ addOpcode("ICONST_0", ICONST_0, OpcodeGroup.INSN);
+ addOpcode("ICONST_1", ICONST_1, OpcodeGroup.INSN);
+ addOpcode("ICONST_2", ICONST_2, OpcodeGroup.INSN);
+ addOpcode("ICONST_3", ICONST_3, OpcodeGroup.INSN);
+ addOpcode("ICONST_4", ICONST_4, OpcodeGroup.INSN);
+ addOpcode("ICONST_5", ICONST_5, OpcodeGroup.INSN);
+ addOpcode("LCONST_0", LCONST_0, OpcodeGroup.INSN);
+ addOpcode("LCONST_1", LCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_0", FCONST_0, OpcodeGroup.INSN);
+ addOpcode("FCONST_1", FCONST_1, OpcodeGroup.INSN);
+ addOpcode("FCONST_2", FCONST_2, OpcodeGroup.INSN);
+ addOpcode("DCONST_0", DCONST_0, OpcodeGroup.INSN);
+ addOpcode("DCONST_1", DCONST_1, OpcodeGroup.INSN);
+ addOpcode("BIPUSH", BIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("SIPUSH", SIPUSH, OpcodeGroup.INSN_INT);
+ addOpcode("LDC", LDC, OpcodeGroup.INSN_LDC);
+ addOpcode("ILOAD", ILOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("LLOAD", LLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("FLOAD", FLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("DLOAD", DLOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("ALOAD", ALOAD, OpcodeGroup.INSN_VAR);
+ addOpcode("IALOAD", IALOAD, OpcodeGroup.INSN);
+ addOpcode("LALOAD", LALOAD, OpcodeGroup.INSN);
+ addOpcode("FALOAD", FALOAD, OpcodeGroup.INSN);
+ addOpcode("DALOAD", DALOAD, OpcodeGroup.INSN);
+ addOpcode("AALOAD", AALOAD, OpcodeGroup.INSN);
+ addOpcode("BALOAD", BALOAD, OpcodeGroup.INSN);
+ addOpcode("CALOAD", CALOAD, OpcodeGroup.INSN);
+ addOpcode("SALOAD", SALOAD, OpcodeGroup.INSN);
+ addOpcode("ISTORE", ISTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("LSTORE", LSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("FSTORE", FSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("DSTORE", DSTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("ASTORE", ASTORE, OpcodeGroup.INSN_VAR);
+ addOpcode("IASTORE", IASTORE, OpcodeGroup.INSN);
+ addOpcode("LASTORE", LASTORE, OpcodeGroup.INSN);
+ addOpcode("FASTORE", FASTORE, OpcodeGroup.INSN);
+ addOpcode("DASTORE", DASTORE, OpcodeGroup.INSN);
+ addOpcode("AASTORE", AASTORE, OpcodeGroup.INSN);
+ addOpcode("BASTORE", BASTORE, OpcodeGroup.INSN);
+ addOpcode("CASTORE", CASTORE, OpcodeGroup.INSN);
+ addOpcode("SASTORE", SASTORE, OpcodeGroup.INSN);
+ addOpcode("POP", POP, OpcodeGroup.INSN);
+ addOpcode("POP2", POP2, OpcodeGroup.INSN);
+ addOpcode("DUP", DUP, OpcodeGroup.INSN);
+ addOpcode("DUP_X1", DUP_X1, OpcodeGroup.INSN);
+ addOpcode("DUP_X2", DUP_X2, OpcodeGroup.INSN);
+ addOpcode("DUP2", DUP2, OpcodeGroup.INSN);
+ addOpcode("DUP2_X1", DUP2_X1, OpcodeGroup.INSN);
+ addOpcode("DUP2_X2", DUP2_X2, OpcodeGroup.INSN);
+ addOpcode("SWAP", SWAP, OpcodeGroup.INSN);
+ addOpcode("IADD", IADD, OpcodeGroup.INSN);
+ addOpcode("LADD", LADD, OpcodeGroup.INSN);
+ addOpcode("FADD", FADD, OpcodeGroup.INSN);
+ addOpcode("DADD", DADD, OpcodeGroup.INSN);
+ addOpcode("ISUB", ISUB, OpcodeGroup.INSN);
+ addOpcode("LSUB", LSUB, OpcodeGroup.INSN);
+ addOpcode("FSUB", FSUB, OpcodeGroup.INSN);
+ addOpcode("DSUB", DSUB, OpcodeGroup.INSN);
+ addOpcode("IMUL", IMUL, OpcodeGroup.INSN);
+ addOpcode("LMUL", LMUL, OpcodeGroup.INSN);
+ addOpcode("FMUL", FMUL, OpcodeGroup.INSN);
+ addOpcode("DMUL", DMUL, OpcodeGroup.INSN);
+ addOpcode("IDIV", IDIV, OpcodeGroup.INSN);
+ addOpcode("LDIV", LDIV, OpcodeGroup.INSN);
+ addOpcode("FDIV", FDIV, OpcodeGroup.INSN);
+ addOpcode("DDIV", DDIV, OpcodeGroup.INSN);
+ addOpcode("IREM", IREM, OpcodeGroup.INSN);
+ addOpcode("LREM", LREM, OpcodeGroup.INSN);
+ addOpcode("FREM", FREM, OpcodeGroup.INSN);
+ addOpcode("DREM", DREM, OpcodeGroup.INSN);
+ addOpcode("INEG", INEG, OpcodeGroup.INSN);
+ addOpcode("LNEG", LNEG, OpcodeGroup.INSN);
+ addOpcode("FNEG", FNEG, OpcodeGroup.INSN);
+ addOpcode("DNEG", DNEG, OpcodeGroup.INSN);
+ addOpcode("ISHL", ISHL, OpcodeGroup.INSN);
+ addOpcode("LSHL", LSHL, OpcodeGroup.INSN);
+ addOpcode("ISHR", ISHR, OpcodeGroup.INSN);
+ addOpcode("LSHR", LSHR, OpcodeGroup.INSN);
+ addOpcode("IUSHR", IUSHR, OpcodeGroup.INSN);
+ addOpcode("LUSHR", LUSHR, OpcodeGroup.INSN);
+ addOpcode("IAND", IAND, OpcodeGroup.INSN);
+ addOpcode("LAND", LAND, OpcodeGroup.INSN);
+ addOpcode("IOR", IOR, OpcodeGroup.INSN);
+ addOpcode("LOR", LOR, OpcodeGroup.INSN);
+ addOpcode("IXOR", IXOR, OpcodeGroup.INSN);
+ addOpcode("LXOR", LXOR, OpcodeGroup.INSN);
+ addOpcode("IINC", IINC, OpcodeGroup.INSN_IINC);
+ addOpcode("I2L", I2L, OpcodeGroup.INSN);
+ addOpcode("I2F", I2F, OpcodeGroup.INSN);
+ addOpcode("I2D", I2D, OpcodeGroup.INSN);
+ addOpcode("L2I", L2I, OpcodeGroup.INSN);
+ addOpcode("L2F", L2F, OpcodeGroup.INSN);
+ addOpcode("L2D", L2D, OpcodeGroup.INSN);
+ addOpcode("F2I", F2I, OpcodeGroup.INSN);
+ addOpcode("F2L", F2L, OpcodeGroup.INSN);
+ addOpcode("F2D", F2D, OpcodeGroup.INSN);
+ addOpcode("D2I", D2I, OpcodeGroup.INSN);
+ addOpcode("D2L", D2L, OpcodeGroup.INSN);
+ addOpcode("D2F", D2F, OpcodeGroup.INSN);
+ addOpcode("I2B", I2B, OpcodeGroup.INSN);
+ addOpcode("I2C", I2C, OpcodeGroup.INSN);
+ addOpcode("I2S", I2S, OpcodeGroup.INSN);
+ addOpcode("LCMP", LCMP, OpcodeGroup.INSN);
+ addOpcode("FCMPL", FCMPL, OpcodeGroup.INSN);
+ addOpcode("FCMPG", FCMPG, OpcodeGroup.INSN);
+ addOpcode("DCMPL", DCMPL, OpcodeGroup.INSN);
+ addOpcode("DCMPG", DCMPG, OpcodeGroup.INSN);
+ addOpcode("IFEQ", IFEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNE", IFNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLT", IFLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGE", IFGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFGT", IFGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFLE", IFLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPEQ", IF_ICMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPNE", IF_ICMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLT", IF_ICMPLT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGE", IF_ICMPGE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPGT", IF_ICMPGT, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ICMPLE", IF_ICMPLE, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPEQ", IF_ACMPEQ, OpcodeGroup.INSN_JUMP);
+ addOpcode("IF_ACMPNE", IF_ACMPNE, OpcodeGroup.INSN_JUMP);
+ addOpcode("GOTO", GOTO, OpcodeGroup.INSN_JUMP);
+ addOpcode("JSR", JSR, OpcodeGroup.INSN_JUMP);
+ addOpcode("RET", RET, OpcodeGroup.INSN_VAR);
+ addOpcode("IRETURN", IRETURN, OpcodeGroup.INSN);
+ addOpcode("LRETURN", LRETURN, OpcodeGroup.INSN);
+ addOpcode("FRETURN", FRETURN, OpcodeGroup.INSN);
+ addOpcode("DRETURN", DRETURN, OpcodeGroup.INSN);
+ addOpcode("ARETURN", ARETURN, OpcodeGroup.INSN);
+ addOpcode("RETURN", RETURN, OpcodeGroup.INSN);
+ addOpcode("GETSTATIC", GETSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTSTATIC", PUTSTATIC, OpcodeGroup.INSN_FIELD);
+ addOpcode("GETFIELD", GETFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("PUTFIELD", PUTFIELD, OpcodeGroup.INSN_FIELD);
+ addOpcode("INVOKEVIRTUAL", INVOKEVIRTUAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESPECIAL", INVOKESPECIAL, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKESTATIC", INVOKESTATIC, OpcodeGroup.INSN_METHOD);
+ addOpcode("INVOKEINTERFACE", INVOKEINTERFACE, OpcodeGroup.INSN_METHOD);
+ addOpcode("NEW", NEW, OpcodeGroup.INSN_TYPE);
+ addOpcode("NEWARRAY", NEWARRAY, OpcodeGroup.INSN_INT);
+ addOpcode("ANEWARRAY", ANEWARRAY, OpcodeGroup.INSN_TYPE);
+ addOpcode("ARRAYLENGTH", ARRAYLENGTH, OpcodeGroup.INSN);
+ addOpcode("ATHROW", ATHROW, OpcodeGroup.INSN);
+ addOpcode("CHECKCAST", CHECKCAST, OpcodeGroup.INSN_TYPE);
+ addOpcode("INSTANCEOF", INSTANCEOF, OpcodeGroup.INSN_TYPE);
+ addOpcode("MONITORENTER", MONITORENTER, OpcodeGroup.INSN);
+ addOpcode("MONITOREXIT", MONITOREXIT, OpcodeGroup.INSN);
+ addOpcode("MULTIANEWARRAY", MULTIANEWARRAY,
+ OpcodeGroup.INSN_MULTIANEWARRAY);
+ addOpcode("IFNULL", IFNULL, OpcodeGroup.INSN_JUMP);
+ addOpcode("IFNONNULL", IFNONNULL, OpcodeGroup.INSN_JUMP);
+ }
+
+ private static void addOpcode(String operStr, int oper, int group) {
+ OPCODES.put(operStr, new Opcode(oper, group));
+ }
+
+ static final HashMap<String, Integer> TYPES = new HashMap<String, Integer>();
+ static {
+ String[] types = SAXCodeAdapter.TYPES;
+ for (int i = 0; i < types.length; i++) {
+ TYPES.put(types[i], new Integer(i));
+ }
+ }
+
+ /**
+ * Constructs a new {@link ASMContentHandler ASMContentHandler} object.
+ *
+ * @param cv
+ * class visitor that will be called to reconstruct the classfile
+ * using the XML stream.
+ */
+ public ASMContentHandler(final ClassVisitor cv) {
+ this.cv = cv;
+ }
+
+ /**
+ * Process notification of the start of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified name (with prefix), or the empty string if
+ * qualified names are not available.
+ * @param list
+ * - The attributes attached to the element. If there are no
+ * attributes, it shall be an empty Attributes object.
+ * @exception SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void startElement(final String ns, final String lName,
+ final String qName, final Attributes list) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Compute the current matching rule
+ StringBuffer sb = new StringBuffer(match);
+ if (match.length() > 0) {
+ sb.append('/');
+ }
+ sb.append(name);
+ match = sb.toString();
+
+ // Fire "begin" events for all relevant rules
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.begin(name, list);
+ }
+ }
+
+ /**
+ * Process notification of the end of an XML element being reached.
+ *
+ * @param ns
+ * - The Namespace URI, or the empty string if the element has no
+ * Namespace URI or if Namespace processing is not being
+ * performed.
+ * @param lName
+ * - The local name (without prefix), or the empty string if
+ * Namespace processing is not being performed.
+ * @param qName
+ * - The qualified XML 1.0 name (with prefix), or the empty
+ * string if qualified names are not available.
+ *
+ * @exception SAXException
+ * if a parsing error is to be reported
+ */
+ @Override
+ public final void endElement(final String ns, final String lName,
+ final String qName) throws SAXException {
+ // the actual element name is either in lName or qName, depending
+ // on whether the parser is namespace aware
+ String name = lName == null || lName.length() == 0 ? qName : lName;
+
+ // Fire "end" events for all relevant rules in reverse order
+ Rule r = (Rule) RULES.match(match);
+ if (r != null) {
+ r.end(name);
+ }
+
+ // Recover the previous match expression
+ int slash = match.lastIndexOf('/');
+ if (slash >= 0) {
+ match = match.substring(0, slash);
+ } else {
+ match = "";
+ }
+ }
+
+ /**
+ * Return the top object on the stack without removing it. If there are no
+ * objects on the stack, return <code>null</code>.
+ *
+ * @return the top object on the stack without removing it.
+ */
+ final Object peek() {
+ int size = stack.size();
+ return size == 0 ? null : stack.get(size - 1);
+ }
+
+ /**
+ * Pop the top object off of the stack, and return it. If there are no
+ * objects on the stack, return <code>null</code>.
+ *
+ * @return the top object off of the stack.
+ */
+ final Object pop() {
+ int size = stack.size();
+ return size == 0 ? null : stack.remove(size - 1);
+ }
+
+ /**
+ * Push a new object onto the top of the object stack.
+ *
+ * @param object
+ * The new object
+ */
+ final void push(final Object object) {
+ stack.add(object);
+ }
+
+ static final class RuleSet {
+
+ private final HashMap<String, Object> rules = new HashMap<String, Object>();
+
+ private final ArrayList<String> lpatterns = new ArrayList<String>();
+
+ private final ArrayList<String> rpatterns = new ArrayList<String>();
+
+ public void add(final String path, final Object rule) {
+ String pattern = path;
+ if (path.startsWith("*/")) {
+ pattern = path.substring(1);
+ lpatterns.add(pattern);
+ } else if (path.endsWith("/*")) {
+ pattern = path.substring(0, path.length() - 1);
+ rpatterns.add(pattern);
+ }
+ rules.put(pattern, rule);
+ }
+
+ public Object match(final String path) {
+ if (rules.containsKey(path)) {
+ return rules.get(path);
+ }
+
+ int n = path.lastIndexOf('/');
+ for (Iterator<String> it = lpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.substring(n).endsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ for (Iterator<String> it = rpatterns.iterator(); it.hasNext();) {
+ String pattern = it.next();
+ if (path.startsWith(pattern)) {
+ return rules.get(pattern);
+ }
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Rule
+ */
+ protected abstract class Rule {
+
+ public void begin(final String name, final Attributes attrs)
+ throws SAXException {
+ }
+
+ public void end(final String name) {
+ }
+
+ protected final Object getValue(final String desc, final String val)
+ throws SAXException {
+ Object value = null;
+ if (val != null) {
+ if ("Ljava/lang/String;".equals(desc)) {
+ value = decode(val);
+ } else if ("Ljava/lang/Integer;".equals(desc)
+ || "I".equals(desc) || "S".equals(desc)
+ || "B".equals(desc) || "C".equals(desc)
+ || "Z".equals(desc)) {
+ value = new Integer(val);
+
+ } else if ("Ljava/lang/Short;".equals(desc)) {
+ value = new Short(val);
+
+ } else if ("Ljava/lang/Byte;".equals(desc)) {
+ value = new Byte(val);
+
+ } else if ("Ljava/lang/Character;".equals(desc)) {
+ value = new Character(decode(val).charAt(0));
+
+ } else if ("Ljava/lang/Boolean;".equals(desc)) {
+ value = Boolean.valueOf(val);
+
+ } else if ("Ljava/lang/Long;".equals(desc) || "J".equals(desc)) {
+ value = new Long(val);
+ } else if ("Ljava/lang/Float;".equals(desc) || "F".equals(desc)) {
+ value = new Float(val);
+ } else if ("Ljava/lang/Double;".equals(desc)
+ || "D".equals(desc)) {
+ value = new Double(val);
+ } else if (Type.getDescriptor(Type.class).equals(desc)) {
+ value = Type.getType(val);
+
+ } else if (Type.getDescriptor(Handle.class).equals(desc)) {
+ value = decodeHandle(val);
+
+ } else {
+ // TODO use of default toString().
+ throw new SAXException("Invalid value:" + val + " desc:"
+ + desc + " ctx:" + this);
+ }
+ }
+ return value;
+ }
+
+ Handle decodeHandle(final String val) throws SAXException {
+ try {
+ int dotIndex = val.indexOf('.');
+ int descIndex = val.indexOf('(', dotIndex + 1);
+ int tagIndex = val.lastIndexOf('(');
+
+ int tag = Integer.parseInt(val.substring(tagIndex + 1,
+ val.length() - 1));
+ String owner = val.substring(0, dotIndex);
+ String name = val.substring(dotIndex + 1, descIndex);
+ String desc = val.substring(descIndex, tagIndex - 1);
+ return new Handle(tag, owner, name, desc);
+
+ } catch (RuntimeException e) {
+ throw new SAXException("Malformed handle " + val, e);
+ }
+ }
+
+ private final String decode(final String val) throws SAXException {
+ StringBuffer sb = new StringBuffer(val.length());
+ try {
+ int n = 0;
+ while (n < val.length()) {
+ char c = val.charAt(n);
+ if (c == '\\') {
+ n++;
+ c = val.charAt(n);
+ if (c == '\\') {
+ sb.append('\\');
+ } else {
+ n++; // skip 'u'
+ sb.append((char) Integer.parseInt(
+ val.substring(n, n + 4), 16));
+ n += 3;
+ }
+ } else {
+ sb.append(c);
+ }
+ n++;
+ }
+
+ } catch (RuntimeException ex) {
+ throw new SAXException(ex);
+ }
+ return sb.toString();
+ }
+
+ protected final Label getLabel(final Object label) {
+ Label lbl = labels.get(label);
+ if (lbl == null) {
+ lbl = new Label();
+ labels.put(label, lbl);
+ }
+ return lbl;
+ }
+
+ // TODO verify move to stack
+ protected final MethodVisitor getCodeVisitor() {
+ return (MethodVisitor) peek();
+ }
+
+ protected final int getAccess(final String s) {
+ int access = 0;
+ if (s.indexOf("public") != -1) {
+ access |= ACC_PUBLIC;
+ }
+ if (s.indexOf("private") != -1) {
+ access |= ACC_PRIVATE;
+ }
+ if (s.indexOf("protected") != -1) {
+ access |= ACC_PROTECTED;
+ }
+ if (s.indexOf("static") != -1) {
+ access |= ACC_STATIC;
+ }
+ if (s.indexOf("final") != -1) {
+ access |= ACC_FINAL;
+ }
+ if (s.indexOf("super") != -1) {
+ access |= ACC_SUPER;
+ }
+ if (s.indexOf("synchronized") != -1) {
+ access |= ACC_SYNCHRONIZED;
+ }
+ if (s.indexOf("volatile") != -1) {
+ access |= ACC_VOLATILE;
+ }
+ if (s.indexOf("bridge") != -1) {
+ access |= ACC_BRIDGE;
+ }
+ if (s.indexOf("varargs") != -1) {
+ access |= ACC_VARARGS;
+ }
+ if (s.indexOf("transient") != -1) {
+ access |= ACC_TRANSIENT;
+ }
+ if (s.indexOf("native") != -1) {
+ access |= ACC_NATIVE;
+ }
+ if (s.indexOf("interface") != -1) {
+ access |= ACC_INTERFACE;
+ }
+ if (s.indexOf("abstract") != -1) {
+ access |= ACC_ABSTRACT;
+ }
+ if (s.indexOf("strict") != -1) {
+ access |= ACC_STRICT;
+ }
+ if (s.indexOf("synthetic") != -1) {
+ access |= ACC_SYNTHETIC;
+ }
+ if (s.indexOf("annotation") != -1) {
+ access |= ACC_ANNOTATION;
+ }
+ if (s.indexOf("enum") != -1) {
+ access |= ACC_ENUM;
+ }
+ if (s.indexOf("deprecated") != -1) {
+ access |= ACC_DEPRECATED;
+ }
+ if (s.indexOf("mandated") != -1) {
+ access |= ACC_MANDATED;
+ }
+ return access;
+ }
+ }
+
+ /**
+ * ClassRule
+ */
+ final class ClassRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int major = Integer.parseInt(attrs.getValue("major"));
+ int minor = Integer.parseInt(attrs.getValue("minor"));
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("version", new Integer(minor << 16 | major));
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("parent", attrs.getValue("parent"));
+ vals.put("source", attrs.getValue("source"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("interfaces", new ArrayList<String>());
+ push(vals);
+ // values will be extracted in InterfacesRule.end();
+ }
+ }
+
+ final class SourceRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String file = attrs.getValue("file");
+ String debug = attrs.getValue("debug");
+ cv.visitSource(file, debug);
+ }
+ }
+
+ /**
+ * InterfaceRule
+ */
+ final class InterfaceRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("interfaces"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * InterfacesRule
+ */
+ final class InterfacesRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int version = ((Integer) vals.get("version")).intValue();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String signature = (String) vals.get("signature");
+ String parent = (String) vals.get("parent");
+ ArrayList<?> infs = (ArrayList<?>) vals.get("interfaces");
+ String[] interfaces = infs.toArray(new String[infs.size()]);
+ cv.visit(version, access, name, signature, parent, interfaces);
+ push(cv);
+ }
+ }
+
+ /**
+ * OuterClassRule
+ */
+ final class OuterClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String owner = attrs.getValue("owner");
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ /**
+ * InnerClassRule
+ */
+ final class InnerClassRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String outerName = attrs.getValue("outerName");
+ String innerName = attrs.getValue("innerName");
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ /**
+ * FieldRule
+ */
+ final class FieldRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ int access = getAccess(attrs.getValue("access"));
+ String name = attrs.getValue("name");
+ String signature = attrs.getValue("signature");
+ String desc = attrs.getValue("desc");
+ Object value = getValue(desc, attrs.getValue("value"));
+ push(cv.visitField(access, name, desc, signature, value));
+ }
+
+ @Override
+ public void end(final String name) {
+ ((FieldVisitor) pop()).visitEnd();
+ }
+ }
+
+ /**
+ * MethodRule
+ */
+ final class MethodRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ labels = new HashMap<Object, Label>();
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("access", attrs.getValue("access"));
+ vals.put("name", attrs.getValue("name"));
+ vals.put("desc", attrs.getValue("desc"));
+ vals.put("signature", attrs.getValue("signature"));
+ vals.put("exceptions", new ArrayList<String>());
+ push(vals);
+ // values will be extracted in ExceptionsRule.end();
+ }
+
+ @Override
+ public final void end(final String name) {
+ ((MethodVisitor) pop()).visitEnd();
+ labels = null;
+ }
+ }
+
+ /**
+ * ExceptionRule
+ */
+ final class ExceptionRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<String>) ((HashMap<?, ?>) peek()).get("exceptions"))
+ .add(attrs.getValue("name"));
+ }
+ }
+
+ /**
+ * ExceptionsRule
+ */
+ final class ExceptionsRule extends Rule {
+
+ @Override
+ public final void end(final String element) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int access = getAccess((String) vals.get("access"));
+ String name = (String) vals.get("name");
+ String desc = (String) vals.get("desc");
+ String signature = (String) vals.get("signature");
+ ArrayList<?> excs = (ArrayList<?>) vals.get("exceptions");
+ String[] exceptions = excs.toArray(new String[excs.size()]);
+
+ push(cv.visitMethod(access, name, desc, signature, exceptions));
+ }
+ }
+
+ /**
+ * MethodParameterRule
+ */
+ final class MethodParameterRule extends Rule {
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ String name = attrs.getValue("name");
+ int access = getAccess(attrs.getValue("access"));
+ getCodeVisitor().visitParameter(name, access);
+ }
+ }
+
+ /**
+ * TableSwitchRule
+ */
+ final class TableSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("min", attrs.getValue("min"));
+ vals.put("max", attrs.getValue("max"));
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList<String>());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ int min = Integer.parseInt((String) vals.get("min"));
+ int max = Integer.parseInt((String) vals.get("max"));
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ getCodeVisitor().visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * TableSwitchLabelRule
+ */
+ final class TableSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ ((ArrayList<Label>) ((HashMap<?, ?>) peek()).get("labels"))
+ .add(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * LookupSwitchRule
+ */
+ final class LookupSwitchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> vals = new HashMap<String, Object>();
+ vals.put("dflt", attrs.getValue("dflt"));
+ vals.put("labels", new ArrayList<Label>());
+ vals.put("keys", new ArrayList<String>());
+ push(vals);
+ }
+
+ @Override
+ public final void end(final String name) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) pop();
+ Label dflt = getLabel(vals.get("dflt"));
+ ArrayList<String> keyList = (ArrayList<String>) vals.get("keys");
+ ArrayList<?> lbls = (ArrayList<?>) vals.get("labels");
+ Label[] labels = lbls.toArray(new Label[lbls.size()]);
+ int[] keys = new int[keyList.size()];
+ for (int i = 0; i < keys.length; i++) {
+ keys[i] = Integer.parseInt(keyList.get(i));
+ }
+ getCodeVisitor().visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * LookupSwitchLabelRule
+ */
+ final class LookupSwitchLabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ HashMap<?, ?> vals = (HashMap<?, ?>) peek();
+ ((ArrayList<Label>) vals.get("labels")).add(getLabel(attrs
+ .getValue("name")));
+ ((ArrayList<String>) vals.get("keys")).add(attrs.getValue("key"));
+ }
+ }
+
+ /**
+ * FrameRule
+ */
+ final class FrameRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ HashMap<String, Object> typeLists = new HashMap<String, Object>();
+ typeLists.put("local", new ArrayList<Object>());
+ typeLists.put("stack", new ArrayList<Object>());
+ push(attrs.getValue("type"));
+ push(attrs.getValue("count") == null ? "0" : attrs
+ .getValue("count"));
+ push(typeLists);
+ }
+
+ @Override
+ public void end(final String name) {
+ HashMap<?, ?> typeLists = (HashMap<?, ?>) pop();
+ ArrayList<?> locals = (ArrayList<?>) typeLists.get("local");
+ int nLocal = locals.size();
+ Object[] local = locals.toArray();
+ ArrayList<?> stacks = (ArrayList<?>) typeLists.get("stack");
+ int nStack = stacks.size();
+ Object[] stack = stacks.toArray();
+ String count = (String) pop();
+ String type = (String) pop();
+ if ("NEW".equals(type)) {
+ getCodeVisitor()
+ .visitFrame(F_NEW, nLocal, local, nStack, stack);
+ } else if ("FULL".equals(type)) {
+ getCodeVisitor().visitFrame(F_FULL, nLocal, local, nStack,
+ stack);
+ } else if ("APPEND".equals(type)) {
+ getCodeVisitor().visitFrame(F_APPEND, nLocal, local, 0, null);
+ } else if ("CHOP".equals(type)) {
+ getCodeVisitor().visitFrame(F_CHOP, Integer.parseInt(count),
+ null, 0, null);
+ } else if ("SAME".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME, 0, null, 0, null);
+ } else if ("SAME1".equals(type)) {
+ getCodeVisitor().visitFrame(F_SAME1, 0, null, nStack, stack);
+ }
+ }
+ }
+
+ final class FrameTypeRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ ArrayList<Object> types = (ArrayList<Object>) ((HashMap<?, ?>) peek())
+ .get(name);
+ String type = attrs.getValue("type");
+ if ("uninitialized".equals(type)) {
+ types.add(getLabel(attrs.getValue("label")));
+ } else {
+ Integer t = TYPES.get(type);
+ if (t == null) {
+ types.add(type);
+ } else {
+ types.add(t);
+ }
+ }
+ }
+ }
+
+ /**
+ * LabelRule
+ */
+ final class LabelRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ getCodeVisitor().visitLabel(getLabel(attrs.getValue("name")));
+ }
+ }
+
+ /**
+ * TryCatchRule
+ */
+ final class TryCatchRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ Label handler = getLabel(attrs.getValue("handler"));
+ String type = attrs.getValue("type");
+ getCodeVisitor().visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * LineNumberRule
+ */
+ final class LineNumberRule extends Rule {
+
+ @Override
+ public final void begin(final String name, final Attributes attrs) {
+ int line = Integer.parseInt(attrs.getValue("line"));
+ Label start = getLabel(attrs.getValue("start"));
+ getCodeVisitor().visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * LocalVarRule
+ */
+ final class LocalVarRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ String name = attrs.getValue("name");
+ String desc = attrs.getValue("desc");
+ String signature = attrs.getValue("signature");
+ Label start = getLabel(attrs.getValue("start"));
+ Label end = getLabel(attrs.getValue("end"));
+ int var = Integer.parseInt(attrs.getValue("var"));
+ getCodeVisitor().visitLocalVariable(name, desc, signature, start,
+ end, var);
+ }
+ }
+
+ /**
+ * InvokeDynamicRule
+ */
+ final class InvokeDynamicRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ push(attrs.getValue("name"));
+ push(attrs.getValue("desc"));
+ push(decodeHandle(attrs.getValue("bsm")));
+ push(new ArrayList<Object>());
+ }
+
+ @Override
+ public final void end(final String element) {
+ ArrayList<?> bsmArgs = (ArrayList<?>) pop();
+ Handle bsm = (Handle) pop();
+ String desc = (String) pop();
+ String name = (String) pop();
+ getCodeVisitor().visitInvokeDynamicInsn(name, desc, bsm,
+ bsmArgs.toArray());
+ }
+ }
+
+ /**
+ * InvokeDynamicBsmArgumentsRule
+ */
+ final class InvokeDynamicBsmArgumentsRule extends Rule {
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ ArrayList<Object> bsmArgs = (ArrayList<Object>) peek();
+ bsmArgs.add(getValue(attrs.getValue("desc"), attrs.getValue("cst")));
+ }
+ }
+
+ /**
+ * OpcodesRule
+ */
+ final class OpcodesRule extends Rule {
+
+ // public boolean match( String match, String element) {
+ // return match.startsWith( path) && OPCODES.containsKey( element);
+ // }
+
+ @Override
+ public final void begin(final String element, final Attributes attrs)
+ throws SAXException {
+ Opcode o = OPCODES.get(element);
+ if (o == null) {
+ throw new SAXException("Invalid element: " + element + " at "
+ + match);
+ }
+
+ switch (o.type) {
+ case OpcodeGroup.INSN:
+ getCodeVisitor().visitInsn(o.opcode);
+ break;
+
+ case OpcodeGroup.INSN_FIELD:
+ getCodeVisitor().visitFieldInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_INT:
+ getCodeVisitor().visitIntInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("value")));
+ break;
+
+ case OpcodeGroup.INSN_JUMP:
+ getCodeVisitor().visitJumpInsn(o.opcode,
+ getLabel(attrs.getValue("label")));
+ break;
+
+ case OpcodeGroup.INSN_METHOD:
+ getCodeVisitor().visitMethodInsn(o.opcode,
+ attrs.getValue("owner"), attrs.getValue("name"),
+ attrs.getValue("desc"),
+ attrs.getValue("itf").equals("true"));
+ break;
+
+ case OpcodeGroup.INSN_TYPE:
+ getCodeVisitor()
+ .visitTypeInsn(o.opcode, attrs.getValue("desc"));
+ break;
+
+ case OpcodeGroup.INSN_VAR:
+ getCodeVisitor().visitVarInsn(o.opcode,
+ Integer.parseInt(attrs.getValue("var")));
+ break;
+
+ case OpcodeGroup.INSN_IINC:
+ getCodeVisitor().visitIincInsn(
+ Integer.parseInt(attrs.getValue("var")),
+ Integer.parseInt(attrs.getValue("inc")));
+ break;
+
+ case OpcodeGroup.INSN_LDC:
+ getCodeVisitor()
+ .visitLdcInsn(
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("cst")));
+ break;
+
+ case OpcodeGroup.INSN_MULTIANEWARRAY:
+ getCodeVisitor().visitMultiANewArrayInsn(
+ attrs.getValue("desc"),
+ Integer.parseInt(attrs.getValue("dims")));
+ break;
+
+ default:
+ throw new Error("Internal error");
+
+ }
+ }
+ }
+
+ /**
+ * MaxRule
+ */
+ final class MaxRule extends Rule {
+
+ @Override
+ public final void begin(final String element, final Attributes attrs) {
+ int maxStack = Integer.parseInt(attrs.getValue("maxStack"));
+ int maxLocals = Integer.parseInt(attrs.getValue("maxLocals"));
+ getCodeVisitor().visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ final class AnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ Object v = peek();
+ if (v instanceof ClassVisitor) {
+ push(((ClassVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof FieldVisitor) {
+ push(((FieldVisitor) v).visitAnnotation(desc, visible));
+ } else if (v instanceof MethodVisitor) {
+ push(((MethodVisitor) v).visitAnnotation(desc, visible));
+ }
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class TypeAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+
+ Object v = peek();
+ if (v instanceof ClassVisitor) {
+ push(((ClassVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ } else if (v instanceof FieldVisitor) {
+ push(((FieldVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ } else if (v instanceof MethodVisitor) {
+ push(((MethodVisitor) v).visitTypeAnnotation(typeRef, typePath,
+ desc, visible));
+ }
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationParameterRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ int parameter = Integer.parseInt(attrs.getValue("parameter"));
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+
+ push(((MethodVisitor) peek()).visitParameterAnnotation(parameter,
+ desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class InsnAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ push(((MethodVisitor) peek()).visitInsnAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class TryCatchAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ push(((MethodVisitor) peek()).visitTryCatchAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class LocalVariableAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String name, final Attributes attrs) {
+ String desc = attrs.getValue("desc");
+ boolean visible = Boolean.valueOf(attrs.getValue("visible"))
+ .booleanValue();
+ int typeRef = Integer.parseInt(attrs.getValue("typeRef"));
+ TypePath typePath = TypePath.fromString(attrs.getValue("typePath"));
+ String[] s = attrs.getValue("start").split(" ");
+ Label[] start = new Label[s.length];
+ for (int i = 0; i < start.length; ++i) {
+ start[i] = getLabel(s[i]);
+ }
+ String[] e = attrs.getValue("end").split(" ");
+ Label[] end = new Label[e.length];
+ for (int i = 0; i < end.length; ++i) {
+ end[i] = getLabel(e[i]);
+ }
+ String[] v = attrs.getValue("index").split(" ");
+ int[] index = new int[v.length];
+ for (int i = 0; i < index.length; ++i) {
+ index[i] = Integer.parseInt(v[i]);
+ }
+ push(((MethodVisitor) peek()).visitLocalVariableAnnotation(typeRef,
+ typePath, start, end, index, desc, visible));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs)
+ throws SAXException {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visit(
+ attrs.getValue("name"),
+ getValue(attrs.getValue("desc"),
+ attrs.getValue("value")));
+ }
+ }
+ }
+
+ final class AnnotationValueEnumRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ if (av != null) {
+ av.visitEnum(attrs.getValue("name"), attrs.getValue("desc"),
+ attrs.getValue("value"));
+ }
+ }
+ }
+
+ final class AnnotationValueAnnotationRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitAnnotation(attrs.getValue("name"),
+ attrs.getValue("desc")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationValueArrayRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ AnnotationVisitor av = (AnnotationVisitor) peek();
+ push(av == null ? null : av.visitArray(attrs.getValue("name")));
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ final class AnnotationDefaultRule extends Rule {
+
+ @Override
+ public void begin(final String nm, final Attributes attrs) {
+ MethodVisitor av = (MethodVisitor) peek();
+ push(av == null ? null : av.visitAnnotationDefault());
+ }
+
+ @Override
+ public void end(final String name) {
+ AnnotationVisitor av = (AnnotationVisitor) pop();
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ }
+
+ /**
+ * Opcode
+ */
+ static final class Opcode {
+
+ public final int opcode;
+
+ public final int type;
+
+ Opcode(final int opcode, final int type) {
+ this.opcode = opcode;
+ this.type = type;
+ }
+ }
+}
[05/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..5770364
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1542 @@
+/***
+ * 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.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based <i>only</i> on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
+ * They are not performed if any other constructor is used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+ /**
+ * The class version number.
+ */
+ public int version;
+
+ /**
+ * The access flags of the method.
+ */
+ private int access;
+
+ /**
+ * <tt>true</tt> if the visitCode method has been called.
+ */
+ private boolean startCode;
+
+ /**
+ * <tt>true</tt> if the visitMaxs method has been called.
+ */
+ private boolean endCode;
+
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean endMethod;
+
+ /**
+ * Number of visited instructions.
+ */
+ private int insnCount;
+
+ /**
+ * The already visited labels. This map associate Integer values to pseudo
+ * code offsets.
+ */
+ private final Map<Label, Integer> labels;
+
+ /**
+ * The labels used in this method. Every used label must be visited with
+ * visitLabel before the end of the method (i.e. should be in #labels).
+ */
+ private Set<Label> usedLabels;
+
+ /**
+ * Number of visited frames in expanded form.
+ */
+ private int expandedFrames;
+
+ /**
+ * Number of visited frames in compressed form.
+ */
+ private int compressedFrames;
+
+ /**
+ * Number of instructions before the last visited frame.
+ */
+ private int lastFrame = -1;
+
+ /**
+ * The exception handler ranges. Each pair of list element contains the
+ * start and end labels of an exception handler block.
+ */
+ private List<Label> handlers;
+
+ /**
+ * Code of the visit method to be used for each opcode.
+ */
+ private static final int[] TYPE;
+
+ /**
+ * The Label.status field.
+ */
+ private static Field labelStatusField;
+
+ static {
+ String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+ + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+ + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+ TYPE = new int[s.length()];
+ for (int i = 0; i < TYPE.length; ++i) {
+ TYPE[i] = s.charAt(i) - 'A' - 1;
+ }
+ }
+
+ // code to generate the above string
+ // public static void main (String[] args) {
+ // int[] TYPE = new int[] {
+ // 0, //NOP
+ // 0, //ACONST_NULL
+ // 0, //ICONST_M1
+ // 0, //ICONST_0
+ // 0, //ICONST_1
+ // 0, //ICONST_2
+ // 0, //ICONST_3
+ // 0, //ICONST_4
+ // 0, //ICONST_5
+ // 0, //LCONST_0
+ // 0, //LCONST_1
+ // 0, //FCONST_0
+ // 0, //FCONST_1
+ // 0, //FCONST_2
+ // 0, //DCONST_0
+ // 0, //DCONST_1
+ // 1, //BIPUSH
+ // 1, //SIPUSH
+ // 7, //LDC
+ // -1, //LDC_W
+ // -1, //LDC2_W
+ // 2, //ILOAD
+ // 2, //LLOAD
+ // 2, //FLOAD
+ // 2, //DLOAD
+ // 2, //ALOAD
+ // -1, //ILOAD_0
+ // -1, //ILOAD_1
+ // -1, //ILOAD_2
+ // -1, //ILOAD_3
+ // -1, //LLOAD_0
+ // -1, //LLOAD_1
+ // -1, //LLOAD_2
+ // -1, //LLOAD_3
+ // -1, //FLOAD_0
+ // -1, //FLOAD_1
+ // -1, //FLOAD_2
+ // -1, //FLOAD_3
+ // -1, //DLOAD_0
+ // -1, //DLOAD_1
+ // -1, //DLOAD_2
+ // -1, //DLOAD_3
+ // -1, //ALOAD_0
+ // -1, //ALOAD_1
+ // -1, //ALOAD_2
+ // -1, //ALOAD_3
+ // 0, //IALOAD
+ // 0, //LALOAD
+ // 0, //FALOAD
+ // 0, //DALOAD
+ // 0, //AALOAD
+ // 0, //BALOAD
+ // 0, //CALOAD
+ // 0, //SALOAD
+ // 2, //ISTORE
+ // 2, //LSTORE
+ // 2, //FSTORE
+ // 2, //DSTORE
+ // 2, //ASTORE
+ // -1, //ISTORE_0
+ // -1, //ISTORE_1
+ // -1, //ISTORE_2
+ // -1, //ISTORE_3
+ // -1, //LSTORE_0
+ // -1, //LSTORE_1
+ // -1, //LSTORE_2
+ // -1, //LSTORE_3
+ // -1, //FSTORE_0
+ // -1, //FSTORE_1
+ // -1, //FSTORE_2
+ // -1, //FSTORE_3
+ // -1, //DSTORE_0
+ // -1, //DSTORE_1
+ // -1, //DSTORE_2
+ // -1, //DSTORE_3
+ // -1, //ASTORE_0
+ // -1, //ASTORE_1
+ // -1, //ASTORE_2
+ // -1, //ASTORE_3
+ // 0, //IASTORE
+ // 0, //LASTORE
+ // 0, //FASTORE
+ // 0, //DASTORE
+ // 0, //AASTORE
+ // 0, //BASTORE
+ // 0, //CASTORE
+ // 0, //SASTORE
+ // 0, //POP
+ // 0, //POP2
+ // 0, //DUP
+ // 0, //DUP_X1
+ // 0, //DUP_X2
+ // 0, //DUP2
+ // 0, //DUP2_X1
+ // 0, //DUP2_X2
+ // 0, //SWAP
+ // 0, //IADD
+ // 0, //LADD
+ // 0, //FADD
+ // 0, //DADD
+ // 0, //ISUB
+ // 0, //LSUB
+ // 0, //FSUB
+ // 0, //DSUB
+ // 0, //IMUL
+ // 0, //LMUL
+ // 0, //FMUL
+ // 0, //DMUL
+ // 0, //IDIV
+ // 0, //LDIV
+ // 0, //FDIV
+ // 0, //DDIV
+ // 0, //IREM
+ // 0, //LREM
+ // 0, //FREM
+ // 0, //DREM
+ // 0, //INEG
+ // 0, //LNEG
+ // 0, //FNEG
+ // 0, //DNEG
+ // 0, //ISHL
+ // 0, //LSHL
+ // 0, //ISHR
+ // 0, //LSHR
+ // 0, //IUSHR
+ // 0, //LUSHR
+ // 0, //IAND
+ // 0, //LAND
+ // 0, //IOR
+ // 0, //LOR
+ // 0, //IXOR
+ // 0, //LXOR
+ // 8, //IINC
+ // 0, //I2L
+ // 0, //I2F
+ // 0, //I2D
+ // 0, //L2I
+ // 0, //L2F
+ // 0, //L2D
+ // 0, //F2I
+ // 0, //F2L
+ // 0, //F2D
+ // 0, //D2I
+ // 0, //D2L
+ // 0, //D2F
+ // 0, //I2B
+ // 0, //I2C
+ // 0, //I2S
+ // 0, //LCMP
+ // 0, //FCMPL
+ // 0, //FCMPG
+ // 0, //DCMPL
+ // 0, //DCMPG
+ // 6, //IFEQ
+ // 6, //IFNE
+ // 6, //IFLT
+ // 6, //IFGE
+ // 6, //IFGT
+ // 6, //IFLE
+ // 6, //IF_ICMPEQ
+ // 6, //IF_ICMPNE
+ // 6, //IF_ICMPLT
+ // 6, //IF_ICMPGE
+ // 6, //IF_ICMPGT
+ // 6, //IF_ICMPLE
+ // 6, //IF_ACMPEQ
+ // 6, //IF_ACMPNE
+ // 6, //GOTO
+ // 6, //JSR
+ // 2, //RET
+ // 9, //TABLESWITCH
+ // 10, //LOOKUPSWITCH
+ // 0, //IRETURN
+ // 0, //LRETURN
+ // 0, //FRETURN
+ // 0, //DRETURN
+ // 0, //ARETURN
+ // 0, //RETURN
+ // 4, //GETSTATIC
+ // 4, //PUTSTATIC
+ // 4, //GETFIELD
+ // 4, //PUTFIELD
+ // 5, //INVOKEVIRTUAL
+ // 5, //INVOKESPECIAL
+ // 5, //INVOKESTATIC
+ // 5, //INVOKEINTERFACE
+ // -1, //INVOKEDYNAMIC
+ // 3, //NEW
+ // 1, //NEWARRAY
+ // 3, //ANEWARRAY
+ // 0, //ARRAYLENGTH
+ // 0, //ATHROW
+ // 3, //CHECKCAST
+ // 3, //INSTANCEOF
+ // 0, //MONITORENTER
+ // 0, //MONITOREXIT
+ // -1, //WIDE
+ // 11, //MULTIANEWARRAY
+ // 6, //IFNULL
+ // 6, //IFNONNULL
+ // -1, //GOTO_W
+ // -1 //JSR_W
+ // };
+ // for (int i = 0; i < TYPE.length; ++i) {
+ // System.out.print((char)(TYPE[i] + 1 + 'A'));
+ // }
+ // System.out.println();
+ // }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv) {
+ this(mv, new HashMap<Label, Integer>());
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv,
+ final Map<Label, Integer> labels) {
+ this(Opcodes.ASM5, mv, labels);
+ if (getClass() != CheckMethodAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ protected CheckMethodAdapter(final int api, final MethodVisitor mv,
+ final Map<Label, Integer> labels) {
+ super(api, mv);
+ this.labels = labels;
+ this.usedLabels = new HashSet<Label>();
+ this.handlers = new ArrayList<Label>();
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will perform basic data flow checks. For instance in a method whose
+ * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
+ * invalid sequence IADD L2I will be detected.
+ *
+ * @param access
+ * the method's access flags.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param cmv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(final int access, final String name,
+ final String desc, final MethodVisitor cmv,
+ final Map<Label, Integer> labels) {
+ this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
+ @Override
+ public void visitEnd() {
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(
+ new BasicVerifier());
+ try {
+ a.analyze("dummy", this);
+ } catch (Exception e) {
+ if (e instanceof IndexOutOfBoundsException
+ && maxLocals == 0 && maxStack == 0) {
+ throw new RuntimeException(
+ "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+ }
+ e.printStackTrace();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ CheckClassAdapter.printAnalyzerResult(this, a, pw);
+ pw.close();
+ throw new RuntimeException(e.getMessage() + ' '
+ + sw.toString());
+ }
+ accept(cmv);
+ }
+ }, labels);
+ this.access = access;
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ if (name != null) {
+ checkUnqualifiedName(version, name, "name");
+ }
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
+ + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkEndMethod();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.METHOD_TYPE_PARAMETER
+ && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.METHOD_RETURN
+ && sort != TypeReference.METHOD_RECEIVER
+ && sort != TypeReference.METHOD_FORMAL_PARAMETER
+ && sort != TypeReference.THROWS) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkEndMethod();
+ return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitParameterAnnotation(
+ parameter, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEndMethod();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ throw new RuntimeException("Abstract methods cannot have code");
+ }
+ startCode = true;
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (insnCount == lastFrame) {
+ throw new IllegalStateException(
+ "At most one frame can be visited at a given code location.");
+ }
+ lastFrame = insnCount;
+ int mLocal;
+ int mStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mLocal = Integer.MAX_VALUE;
+ mStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ mLocal = 0;
+ mStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ mLocal = 0;
+ mStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ mLocal = 3;
+ mStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
+ }
+
+ if (nLocal > mLocal) {
+ throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+ + " for frame type " + type);
+ }
+ if (nStack > mStack) {
+ throw new IllegalArgumentException("Invalid nStack=" + nStack
+ + " for frame type " + type);
+ }
+
+ if (type != Opcodes.F_CHOP) {
+ if (nLocal > 0 && (local == null || local.length < nLocal)) {
+ throw new IllegalArgumentException(
+ "Array local[] is shorter than nLocal");
+ }
+ for (int i = 0; i < nLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
+ }
+ if (nStack > 0 && (stack == null || stack.length < nStack)) {
+ throw new IllegalArgumentException(
+ "Array stack[] is shorter than nStack");
+ }
+ for (int i = 0; i < nStack; ++i) {
+ checkFrameValue(stack[i]);
+ }
+ if (type == Opcodes.F_NEW) {
+ ++expandedFrames;
+ } else {
+ ++compressedFrames;
+ }
+ if (expandedFrames > 0 && compressedFrames > 0) {
+ throw new RuntimeException(
+ "Expanded and compressed frames must not be mixed.");
+ }
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 0);
+ super.visitInsn(opcode);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 1);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ // case Constants.NEWARRAY:
+ default:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException(
+ "Invalid operand (must be an array type code T_...): "
+ + operand);
+ }
+ }
+ super.visitIntInsn(opcode, operand);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 2);
+ checkUnsignedShort(var, "Invalid variable index");
+ super.visitVarInsn(opcode, var);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 3);
+ checkInternalName(type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException(
+ "NEW cannot be used to create arrays: " + type);
+ }
+ super.visitTypeInsn(opcode, type);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 4);
+ checkInternalName(owner, "owner");
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Deprecated
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name,
+ 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(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ private void doVisitMethodInsn(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 5);
+ if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
+ checkMethodIdentifier(version, name, "name");
+ }
+ checkInternalName(owner, "owner");
+ checkMethodDesc(desc);
+ if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
+ throw new IllegalArgumentException(
+ "INVOKEVIRTUAL can't be used with interfaces");
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
+ throw new IllegalArgumentException(
+ "INVOKEINTERFACE can't be used with classes");
+ }
+ // Calling super.visitMethodInsn requires to call the correct version
+ // depending on this.api (otherwise infinite loops can occur). To
+ // simplify and to make it easier to automatically remove the backward
+ // compatibility code, we inline the code of the overridden method here.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ checkStartCode();
+ checkEndCode();
+ checkMethodIdentifier(version, name, "name");
+ checkMethodDesc(desc);
+ if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+ && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+ throw new IllegalArgumentException("invalid handle tag "
+ + bsm.getTag());
+ }
+ for (int i = 0; i < bsmArgs.length; i++) {
+ checkLDCConstant(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 6);
+ checkLabel(label, false, "label");
+ checkNonDebugLabel(label);
+ super.visitJumpInsn(opcode, label);
+ usedLabels.add(label);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(label, false, "label");
+ if (labels.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labels.put(label, new Integer(insnCount));
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ checkStartCode();
+ checkEndCode();
+ checkLDCConstant(cst);
+ super.visitLdcInsn(cst);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(var, "Invalid variable index");
+ checkSignedShort(increment, "Invalid increment");
+ super.visitIincInsn(var, increment);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ checkStartCode();
+ checkEndCode();
+ if (max < min) {
+ throw new IllegalArgumentException("Max = " + max
+ + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException(
+ "There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ checkEndCode();
+ checkStartCode();
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException(
+ "There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ usedLabels.add(dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ checkStartCode();
+ checkEndCode();
+ checkDesc(desc, false);
+ if (desc.charAt(0) != '[') {
+ throw new IllegalArgumentException(
+ "Invalid descriptor (must be an array type descriptor): "
+ + desc);
+ }
+ if (dims < 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must be greater than 0): " + dims);
+ }
+ if (dims > desc.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must not be greater than dims(desc)): "
+ + dims);
+ }
+ super.visitMultiANewArrayInsn(desc, dims);
+ ++insnCount;
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE
+ && sort != TypeReference.METHOD_REFERENCE
+ && sort != TypeReference.CAST
+ && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(start, false, "start label");
+ checkLabel(end, false, "end label");
+ checkLabel(handler, false, "handler label");
+ checkNonDebugLabel(start);
+ checkNonDebugLabel(end);
+ checkNonDebugLabel(handler);
+ if (labels.get(start) != null || labels.get(end) != null
+ || labels.get(handler) != null) {
+ throw new IllegalStateException(
+ "Try catch blocks must be visited before their labels");
+ }
+ if (type != null) {
+ checkInternalName(type, "type");
+ }
+ super.visitTryCatchBlock(start, end, handler, type);
+ handlers.add(start);
+ handlers.add(end);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.EXCEPTION_PARAMETER) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.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) {
+ checkStartCode();
+ checkEndCode();
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ checkLabel(start, true, "start label");
+ checkLabel(end, true, "end label");
+ checkUnsignedShort(index, "Invalid variable index");
+ int s = labels.get(start).intValue();
+ int e = labels.get(end).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.LOCAL_VARIABLE
+ && sort != TypeReference.RESOURCE_VARIABLE) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ checkDesc(desc, false);
+ if (start == null || end == null || index == null
+ || end.length != start.length || index.length != start.length) {
+ throw new IllegalArgumentException(
+ "Invalid start, end and index arrays (must be non null and of identical length");
+ }
+ for (int i = 0; i < start.length; ++i) {
+ checkLabel(start[i], true, "start label");
+ checkLabel(end[i], true, "end label");
+ checkUnsignedShort(index[i], "Invalid variable index");
+ int s = labels.get(start[i]).intValue();
+ int e = labels.get(end[i]).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ }
+ return super.visitLocalVariableAnnotation(typeRef, typePath, start,
+ end, index, desc, visible);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(line, "Invalid line number");
+ checkLabel(start, true, "start label");
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ checkStartCode();
+ checkEndCode();
+ endCode = true;
+ for (Label l : usedLabels) {
+ if (labels.get(l) == null) {
+ throw new IllegalStateException("Undefined label used");
+ }
+ }
+ for (int i = 0; i < handlers.size();) {
+ Integer start = labels.get(handlers.get(i++));
+ Integer end = labels.get(handlers.get(i++));
+ if (start == null || end == null) {
+ throw new IllegalStateException(
+ "Undefined try catch block labels");
+ }
+ if (end.intValue() <= start.intValue()) {
+ throw new IllegalStateException(
+ "Emty try catch block handler range");
+ }
+ }
+ checkUnsignedShort(maxStack, "Invalid max stack");
+ checkUnsignedShort(maxLocals, "Invalid max locals");
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEndMethod();
+ endMethod = true;
+ super.visitEnd();
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks that the visitCode method has been called.
+ */
+ void checkStartCode() {
+ if (!startCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions before visitCode has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitMaxs method has not been called.
+ */
+ void checkEndCode() {
+ if (endCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions after visitMaxs has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitEnd method has not been called.
+ */
+ void checkEndMethod() {
+ if (endMethod) {
+ throw new IllegalStateException(
+ "Cannot visit elements after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks a stack frame value.
+ *
+ * @param value
+ * the value to be checked.
+ */
+ void checkFrameValue(final Object value) {
+ if (value == Opcodes.TOP || value == Opcodes.INTEGER
+ || value == Opcodes.FLOAT || value == Opcodes.LONG
+ || value == Opcodes.DOUBLE || value == Opcodes.NULL
+ || value == Opcodes.UNINITIALIZED_THIS) {
+ return;
+ }
+ if (value instanceof String) {
+ checkInternalName((String) value, "Invalid stack frame value");
+ return;
+ }
+ if (!(value instanceof Label)) {
+ throw new IllegalArgumentException("Invalid stack frame value: "
+ + value);
+ } else {
+ usedLabels.add((Label) value);
+ }
+ }
+
+ /**
+ * Checks that the type of the given opcode is equal to the given type.
+ *
+ * @param opcode
+ * the opcode to be checked.
+ * @param type
+ * the expected opcode type.
+ */
+ static void checkOpcode(final int opcode, final int type) {
+ if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+ throw new IllegalArgumentException("Invalid opcode: " + opcode);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed byte.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedByte(final int value, final String msg) {
+ if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed byte): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedShort(final int value, final String msg) {
+ if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an unsigned short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkUnsignedShort(final int value, final String msg) {
+ if (value < 0 || value > 65535) {
+ throw new IllegalArgumentException(msg
+ + " (must be an unsigned short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an {@link Integer}, a{@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the value to be checked.
+ */
+ static void checkConstant(final Object cst) {
+ if (!(cst instanceof Integer) && !(cst instanceof Float)
+ && !(cst instanceof Long) && !(cst instanceof Double)
+ && !(cst instanceof String)) {
+ throw new IllegalArgumentException("Invalid constant: " + cst);
+ }
+ }
+
+ void checkLDCConstant(final Object cst) {
+ if (cst instanceof Type) {
+ int s = ((Type) cst).getSort();
+ if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+ throw new IllegalArgumentException("Illegal LDC constant value");
+ }
+ if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+ throw new IllegalArgumentException(
+ "ldc of a constant class requires at least version 1.5");
+ }
+ if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a method type requires at least version 1.7");
+ }
+ } else if (cst instanceof Handle) {
+ if ((version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a handle requires at least version 1.7");
+ }
+ int tag = ((Handle) cst).getTag();
+ if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+ throw new IllegalArgumentException("invalid handle tag " + tag);
+ }
+ } else {
+ checkConstant(cst);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid unqualified name.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkUnqualifiedName(int version, final String name,
+ final String msg) {
+ if ((version & 0xFFFF) < Opcodes.V1_5) {
+ checkIdentifier(name, msg);
+ } else {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final String msg) {
+ checkIdentifier(name, 0, -1, msg);
+ }
+
+ /**
+ * Checks that the given substring is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final int start,
+ final int end, final String msg) {
+ if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ int max = end == -1 ? name.length() : end;
+ for (int i = start + 1; i < max; ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkMethodIdentifier(int version, final String name,
+ final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if ((version & 0xFFFF) >= Opcodes.V1_5) {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ return;
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (name.charAt(0) == '[') {
+ checkDesc(name, false);
+ } else {
+ checkInternalName(name, 0, -1, msg);
+ }
+ }
+
+ /**
+ * Checks that the given substring is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final int start,
+ final int end, final String msg) {
+ int max = end == -1 ? name.length() : end;
+ try {
+ int begin = start;
+ int slash;
+ do {
+ slash = name.indexOf('/', begin + 1);
+ if (slash == -1 || slash > max) {
+ slash = max;
+ }
+ checkIdentifier(name, begin, slash, null);
+ begin = slash + 1;
+ } while (slash != max);
+ } catch (IllegalArgumentException unused) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a fully qualified class name in internal form): "
+ + name);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param canBeVoid
+ * <tt>true</tt> if <tt>V</tt> can be considered valid.
+ */
+ static void checkDesc(final String desc, final boolean canBeVoid) {
+ int end = checkDesc(desc, 0, canBeVoid);
+ if (end != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that a the given substring is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param canBeVoid
+ * <tt>true</tt> if <tt>V</tt> can be considered valid.
+ * @return the index of the last character of the type decriptor, plus one.
+ */
+ static int checkDesc(final String desc, final int start,
+ final boolean canBeVoid) {
+ if (desc == null || start >= desc.length()) {
+ throw new IllegalArgumentException(
+ "Invalid type descriptor (must not be null or empty)");
+ }
+ int index;
+ switch (desc.charAt(start)) {
+ case 'V':
+ if (canBeVoid) {
+ return start + 1;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return start + 1;
+ case '[':
+ index = start + 1;
+ while (index < desc.length() && desc.charAt(index) == '[') {
+ ++index;
+ }
+ if (index < desc.length()) {
+ return checkDesc(desc, index, false);
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'L':
+ index = desc.indexOf(';', start);
+ if (index == -1 || index - start < 2) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ try {
+ checkInternalName(desc, start + 1, index, null);
+ } catch (IllegalArgumentException unused) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ return index + 1;
+ default:
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid method descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ */
+ static void checkMethodDesc(final String desc) {
+ if (desc == null || desc.length() == 0) {
+ throw new IllegalArgumentException(
+ "Invalid method descriptor (must not be null or empty)");
+ }
+ if (desc.charAt(0) != '(' || desc.length() < 3) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ int start = 1;
+ if (desc.charAt(start) != ')') {
+ do {
+ if (desc.charAt(start) == 'V') {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ start = checkDesc(desc, start, false);
+ } while (start < desc.length() && desc.charAt(start) != ')');
+ }
+ start = checkDesc(desc, start + 1, true);
+ if (start != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given label is not null. This method can also check that
+ * the label has been visited.
+ *
+ * @param label
+ * the label to be checked.
+ * @param checkVisited
+ * <tt>true</tt> to check that the label has been visited.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ void checkLabel(final Label label, final boolean checkVisited,
+ final String msg) {
+ if (label == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null)");
+ }
+ if (checkVisited && labels.get(label) == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be visited first)");
+ }
+ }
+
+ /**
+ * Checks that the given label is not a label used only for debug purposes.
+ *
+ * @param label
+ * the label to be checked.
+ */
+ private static void checkNonDebugLabel(final Label label) {
+ Field f = getLabelStatusField();
+ int status = 0;
+ try {
+ status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+ } catch (IllegalAccessException e) {
+ throw new Error("Internal error");
+ }
+ if ((status & 0x01) != 0) {
+ throw new IllegalArgumentException(
+ "Labels used for debug info cannot be reused for control flow");
+ }
+ }
+
+ /**
+ * Returns the Field object corresponding to the Label.status field.
+ *
+ * @return the Field object corresponding to the Label.status field.
+ */
+ private static Field getLabelStatusField() {
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("a");
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("status");
+ }
+ }
+ return labelStatusField;
+ }
+
+ /**
+ * Returns the field of the Label class whose name is given.
+ *
+ * @param name
+ * a field name.
+ * @return the field of the Label class whose name is given, or null.
+ */
+ private static Field getLabelField(final String name) {
+ try {
+ Field f = Label.class.getDeclaredField(name);
+ f.setAccessible(true);
+ return f;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..cf1f98b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,330 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.util;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+ /**
+ * Type to be used to check class signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ private static final int EMPTY = 1;
+
+ private static final int FORMAL = 2;
+
+ private static final int BOUND = 4;
+
+ private static final int SUPER = 8;
+
+ private static final int PARAM = 16;
+
+ private static final int RETURN = 32;
+
+ private static final int SIMPLE_TYPE = 64;
+
+ private static final int CLASS_TYPE = 128;
+
+ private static final int END = 256;
+
+ /**
+ * Type of the signature to be checked.
+ */
+ private final int type;
+
+ /**
+ * State of the automaton used to check the order of method calls.
+ */
+ private int state;
+
+ /**
+ * <tt>true</tt> if the checked type signature can be 'V'.
+ */
+ private boolean canBeVoid;
+
+ /**
+ * The visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ private final SignatureVisitor sv;
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the
+ * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
+ *
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+ this(Opcodes.ASM5, type, sv);
+ }
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ protected CheckSignatureAdapter(final int api, final int type,
+ final SignatureVisitor sv) {
+ super(api);
+ this.type = type;
+ this.state = EMPTY;
+ this.sv = sv;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE
+ || (state != EMPTY && state != FORMAL && state != BOUND)) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+ state = FORMAL;
+ if (sv != null) {
+ sv.visitFormalTypeParameter(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (state != FORMAL) {
+ throw new IllegalStateException();
+ }
+ state = BOUND;
+ SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (state != FORMAL && state != BOUND) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = SUPER;
+ SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (state != SUPER) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterface();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // method signatures
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = PARAM;
+ SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = RETURN;
+ SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+ CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ cv.canBeVoid = true;
+ return cv;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (state != RETURN) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // type signatures
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitBaseType(descriptor);
+ }
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "type variable");
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitTypeVariable(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = SIMPLE_TYPE;
+ SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ state = CLASS_TYPE;
+ if (sv != null) {
+ sv.visitClassType(name);
+ }
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "inner class name");
+ if (sv != null) {
+ sv.visitInnerClassType(name);
+ }
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (sv != null) {
+ sv.visitTypeArgument();
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = END;
+ if (sv != null) {
+ sv.visitEnd();
+ }
+ }
+}
[10/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
index a248cdf..d6c9c90 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FieldNode.java
@@ -29,14 +29,19 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A node that represents a field.
- *
+ *
* @author Eric Bruneton
*/
public class FieldNode extends FieldVisitor {
@@ -63,8 +68,8 @@ public class FieldNode extends FieldVisitor {
public String signature;
/**
- * The field's initial value. This field, which may be <tt>null</tt> if
- * the field does not have an initial value, must be an {@link Integer}, a
+ * The field's initial value. This field, which may be <tt>null</tt> if the
+ * field does not have an initial value, must be an {@link Integer}, a
* {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
*/
public Object value;
@@ -72,8 +77,8 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime visible annotations of this field. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -81,17 +86,35 @@ public class FieldNode extends FieldVisitor {
/**
* The runtime invisible annotations of this field. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this field. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this field. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this field. This list is a list of
- * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
@@ -99,56 +122,60 @@ public class FieldNode extends FieldVisitor {
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #FieldNode(int, int, String, String, String, Object)} version.
- *
- * @param access the field's access flags (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
- * if the field is synthetic and/or deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
- * Type}).
- * @param signature the field's signature.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must be
- * an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ *
+ * @param access
+ * the field's access flags (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+ * indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+ * Type}).
+ * @param signature
+ * the field's signature.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public FieldNode(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
- this(Opcodes.ASM4, access, name, desc, signature, value);
+ public FieldNode(final int access, final String name, final String desc,
+ final String signature, final Object value) {
+ this(Opcodes.ASM5, access, name, desc, signature, value);
+ if (getClass() != FieldNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link FieldNode}. <i>Subclasses must not use this
- * constructor</i>. Instead, they must use the
- * {@link #FieldNode(int, int, String, String, String, Object)} version.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @param access the field's access flags (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also indicates
- * if the field is synthetic and/or deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
- * Type}).
- * @param signature the field's signature.
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must be
- * an {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ * constructor</i>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param access
+ * the field's access flags (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This parameter also
+ * indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type
+ * Type}).
+ * @param signature
+ * the field's signature.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
*/
- public FieldNode(
- final int api,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final Object value)
- {
+ public FieldNode(final int api, final int access, final String name,
+ final String desc, final String signature, final Object value) {
super(api);
this.access = access;
this.name = name;
@@ -162,10 +189,8 @@ public class FieldNode extends FieldVisitor {
// ------------------------------------------------------------------------
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -182,6 +207,24 @@ public class FieldNode extends FieldVisitor {
}
@Override
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
public void visitAttribute(final Attribute attr) {
if (attrs == null) {
attrs = new ArrayList<Attribute>(1);
@@ -202,17 +245,29 @@ public class FieldNode extends FieldVisitor {
* This methods checks that this node, and all its nodes recursively, do not
* contain elements that were introduced in more recent versions of the ASM
* API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
}
/**
* Makes the given class visitor visit this field.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
@@ -230,6 +285,19 @@ public class FieldNode extends FieldVisitor {
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(fv.visitAnnotation(an.desc, false));
}
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
n = attrs == null ? 0 : attrs.size();
for (i = 0; i < n; ++i) {
fv.visitAttribute(attrs.get(i));
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
index c2564e3..8600566 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/FrameNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a stack map frame. These nodes are pseudo instruction
* nodes in order to be inserted in an instruction list. In fact these nodes
@@ -45,18 +45,19 @@ import java.util.Map;
* the target of a jump instruction, or that starts an exception handler block.
* The stack map frame types must describe the values of the local variables and
* of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
- * <br> (*) this is mandatory only for classes whose version is greater than or
- * equal to {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#V1_6 V1_6}.
- *
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or equal
+ * to {@link Opcodes#V1_6 V1_6}.
+ *
* @author Eric Bruneton
*/
public class FrameNode extends AbstractInsnNode {
/**
- * The type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for expanded
- * frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
+ * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
*/
public int type;
@@ -82,49 +83,49 @@ public class FrameNode extends AbstractInsnNode {
/**
* Constructs a new {@link FrameNode}.
- *
- * @param type the type of this frame. Must be {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_NEW} for
- * expanded frames, or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_FULL},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND}, {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_CHOP},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME} or {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_APPEND},
- * {@link org.apache.tapestry5.internal.plastic.asm.Opcodes#F_SAME1} for compressed frames.
- * @param nLocal number of local variables of this stack map frame.
- * @param local the types of the local variables of this stack map frame.
- * Elements of this list can be Integer, String or LabelNode objects
- * (for primitive, reference and uninitialized types respectively -
- * see {@link MethodVisitor}).
- * @param nStack number of operand stack elements of this stack map frame.
- * @param stack the types of the operand stack elements of this stack map
- * frame. Elements of this list can be Integer, String or LabelNode
- * objects (for primitive, reference and uninitialized types
- * respectively - see {@link MethodVisitor}).
+ *
+ * @param type
+ * the type of this frame. Must be {@link Opcodes#F_NEW} for
+ * expanded frames, or {@link Opcodes#F_FULL},
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+ * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_SAME1} for compressed frames.
+ * @param nLocal
+ * number of local variables of this stack map frame.
+ * @param local
+ * the types of the local variables of this stack map frame.
+ * Elements of this list can be Integer, String or LabelNode
+ * objects (for primitive, reference and uninitialized types
+ * respectively - see {@link MethodVisitor}).
+ * @param nStack
+ * number of operand stack elements of this stack map frame.
+ * @param stack
+ * the types of the operand stack elements of this stack map
+ * frame. Elements of this list can be Integer, String or
+ * LabelNode objects (for primitive, reference and uninitialized
+ * types respectively - see {@link MethodVisitor}).
*/
- public FrameNode(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
+ public FrameNode(final int type, final int nLocal, final Object[] local,
+ final int nStack, final Object[] stack) {
super(-1);
this.type = type;
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- this.local = asList(nLocal, local);
- this.stack = asList(nStack, stack);
- break;
- case Opcodes.F_APPEND:
- this.local = asList(nLocal, local);
- break;
- case Opcodes.F_CHOP:
- this.local = Arrays.asList(new Object[nLocal]);
- break;
- case Opcodes.F_SAME:
- break;
- case Opcodes.F_SAME1:
- this.stack = asList(1, stack);
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ this.local = asList(nLocal, local);
+ this.stack = asList(nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ this.local = asList(nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ this.local = Arrays.asList(new Object[nLocal]);
+ break;
+ case Opcodes.F_SAME:
+ break;
+ case Opcodes.F_SAME1:
+ this.stack = asList(1, stack);
+ break;
}
}
@@ -135,32 +136,30 @@ public class FrameNode extends AbstractInsnNode {
/**
* Makes the given visitor visit this stack map frame.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
@Override
public void accept(final MethodVisitor mv) {
switch (type) {
- case Opcodes.F_NEW:
- case Opcodes.F_FULL:
- mv.visitFrame(type,
- local.size(),
- asArray(local),
- stack.size(),
- asArray(stack));
- break;
- case Opcodes.F_APPEND:
- mv.visitFrame(type, local.size(), asArray(local), 0, null);
- break;
- case Opcodes.F_CHOP:
- mv.visitFrame(type, local.size(), null, 0, null);
- break;
- case Opcodes.F_SAME:
- mv.visitFrame(type, 0, null, 0, null);
- break;
- case Opcodes.F_SAME1:
- mv.visitFrame(type, 0, null, 1, asArray(stack));
- break;
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mv.visitFrame(type, local.size(), asArray(local), stack.size(),
+ asArray(stack));
+ break;
+ case Opcodes.F_APPEND:
+ mv.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_CHOP:
+ mv.visitFrame(type, local.size(), null, 0, null);
+ break;
+ case Opcodes.F_SAME:
+ mv.visitFrame(type, 0, null, 0, null);
+ break;
+ case Opcodes.F_SAME1:
+ mv.visitFrame(type, 0, null, 1, asArray(stack));
+ break;
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
index c1b13dd..729dd3e 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IincInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an IINC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class IincInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class IincInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link IincInsnNode}.
- *
- * @param var index of the local variable to be incremented.
- * @param incr increment amount to increment the local variable by.
+ *
+ * @param var
+ * index of the local variable to be incremented.
+ * @param incr
+ * increment amount to increment the local variable by.
*/
public IincInsnNode(final int var, final int incr) {
super(Opcodes.IINC);
@@ -71,10 +73,11 @@ public class IincInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIincInsn(var, incr);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IincInsnNode(var, incr);
+ return new IincInsnNode(var, incr).cloneAnnotations(this);
}
}
\ 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/InnerClassNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
index bfc16b0..877430f 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InnerClassNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
/**
* A node that represents an inner class.
- *
+ *
* @author Eric Bruneton
*/
public class InnerClassNode {
@@ -46,8 +46,8 @@ public class InnerClassNode {
/**
* The internal name of the class to which the inner class belongs (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May
- * be <tt>null</tt>.
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
*/
public String outerName;
@@ -65,25 +65,24 @@ public class InnerClassNode {
/**
* Constructs a new {@link InnerClassNode}.
- *
- * @param name the internal name of an inner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param outerName the internal name of the class to which the inner class
- * belongs (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * May be <tt>null</tt>.
- * @param innerName the (simple) name of the inner class inside its
- * enclosing class. May be <tt>null</tt> for anonymous inner
- * classes.
- * @param access the access flags of the inner class as originally declared
- * in the enclosing class.
+ *
+ * @param name
+ * the internal name of an inner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param outerName
+ * the internal name of the class to which the inner class
+ * belongs (see {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}). May be <tt>null</tt>.
+ * @param innerName
+ * the (simple) name of the inner class inside its enclosing
+ * class. May be <tt>null</tt> for anonymous inner classes.
+ * @param access
+ * the access flags of the inner class as originally declared in
+ * the enclosing class.
*/
- public InnerClassNode(
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
+ public InnerClassNode(final String name, final String outerName,
+ final String innerName, final int access) {
this.name = name;
this.outerName = outerName;
this.innerName = innerName;
@@ -92,8 +91,9 @@ public class InnerClassNode {
/**
* Makes the given class visitor visit this inner class.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
cv.visitInnerClass(name, outerName, innerName, access);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
index c4fa98a..8eaaf68 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnList.java
@@ -29,11 +29,11 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.ListIterator;
import java.util.NoSuchElementException;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A doubly linked list of {@link AbstractInsnNode} objects. <i>This
* implementation is not thread safe</i>.
@@ -63,7 +63,7 @@ public class InsnList {
/**
* Returns the number of instructions in this list.
- *
+ *
* @return the number of instructions in this list.
*/
public int size() {
@@ -72,9 +72,9 @@ public class InsnList {
/**
* Returns the first instruction in this list.
- *
- * @return the first instruction in this list, or <tt>null</tt> if the
- * list is empty.
+ *
+ * @return the first instruction in this list, or <tt>null</tt> if the list
+ * is empty.
*/
public AbstractInsnNode getFirst() {
return first;
@@ -82,7 +82,7 @@ public class InsnList {
/**
* Returns the last instruction in this list.
- *
+ *
* @return the last instruction in this list, or <tt>null</tt> if the list
* is empty.
*/
@@ -95,10 +95,12 @@ public class InsnList {
* of the instructions in this list to avoid scanning the whole list each
* time it is called. Once the cache is built, this method run in constant
* time. This cache is invalidated by all the methods that modify the list.
- *
- * @param index the index of the instruction that must be returned.
+ *
+ * @param index
+ * the index of the instruction that must be returned.
* @return the instruction whose index is given.
- * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+ * @throws IndexOutOfBoundsException
+ * if (index < 0 || index >= size()).
*/
public AbstractInsnNode get(final int index) {
if (index < 0 || index >= size) {
@@ -111,11 +113,12 @@ public class InsnList {
}
/**
- * Returns <tt>true</tt> if the given instruction belongs to this list.
- * This method always scans the instructions of this list until it finds the
+ * Returns <tt>true</tt> if the given instruction belongs to this list. This
+ * method always scans the instructions of this list until it finds the
* given instruction or reaches the end of the list.
- *
- * @param insn an instruction.
+ *
+ * @param insn
+ * an instruction.
* @return <tt>true</tt> if the given instruction belongs to this list.
*/
public boolean contains(final AbstractInsnNode insn) {
@@ -132,8 +135,9 @@ public class InsnList {
* list each time it is called. Once the cache is built, this method run in
* constant time. The cache is invalidated by all the methods that modify
* the list.
- *
- * @param insn an instruction <i>of this list</i>.
+ *
+ * @param insn
+ * an instruction <i>of this list</i>.
* @return the index of the given instruction in this list. <i>The result of
* this method is undefined if the given instruction does not belong
* to this list</i>. Use {@link #contains contains} to test if an
@@ -148,8 +152,9 @@ public class InsnList {
/**
* Makes the given visitor visit all of the instructions in this list.
- *
- * @param mv the method visitor that must visit the instructions.
+ *
+ * @param mv
+ * the method visitor that must visit the instructions.
*/
public void accept(final MethodVisitor mv) {
AbstractInsnNode insn = first;
@@ -161,7 +166,7 @@ public class InsnList {
/**
* Returns an iterator over the instructions in this list.
- *
+ *
* @return an iterator over the instructions in this list.
*/
public ListIterator<AbstractInsnNode> iterator() {
@@ -170,7 +175,7 @@ public class InsnList {
/**
* Returns an iterator over the instructions in this list.
- *
+ *
* @return an iterator over the instructions in this list.
*/
@SuppressWarnings("unchecked")
@@ -180,7 +185,7 @@ public class InsnList {
/**
* Returns an array containing all of the instructions in this list.
- *
+ *
* @return an array containing all of the instructions in this list.
*/
public AbstractInsnNode[] toArray() {
@@ -197,10 +202,12 @@ public class InsnList {
/**
* Replaces an instruction of this list with another instruction.
- *
- * @param location an instruction <i>of this list</i>.
- * @param insn another instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i>.
+ * @param insn
+ * another instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
AbstractInsnNode next = location.next;
@@ -231,9 +238,10 @@ public class InsnList {
/**
* Adds the given instruction to the end of this list.
- *
- * @param insn an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param insn
+ * an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void add(final AbstractInsnNode insn) {
++size;
@@ -251,9 +259,10 @@ public class InsnList {
/**
* Adds the given instructions to the end of this list.
- *
- * @param insns an instruction list, which is cleared during the process.
- * This list must be different from 'this'.
+ *
+ * @param insns
+ * an instruction list, which is cleared during the process. This
+ * list must be different from 'this'.
*/
public void add(final InsnList insns) {
if (insns.size == 0) {
@@ -275,9 +284,10 @@ public class InsnList {
/**
* Inserts the given instruction at the begining of this list.
- *
- * @param insn an instruction, <i>which must not belong to any
- * {@link InsnList}</i>.
+ *
+ * @param insn
+ * an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
*/
public void insert(final AbstractInsnNode insn) {
++size;
@@ -295,9 +305,10 @@ public class InsnList {
/**
* Inserts the given instructions at the begining of this list.
- *
- * @param insns an instruction list, which is cleared during the process.
- * This list must be different from 'this'.
+ *
+ * @param insns
+ * an instruction list, which is cleared during the process. This
+ * list must be different from 'this'.
*/
public void insert(final InsnList insns) {
if (insns.size == 0) {
@@ -319,13 +330,16 @@ public class InsnList {
/**
* Inserts the given instruction after the specified instruction.
- *
- * @param location an instruction <i>of this list</i> after which insn must be
- * inserted.
- * @param insn the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i> after which insn must be
+ * inserted.
+ * @param insn
+ * the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
*/
- public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ public void insert(final AbstractInsnNode location,
+ final AbstractInsnNode insn) {
++size;
AbstractInsnNode next = location.next;
if (next == null) {
@@ -342,11 +356,13 @@ public class InsnList {
/**
* Inserts the given instructions after the specified instruction.
- *
- * @param location an instruction <i>of this list</i> after which the
- * instructions must be inserted.
- * @param insns the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
+ *
+ * @param location
+ * an instruction <i>of this list</i> after which the
+ * instructions must be inserted.
+ * @param insns
+ * the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
*/
public void insert(final AbstractInsnNode location, final InsnList insns) {
if (insns.size == 0) {
@@ -370,13 +386,16 @@ public class InsnList {
/**
* Inserts the given instruction before the specified instruction.
- *
- * @param location an instruction <i>of this list</i> before which insn must be
- * inserted.
- * @param insn the instruction to be inserted, <i>which must not belong to
- * any {@link InsnList}</i>.
+ *
+ * @param location
+ * an instruction <i>of this list</i> before which insn must be
+ * inserted.
+ * @param insn
+ * the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
*/
- public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ public void insertBefore(final AbstractInsnNode location,
+ final AbstractInsnNode insn) {
++size;
AbstractInsnNode prev = location.prev;
if (prev == null) {
@@ -393,38 +412,40 @@ public class InsnList {
/**
* Inserts the given instructions before the specified instruction.
- *
- * @param location an instruction <i>of this list</i> before which the instructions
- * must be inserted.
- * @param insns the instruction list to be inserted, which is cleared during
- * the process. This list must be different from 'this'.
+ *
+ * @param location
+ * an instruction <i>of this list</i> before which the
+ * instructions must be inserted.
+ * @param insns
+ * the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
*/
- public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+ public void insertBefore(final AbstractInsnNode location,
+ final InsnList insns) {
if (insns.size == 0) {
return;
}
size += insns.size;
AbstractInsnNode ifirst = insns.first;
AbstractInsnNode ilast = insns.last;
- AbstractInsnNode prev = location .prev;
+ AbstractInsnNode prev = location.prev;
if (prev == null) {
first = ifirst;
} else {
prev.next = ifirst;
}
- location .prev = ilast;
- ilast.next = location ;
+ location.prev = ilast;
+ ilast.next = location;
ifirst.prev = prev;
cache = null;
insns.removeAll(false);
}
-
-
/**
* Removes the given instruction from this list.
- *
- * @param insn the instruction <i>of this list</i> that must be removed.
+ *
+ * @param insn
+ * the instruction <i>of this list</i> that must be removed.
*/
public void remove(final AbstractInsnNode insn) {
--size;
@@ -455,9 +476,10 @@ public class InsnList {
/**
* Removes all of the instructions of this list.
- *
- * @param mark if the instructions must be marked as no longer belonging to
- * any {@link InsnList}.
+ *
+ * @param mark
+ * if the instructions must be marked as no longer belonging to
+ * any {@link InsnList}.
*/
void removeAll(final boolean mark) {
if (mark) {
@@ -499,14 +521,16 @@ public class InsnList {
}
// this class is not generified because it will create bridges
- private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ {
+ private final class InsnListIterator implements ListIterator {
AbstractInsnNode next;
AbstractInsnNode prev;
+ AbstractInsnNode remove;
+
InsnListIterator(int index) {
- if(index==size()) {
+ if (index == size()) {
next = null;
prev = getLast();
} else {
@@ -526,12 +550,22 @@ public class InsnList {
AbstractInsnNode result = next;
prev = result;
next = result.next;
+ remove = result;
return result;
}
public void remove() {
- InsnList.this.remove(prev);
- prev = prev.prev;
+ if (remove != null) {
+ if (remove == next) {
+ next = next.next;
+ } else {
+ prev = prev.prev;
+ }
+ InsnList.this.remove(remove);
+ remove = null;
+ } else {
+ throw new IllegalStateException();
+ }
}
public boolean hasPrevious() {
@@ -542,6 +576,7 @@ public class InsnList {
AbstractInsnNode result = prev;
next = result;
prev = result.prev;
+ remove = result;
return result;
}
@@ -568,6 +603,7 @@ public class InsnList {
public void add(Object o) {
InsnList.this.insertBefore(next, (AbstractInsnNode) o);
prev = (AbstractInsnNode) o;
+ remove = null;
}
public void set(Object o) {
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
index 6abed41..7eb2359 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InsnNode.java
@@ -29,34 +29,36 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a zero operand instruction.
- *
+ *
* @author Eric Bruneton
*/
public class InsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link InsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed. This
- * opcode must be 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, IALOAD, LALOAD,
- * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, 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, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
- * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
- * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
- * MONITORENTER, or MONITOREXIT.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed. This opcode
+ * must be 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, IALOAD,
+ * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+ * 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, I2L, I2F, I2D,
+ * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+ * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+ * or MONITOREXIT.
*/
public InsnNode(final int opcode) {
super(opcode);
@@ -69,16 +71,18 @@ public class InsnNode extends AbstractInsnNode {
/**
* Makes the given visitor visit this instruction.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
@Override
public void accept(final MethodVisitor mv) {
mv.visitInsn(opcode);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InsnNode(opcode);
+ return new InsnNode(opcode).cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
index 03c0d54..5b0c351 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/IntInsnNode.java
@@ -29,13 +29,13 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents an instruction with a single int operand.
- *
+ *
* @author Eric Bruneton
*/
public class IntInsnNode extends AbstractInsnNode {
@@ -47,10 +47,12 @@ public class IntInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link IntInsnNode}.
- *
- * @param opcode the opcode of the instruction to be constructed. This
- * opcode must be BIPUSH, SIPUSH or NEWARRAY.
- * @param operand the operand of the instruction to be constructed.
+ *
+ * @param opcode
+ * the opcode of the instruction to be constructed. This opcode
+ * must be BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand
+ * the operand of the instruction to be constructed.
*/
public IntInsnNode(final int opcode, final int operand) {
super(opcode);
@@ -59,9 +61,10 @@ public class IntInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be BIPUSH,
- * SIPUSH or NEWARRAY.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be BIPUSH, SIPUSH
+ * or NEWARRAY.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -75,10 +78,11 @@ public class IntInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitIntInsn(opcode, operand);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new IntInsnNode(opcode, operand);
+ return new IntInsnNode(opcode, operand).cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
index d67b72f..2578768 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/InvokeDynamicInsnNode.java
@@ -29,15 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.Handle;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an invokedynamic instruction.
- *
+ *
* @author Remi Forax
*/
public class InvokeDynamicInsnNode extends AbstractInsnNode {
@@ -64,18 +64,18 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link InvokeDynamicInsnNode}.
- *
- * @param name invokedynamic name.
- * @param desc invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param bsm the bootstrap method.
- * @param bsmArgs the boostrap constant arguments.
+ *
+ * @param name
+ * invokedynamic name.
+ * @param desc
+ * invokedynamic descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the boostrap constant arguments.
*/
- public InvokeDynamicInsnNode(
- final String name,
- final String desc,
- final Handle bsm,
- final Object... bsmArgs)
- {
+ public InvokeDynamicInsnNode(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
super(Opcodes.INVOKEDYNAMIC);
this.name = name;
this.desc = desc;
@@ -91,10 +91,12 @@ public class InvokeDynamicInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
+ return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs)
+ .cloneAnnotations(this);
}
}
\ 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/JumpInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
index d0011a2..386c900 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/JumpInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a jump instruction. A jump instruction is an
* instruction that may jump to another instruction.
- *
+ *
* @author Eric Bruneton
*/
public class JumpInsnNode extends AbstractInsnNode {
@@ -49,14 +49,16 @@ public class JumpInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link JumpInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
- * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
- * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
- * @param label the operand of the instruction to be constructed. This
- * operand is a label that designates the instruction to which the
- * jump instruction may jump.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label
+ * the operand of the instruction to be constructed. This operand
+ * is a label that designates the instruction to which the jump
+ * instruction may jump.
*/
public JumpInsnNode(final int opcode, final LabelNode label) {
super(opcode);
@@ -65,11 +67,12 @@ public class JumpInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
- * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
- * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
- * IFNULL or IFNONNULL.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be IFEQ, IFNE,
+ * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+ * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO,
+ * JSR, IFNULL or IFNONNULL.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -83,10 +86,12 @@ public class JumpInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitJumpInsn(opcode, label.getLabel());
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new JumpInsnNode(opcode, clone(label, labels));
+ return new JumpInsnNode(opcode, clone(label, labels))
+ .cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
index a21f0d0..39c08ef 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LabelNode.java
@@ -29,11 +29,11 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.Label;
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import java.util.Map;
-
/**
* An {@link AbstractInsnNode} that encapsulates a {@link Label}.
*/
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
index 82748cb..e048e74 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LdcInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents an LDC instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LdcInsnNode extends AbstractInsnNode {
@@ -50,10 +50,11 @@ public class LdcInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link LdcInsnNode}.
- *
- * @param cst the constant to be loaded on the stack. This parameter must be
- * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
- * {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
*/
public LdcInsnNode(final Object cst) {
super(Opcodes.LDC);
@@ -68,10 +69,11 @@ public class LdcInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitLdcInsn(cst);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new LdcInsnNode(cst);
+ return new LdcInsnNode(cst).cloneAnnotations(this);
}
}
\ 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/LineNumberNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
index fe4d39b..c475ee8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LineNumberNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a line number declaration. These nodes are pseudo
* instruction nodes in order to be inserted in an instruction list.
- *
+ *
* @author Eric Bruneton
*/
public class LineNumberNode extends AbstractInsnNode {
@@ -54,10 +54,12 @@ public class LineNumberNode extends AbstractInsnNode {
/**
* Constructs a new {@link LineNumberNode}.
- *
- * @param line a line number. This number refers to the source file from
- * which the class was compiled.
- * @param start the first instruction corresponding to this line number.
+ *
+ * @param line
+ * a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start
+ * the first instruction corresponding to this line number.
*/
public LineNumberNode(final int line, final LabelNode start) {
super(-1);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
new file mode 100644
index 0000000..27f6e09
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableAnnotationNode.java
@@ -0,0 +1,157 @@
+/***
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotation on a local or resource variable.
+ *
+ * @author Eric Bruneton
+ */
+public class LocalVariableAnnotationNode extends TypeAnnotationNode {
+
+ /**
+ * The fist instructions corresponding to the continuous ranges that make
+ * the scope of this local variable (inclusive). Must not be <tt>null</tt>.
+ */
+ public List<LabelNode> start;
+
+ /**
+ * The last instructions corresponding to the continuous ranges that make
+ * the scope of this local variable (exclusive). This list must have the
+ * same size as the 'start' list. Must not be <tt>null</tt>.
+ */
+ public List<LabelNode> end;
+
+ /**
+ * The local variable's index in each range. This list must have the same
+ * size as the 'start' list. Must not be <tt>null</tt>.
+ */
+ public List<Integer> index;
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the
+ * {@link #LocalVariableAnnotationNode(int, TypePath, LabelNode[], LabelNode[], int[], String)}
+ * version.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(int typeRef, TypePath typePath,
+ LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+ this(Opcodes.ASM5, typeRef, typePath, start, end, index, desc);
+ }
+
+ /**
+ * Constructs a new {@link LocalVariableAnnotationNode}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public LocalVariableAnnotationNode(int api, int typeRef, TypePath typePath,
+ LabelNode[] start, LabelNode[] end, int[] index, String desc) {
+ super(api, typeRef, typePath, desc);
+ this.start = new ArrayList<LabelNode>(start.length);
+ this.start.addAll(Arrays.asList(start));
+ this.end = new ArrayList<LabelNode>(end.length);
+ this.end.addAll(Arrays.asList(end));
+ this.index = new ArrayList<Integer>(index.length);
+ for (int i : index) {
+ this.index.add(i);
+ }
+ }
+
+ /**
+ * Makes the given visitor visit this type annotation.
+ *
+ * @param mv
+ * the visitor that must visit this annotation.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ */
+ public void accept(final MethodVisitor mv, boolean visible) {
+ Label[] start = new Label[this.start.size()];
+ Label[] end = new Label[this.end.size()];
+ int[] index = new int[this.index.size()];
+ for (int i = 0; i < start.length; ++i) {
+ start[i] = this.start.get(i).getLabel();
+ end[i] = this.end.get(i).getLabel();
+ index[i] = this.index.get(i);
+ }
+ accept(mv.visitLocalVariableAnnotation(typeRef, typePath, start, end,
+ index, desc, true));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
index 8494414..775a6e8 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LocalVariableNode.java
@@ -33,7 +33,7 @@ import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a local variable declaration.
- *
+ *
* @author Eric Bruneton
*/
public class LocalVariableNode {
@@ -72,25 +72,25 @@ public class LocalVariableNode {
/**
* Constructs a new {@link LocalVariableNode}.
- *
- * @param name the name of a local variable.
- * @param desc the type descriptor of this local variable.
- * @param signature the signature of this local variable. May be
- * <tt>null</tt>.
- * @param start the first instruction corresponding to the scope of this
- * local variable (inclusive).
- * @param end the last instruction corresponding to the scope of this local
- * variable (exclusive).
- * @param index the local variable's index.
+ *
+ * @param name
+ * the name of a local variable.
+ * @param desc
+ * the type descriptor of this local variable.
+ * @param signature
+ * the signature of this local variable. May be <tt>null</tt>.
+ * @param start
+ * the first instruction corresponding to the scope of this local
+ * variable (inclusive).
+ * @param end
+ * the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index
+ * the local variable's index.
*/
- public LocalVariableNode(
- final String name,
- final String desc,
- final String signature,
- final LabelNode start,
- final LabelNode end,
- final int index)
- {
+ public LocalVariableNode(final String name, final String desc,
+ final String signature, final LabelNode start, final LabelNode end,
+ final int index) {
this.name = name;
this.desc = desc;
this.signature = signature;
@@ -101,15 +101,12 @@ public class LocalVariableNode {
/**
* Makes the given visitor visit this local variable declaration.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- mv.visitLocalVariable(name,
- desc,
- signature,
- start.getLabel(),
- end.getLabel(),
- index);
+ mv.visitLocalVariable(name, desc, signature, start.getLabel(),
+ end.getLabel(), index);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
index 5beca30..af635d7 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/LookupSwitchInsnNode.java
@@ -29,18 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a LOOKUPSWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class LookupSwitchInsnNode extends AbstractInsnNode {
@@ -63,21 +63,22 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link LookupSwitchInsnNode}.
- *
- * @param dflt beginning of the default handler block.
- * @param keys the values of the keys.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ *
+ * @param dflt
+ * beginning of the default handler block.
+ * @param keys
+ * the values of the keys.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>keys[i]</tt> key.
*/
- public LookupSwitchInsnNode(
- final LabelNode dflt,
- final int[] keys,
- final LabelNode[] labels)
- {
+ public LookupSwitchInsnNode(final LabelNode dflt, final int[] keys,
+ final LabelNode[] labels) {
super(Opcodes.LOOKUPSWITCH);
this.dflt = dflt;
this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
- this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length);
+ this.labels = new ArrayList<LabelNode>(labels == null ? 0
+ : labels.length);
if (keys != null) {
for (int i = 0; i < keys.length; ++i) {
this.keys.add(new Integer(keys[i]));
@@ -104,6 +105,7 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+ acceptAnnotations(mv);
}
@Override
@@ -111,6 +113,6 @@ public class LookupSwitchInsnNode extends AbstractInsnNode {
LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
labels), null, clone(this.labels, labels));
clone.keys.addAll(keys);
- return clone;
+ return clone.cloneAnnotations(this);
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
index f87234c..5d0c730 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodInsnNode.java
@@ -29,14 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a method instruction. A method instruction is an
* instruction that invokes a method.
- *
+ *
* @author Eric Bruneton
*/
public class MethodInsnNode extends AbstractInsnNode {
@@ -58,33 +59,65 @@ public class MethodInsnNode extends AbstractInsnNode {
public String desc;
/**
+ * If the method's owner class if an interface.
+ */
+ public boolean itf;
+
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ */
+ @Deprecated
+ public MethodInsnNode(final int opcode, final String owner,
+ final String name, final String desc) {
+ this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE);
+ }
+
+ /**
* Constructs a new {@link MethodInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner the internal name of the method's owner class (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName()
+ * getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param itf
+ * if the method's owner class is an interface.
*/
- public MethodInsnNode(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public MethodInsnNode(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
super(opcode);
this.owner = owner;
this.name = name;
this.desc = desc;
+ this.itf = itf;
}
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be
- * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be INVOKEVIRTUAL,
+ * INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -97,11 +130,11 @@ public class MethodInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
- mv.visitMethodInsn(opcode, owner, name, desc);
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MethodInsnNode(opcode, owner, name, desc);
+ return new MethodInsnNode(opcode, owner, name, desc, itf);
}
}
\ No newline at end of file
[08/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..0656c65
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,358 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+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.IntInsnNode;
+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;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+ Opcodes {
+
+ public BasicInterpreter() {
+ super(ASM5);
+ }
+
+ protected BasicInterpreter(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue newOperation(final AbstractInsnNode insn)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(Type.getObjectType("null"));
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ if (cst instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (cst instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (cst instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (cst instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (cst instanceof String) {
+ return newValue(Type.getObjectType("java/lang/String"));
+ } else if (cst instanceof Type) {
+ int sort = ((Type) cst).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ return newValue(Type.getObjectType("java/lang/Class"));
+ } else if (sort == Type.METHOD) {
+ return newValue(Type
+ .getObjectType("java/lang/invoke/MethodType"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant "
+ + cst);
+ }
+ } else if (cst instanceof Handle) {
+ return newValue(Type
+ .getObjectType("java/lang/invoke/MethodHandle"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant "
+ + cst);
+ }
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ throw new AnalyzerException(insn, "Invalid array type");
+ }
+ case ANEWARRAY:
+ String desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getType("[" + Type.getObjectType(desc)));
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getObjectType(desc));
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue binaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ return BasicValue.REFERENCE_VALUE;
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException {
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn,
+ final List<? extends BasicValue> values) throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else if (opcode == INVOKEDYNAMIC) {
+ return newValue(Type
+ .getReturnType(((InvokeDynamicInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+ }
+ }
+
+ @Override
+ public void returnOperation(final AbstractInsnNode insn,
+ final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..44b0704
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,111 @@
+/***
+ * 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 org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ *
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+ public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+ public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ public static final BasicValue DOUBLE_VALUE = new BasicValue(
+ Type.DOUBLE_TYPE);
+
+ public static final BasicValue REFERENCE_VALUE = new BasicValue(
+ Type.getObjectType("java/lang/Object"));
+
+ public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(
+ Type.VOID_TYPE);
+
+ private final Type type;
+
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ public boolean isReference() {
+ return type != null
+ && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..50f4a84
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,433 @@
+/***
+ * 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.List;
+
+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.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+ public BasicVerifier() {
+ super(ASM5);
+ }
+
+ protected BasicVerifier(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return value;
+ case ASTORE:
+ if (!value.isReference()
+ && !BasicValue.RETURNADDRESS_VALUE.equals(value)) {
+ throw new AnalyzerException(insn, null,
+ "an object reference or a return address", value);
+ }
+ return value;
+ default:
+ return value;
+ }
+ if (!expected.equals(value)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn,
+ final BasicValue value) throws AnalyzerException {
+ BasicValue expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type
+ .getObjectType(((FieldInsnNode) insn).owner));
+ break;
+ case CHECKCAST:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(insn, null, "an array reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn, null, "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return super.unaryOperation(insn, value);
+ }
+
+ @Override
+ public BasicValue binaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2)
+ throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fin = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getObjectType(fin.owner));
+ expected2 = newValue(Type.getType(fin.desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", expected1,
+ value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException(insn, "Second argument", expected2,
+ value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(final AbstractInsnNode insn,
+ final BasicValue value1, final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException {
+ BasicValue expected1;
+ BasicValue expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", "a "
+ + expected1 + " array reference", value1);
+ } else if (!BasicValue.INT_VALUE.equals(value2)) {
+ throw new AnalyzerException(insn, "Second argument",
+ BasicValue.INT_VALUE, value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException(insn, "Third argument", expected3,
+ value3);
+ }
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn,
+ final List<? extends BasicValue> values) throws AnalyzerException {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (int i = 0; i < values.size(); ++i) {
+ if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+ throw new AnalyzerException(insn, null,
+ BasicValue.INT_VALUE, values.get(i));
+ }
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+ Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+ if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+ throw new AnalyzerException(insn, "Method owner",
+ newValue(owner), values.get(0));
+ }
+ }
+ String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
+ : ((MethodInsnNode) insn).desc;
+ Type[] args = Type.getArgumentTypes(desc);
+ while (i < values.size()) {
+ BasicValue expected = newValue(args[j++]);
+ BasicValue encountered = values.get(i++);
+ if (!isSubTypeOf(encountered, expected)) {
+ throw new AnalyzerException(insn, "Argument " + j,
+ expected, encountered);
+ }
+ }
+ }
+ return super.naryOperation(insn, values);
+ }
+
+ @Override
+ public void returnOperation(final AbstractInsnNode insn,
+ final BasicValue value, final BasicValue expected)
+ throws AnalyzerException {
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, "Incompatible return type",
+ expected, value);
+ }
+ }
+
+ protected boolean isArrayValue(final BasicValue value) {
+ return value.isReference();
+ }
+
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ protected boolean isSubTypeOf(final BasicValue value,
+ final BasicValue expected) {
+ return value.equals(expected);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000..fdbb0a9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Frame.java
@@ -0,0 +1,738 @@
+/***
+ * 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.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.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InvokeDynamicInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MultiANewArrayInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot in
+ * the operand stack.
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Frame<V extends Value> {
+
+ /**
+ * The expected return type of the analyzed method, or <tt>null</tt> if the
+ * method returns void.
+ */
+ private V returnValue;
+
+ /**
+ * The local variables and operand stack of this frame.
+ */
+ private V[] values;
+
+ /**
+ * The number of local variables of this frame.
+ */
+ private int locals;
+
+ /**
+ * The number of elements in the operand stack.
+ */
+ private int top;
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals
+ * the maximum number of local variables of the frame.
+ * @param nStack
+ * the maximum stack size of the frame.
+ */
+ public Frame(final int nLocals, final int nStack) {
+ this.values = (V[]) new Value[nLocals + nStack];
+ this.locals = nLocals;
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src
+ * a frame.
+ */
+ public Frame(final Frame<? extends V> src) {
+ this(src.locals, src.values.length - src.locals);
+ init(src);
+ }
+
+ /**
+ * Copies the state of the given frame into this frame.
+ *
+ * @param src
+ * a frame.
+ * @return this frame.
+ */
+ public Frame<V> init(final Frame<? extends V> src) {
+ returnValue = src.returnValue;
+ System.arraycopy(src.values, 0, values, 0, values.length);
+ top = src.top;
+ return this;
+ }
+
+ /**
+ * Sets the expected return type of the analyzed method.
+ *
+ * @param v
+ * the expected return type of the analyzed method, or
+ * <tt>null</tt> if the method returns void.
+ */
+ public void setReturn(final V v) {
+ returnValue = v;
+ }
+
+ /**
+ * Returns the maximum number of local variables of this frame.
+ *
+ * @return the maximum number of local variables of this frame.
+ */
+ public int getLocals() {
+ return locals;
+ }
+
+ /**
+ * Returns the maximum stack size of this frame.
+ *
+ * @return the maximum stack size of this frame.
+ */
+ public int getMaxStackSize() {
+ return values.length - locals;
+ }
+
+ /**
+ * Returns the value of the given local variable.
+ *
+ * @param i
+ * a local variable index.
+ * @return the value of the given local variable.
+ * @throws IndexOutOfBoundsException
+ * if the variable does not exist.
+ */
+ public V getLocal(final int i) throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException(
+ "Trying to access an inexistant local variable");
+ }
+ return values[i];
+ }
+
+ /**
+ * Sets the value of the given local variable.
+ *
+ * @param i
+ * a local variable index.
+ * @param value
+ * the new value of this local variable.
+ * @throws IndexOutOfBoundsException
+ * if the variable does not exist.
+ */
+ public void setLocal(final int i, final V value)
+ throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException(
+ "Trying to access an inexistant local variable " + i);
+ }
+ values[i] = value;
+ }
+
+ /**
+ * Returns the number of values in the operand stack of this frame. Long and
+ * double values are treated as single values.
+ *
+ * @return the number of values in the operand stack of this frame.
+ */
+ public int getStackSize() {
+ return top;
+ }
+
+ /**
+ * Returns the value of the given operand stack slot.
+ *
+ * @param i
+ * the index of an operand stack slot.
+ * @return the value of the given operand stack slot.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack slot does not exist.
+ */
+ public V getStack(final int i) throws IndexOutOfBoundsException {
+ return values[i + locals];
+ }
+
+ /**
+ * Clears the operand stack of this frame.
+ */
+ public void clearStack() {
+ top = 0;
+ }
+
+ /**
+ * Pops a value from the operand stack of this frame.
+ *
+ * @return the value that has been popped from the stack.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack is empty.
+ */
+ public V pop() throws IndexOutOfBoundsException {
+ if (top == 0) {
+ throw new IndexOutOfBoundsException(
+ "Cannot pop operand off an empty stack.");
+ }
+ return values[--top + locals];
+ }
+
+ /**
+ * Pushes a value into the operand stack of this frame.
+ *
+ * @param value
+ * the value that must be pushed into the stack.
+ * @throws IndexOutOfBoundsException
+ * if the operand stack is full.
+ */
+ public void push(final V value) throws IndexOutOfBoundsException {
+ if (top + locals >= values.length) {
+ throw new IndexOutOfBoundsException(
+ "Insufficient maximum stack size.");
+ }
+ values[top++ + locals] = value;
+ }
+
+ public void execute(final AbstractInsnNode insn,
+ final Interpreter<V> interpreter) throws AnalyzerException {
+ V value1, value2, value3, value4;
+ List<V> values;
+ int var;
+
+ switch (insn.getOpcode()) {
+ case Opcodes.NOP:
+ break;
+ case Opcodes.ACONST_NULL:
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.LDC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.LLOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.DLOAD:
+ case Opcodes.ALOAD:
+ push(interpreter.copyOperation(insn,
+ getLocal(((VarInsnNode) insn).var)));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.LALOAD:
+ case Opcodes.FALOAD:
+ case Opcodes.DALOAD:
+ case Opcodes.AALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.LSTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.DSTORE:
+ case Opcodes.ASTORE:
+ value1 = interpreter.copyOperation(insn, pop());
+ var = ((VarInsnNode) insn).var;
+ setLocal(var, value1);
+ if (value1.getSize() == 2) {
+ setLocal(var + 1, interpreter.newValue(null));
+ }
+ if (var > 0) {
+ Value local = getLocal(var - 1);
+ if (local != null && local.getSize() == 2) {
+ setLocal(var - 1, interpreter.newValue(null));
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.LASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.DASTORE:
+ case Opcodes.AASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ value3 = pop();
+ value2 = pop();
+ value1 = pop();
+ interpreter.ternaryOperation(insn, value1, value2, value3);
+ break;
+ case Opcodes.POP:
+ if (pop().getSize() == 2) {
+ throw new AnalyzerException(insn, "Illegal use of POP");
+ }
+ break;
+ case Opcodes.POP2:
+ if (pop().getSize() == 1) {
+ if (pop().getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of POP2");
+ }
+ }
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ if (value1.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP");
+ }
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+ case Opcodes.DUP2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(value2);
+ push(value1);
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2");
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ value4 = pop();
+ if (value4.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value4);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+ case Opcodes.SWAP:
+ value2 = pop();
+ value1 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of SWAP");
+ }
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.IADD:
+ case Opcodes.LADD:
+ case Opcodes.FADD:
+ case Opcodes.DADD:
+ case Opcodes.ISUB:
+ case Opcodes.LSUB:
+ case Opcodes.FSUB:
+ case Opcodes.DSUB:
+ case Opcodes.IMUL:
+ case Opcodes.LMUL:
+ case Opcodes.FMUL:
+ case Opcodes.DMUL:
+ case Opcodes.IDIV:
+ case Opcodes.LDIV:
+ case Opcodes.FDIV:
+ case Opcodes.DDIV:
+ case Opcodes.IREM:
+ case Opcodes.LREM:
+ case Opcodes.FREM:
+ case Opcodes.DREM:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ISHL:
+ case Opcodes.LSHL:
+ case Opcodes.ISHR:
+ case Opcodes.LSHR:
+ case Opcodes.IUSHR:
+ case Opcodes.LUSHR:
+ case Opcodes.IAND:
+ case Opcodes.LAND:
+ case Opcodes.IOR:
+ case Opcodes.LOR:
+ case Opcodes.IXOR:
+ case Opcodes.LXOR:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IINC:
+ var = ((IincInsnNode) insn).var;
+ setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+ break;
+ case Opcodes.I2L:
+ case Opcodes.I2F:
+ case Opcodes.I2D:
+ case Opcodes.L2I:
+ case Opcodes.L2F:
+ case Opcodes.L2D:
+ case Opcodes.F2I:
+ case Opcodes.F2L:
+ case Opcodes.F2D:
+ case Opcodes.D2I:
+ case Opcodes.D2L:
+ case Opcodes.D2F:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.GOTO:
+ break;
+ case Opcodes.JSR:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.RET:
+ break;
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ value1 = pop();
+ interpreter.unaryOperation(insn, value1);
+ interpreter.returnOperation(insn, value1, returnValue);
+ break;
+ case Opcodes.RETURN:
+ if (returnValue != null) {
+ throw new AnalyzerException(insn, "Incompatible return type");
+ }
+ break;
+ case Opcodes.GETSTATIC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.PUTSTATIC:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.GETFIELD:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.PUTFIELD:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE: {
+ values = new ArrayList<V>();
+ String desc = ((MethodInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.INVOKEDYNAMIC: {
+ values = new ArrayList<V>();
+ String desc = ((InvokeDynamicInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.NEW:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.NEWARRAY:
+ case Opcodes.ANEWARRAY:
+ case Opcodes.ARRAYLENGTH:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ATHROW:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.CHECKCAST:
+ case Opcodes.INSTANCEOF:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ values = new ArrayList<V>();
+ for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+ values.add(0, pop());
+ }
+ push(interpreter.naryOperation(insn, values));
+ break;
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ default:
+ throw new RuntimeException("Illegal opcode " + insn.getOpcode());
+ }
+ }
+
+ /**
+ * Merges this frame with the given frame.
+ *
+ * @param frame
+ * a frame.
+ * @param interpreter
+ * the interpreter used to merge values.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ * @throws AnalyzerException
+ * if the frames have incompatible sizes.
+ */
+ public boolean merge(final Frame<? extends V> frame,
+ final Interpreter<V> interpreter) throws AnalyzerException {
+ if (top != frame.top) {
+ throw new AnalyzerException(null, "Incompatible stack heights");
+ }
+ boolean changes = false;
+ for (int i = 0; i < locals + top; ++i) {
+ V v = interpreter.merge(values[i], frame.values[i]);
+ if (!v.equals(values[i])) {
+ values[i] = v;
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Merges this frame with the given frame (case of a RET instruction).
+ *
+ * @param frame
+ * a frame
+ * @param access
+ * the local variables that have been accessed by the subroutine
+ * to which the RET instruction corresponds.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ */
+ public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
+ boolean changes = false;
+ for (int i = 0; i < locals; ++i) {
+ if (!access[i] && !values[i].equals(frame.values[i])) {
+ values[i] = frame.values[i];
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Returns a string representation of this frame.
+ *
+ * @return a string representation of this frame.
+ */
+ @Override
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < getLocals(); ++i) {
+ b.append(getLocal(i));
+ }
+ b.append(' ');
+ for (int i = 0; i < getStackSize(); ++i) {
+ b.append(getStack(i).toString());
+ }
+ return b.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000..b7c94c8
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,226 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class Interpreter<V extends Value> {
+
+ protected final int api;
+
+ protected Interpreter(final int api) {
+ this.api = api;
+ }
+
+ /**
+ * Creates a new value that represents the given type.
+ *
+ * Called for method parameters (including <code>this</code>), exception
+ * handler variable and with <code>null</code> type for variables reserved
+ * by long and double types.
+ *
+ * @param type
+ * a primitive or reference type, or <tt>null</tt> to represent
+ * an uninitialized value.
+ * @return a value that represents the given type. The size of the returned
+ * value must be equal to the size of the given type.
+ */
+ public abstract V newValue(Type type);
+
+ /**
+ * Interprets a bytecode instruction without arguments. This method is
+ * called for the following opcodes:
+ *
+ * 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, JSR, GETSTATIC, NEW
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V newOperation(AbstractInsnNode insn)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction that moves a value on the stack or to
+ * or from local variables. This method is called for the following opcodes:
+ *
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+ * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the value that must be moved by the instruction.
+ * @return the result of the interpretation of the given instruction. The
+ * returned value must be <tt>equal</tt> to the given value.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V copyOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a single argument. This method is
+ * called for the following opcodes:
+ *
+ * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+ * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+ * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+ * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+ * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V unaryOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with two arguments. This method is
+ * called for the following opcodes:
+ *
+ * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+ * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+ * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value1
+ * the first argument of the instruction to be interpreted.
+ * @param value2
+ * the second argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with three arguments. This method is
+ * called for the following opcodes:
+ *
+ * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value1
+ * the first argument of the instruction to be interpreted.
+ * @param value2
+ * the second argument of the instruction to be interpreted.
+ * @param value3
+ * the third argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V ternaryOperation(AbstractInsnNode insn, V value1,
+ V value2, V value3) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a variable number of arguments.
+ * This method is called for the following opcodes:
+ *
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+ * MULTIANEWARRAY and INVOKEDYNAMIC
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param values
+ * the arguments of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract V naryOperation(AbstractInsnNode insn,
+ List<? extends V> values) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode return instruction. This method is called for the
+ * following opcodes:
+ *
+ * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+ *
+ * @param insn
+ * the bytecode instruction to be interpreted.
+ * @param value
+ * the argument of the instruction to be interpreted.
+ * @param expected
+ * the expected return type of the analyzed method.
+ * @throws AnalyzerException
+ * if an error occured during the interpretation.
+ */
+ public abstract void returnOperation(AbstractInsnNode insn, V value,
+ V expected) throws AnalyzerException;
+
+ /**
+ * Merges two values. The merge operation must return a value that
+ * represents both values (for instance, if the two values are two types,
+ * the merged value must be a common super type of the two types. If the two
+ * values are integer intervals, the merged value must be an interval that
+ * contains the previous ones. Likewise for other types of values).
+ *
+ * @param v
+ * a value.
+ * @param w
+ * another value.
+ * @return the merged value. If the merged value is equal to <tt>v</tt>,
+ * this method <i>must</i> return <tt>v</tt>.
+ */
+ public abstract V merge(V v, V w);
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000..c53beb4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,320 @@
+/***
+ * 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.List;
+
+import org.apache.tapestry5.internal.plastic.asm.Type;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+ /**
+ * The class that is verified.
+ */
+ private final Type currentClass;
+
+ /**
+ * The super class of the class that is verified.
+ */
+ private final Type currentSuperClass;
+
+ /**
+ * The interfaces implemented by the class that is verified.
+ */
+ private final List<Type> currentClassInterfaces;
+
+ /**
+ * If the class that is verified is an interface.
+ */
+ private final boolean isInterface;
+
+ /**
+ * The loader to use for referenced classes.
+ */
+ private ClassLoader loader = getClass().getClassLoader();
+
+ /**
+ * Constructs a new {@link SimpleVerifier}.
+ */
+ public SimpleVerifier() {
+ this(null, null, false);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass
+ * the class that is verified.
+ * @param currentSuperClass
+ * the super class of the class that is verified.
+ * @param isInterface
+ * if the class that is verified is an interface.
+ */
+ public SimpleVerifier(final Type currentClass,
+ final Type currentSuperClass, final boolean isInterface) {
+ this(currentClass, currentSuperClass, null, isInterface);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass
+ * the class that is verified.
+ * @param currentSuperClass
+ * the super class of the class that is verified.
+ * @param currentClassInterfaces
+ * the interfaces implemented by the class that is verified.
+ * @param isInterface
+ * if the class that is verified is an interface.
+ */
+ public SimpleVerifier(final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces, final boolean isInterface) {
+ this(ASM5, currentClass, currentSuperClass, currentClassInterfaces,
+ isInterface);
+ }
+
+ protected SimpleVerifier(final int api, final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces, final boolean isInterface) {
+ super(api);
+ this.currentClass = currentClass;
+ this.currentSuperClass = currentSuperClass;
+ this.currentClassInterfaces = currentClassInterfaces;
+ this.isInterface = isInterface;
+ }
+
+ /**
+ * Set the <code>ClassLoader</code> which will be used to load referenced
+ * classes. This is useful if you are verifying multiple interdependent
+ * classes.
+ *
+ * @param loader
+ * a <code>ClassLoader</code> to use
+ */
+ public void setClassLoader(final ClassLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+
+ boolean isArray = type.getSort() == Type.ARRAY;
+ if (isArray) {
+ switch (type.getElementType().getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ return new BasicValue(type);
+ }
+ }
+
+ BasicValue v = super.newValue(type);
+ if (BasicValue.REFERENCE_VALUE.equals(v)) {
+ if (isArray) {
+ v = newValue(type.getElementType());
+ String desc = v.getType().getDescriptor();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ desc = '[' + desc;
+ }
+ v = new BasicValue(Type.getType(desc));
+ } else {
+ v = new BasicValue(type);
+ }
+ }
+ return v;
+ }
+
+ @Override
+ protected boolean isArrayValue(final BasicValue value) {
+ Type t = value.getType();
+ return t != null
+ && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException {
+ Type arrayType = objectArrayValue.getType();
+ if (arrayType != null) {
+ if (arrayType.getSort() == Type.ARRAY) {
+ return newValue(Type.getType(arrayType.getDescriptor()
+ .substring(1)));
+ } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+ return objectArrayValue;
+ }
+ }
+ throw new Error("Internal error");
+ }
+
+ @Override
+ protected boolean isSubTypeOf(final BasicValue value,
+ final BasicValue expected) {
+ Type expectedType = expected.getType();
+ Type type = value.getType();
+ switch (expectedType.getSort()) {
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return type.equals(expectedType);
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if ("Lnull;".equals(type.getDescriptor())) {
+ return true;
+ } else if (type.getSort() == Type.OBJECT
+ || type.getSort() == Type.ARRAY) {
+ return isAssignableFrom(expectedType, type);
+ } else {
+ return false;
+ }
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ Type t = v.getType();
+ Type u = w.getType();
+ if (t != null
+ && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
+ if (u != null
+ && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
+ if ("Lnull;".equals(t.getDescriptor())) {
+ return w;
+ }
+ if ("Lnull;".equals(u.getDescriptor())) {
+ return v;
+ }
+ if (isAssignableFrom(t, u)) {
+ return v;
+ }
+ if (isAssignableFrom(u, t)) {
+ return w;
+ }
+ // TODO case of array classes of the same dimension
+ // TODO should we look also for a common super interface?
+ // problem: there may be several possible common super
+ // interfaces
+ do {
+ if (t == null || isInterface(t)) {
+ return BasicValue.REFERENCE_VALUE;
+ }
+ t = getSuperClass(t);
+ if (isAssignableFrom(t, u)) {
+ return newValue(t);
+ }
+ } while (true);
+ }
+ }
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+
+ protected boolean isInterface(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return isInterface;
+ }
+ return getClass(t).isInterface();
+ }
+
+ protected Type getSuperClass(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return currentSuperClass;
+ }
+ Class<?> c = getClass(t).getSuperclass();
+ return c == null ? null : Type.getType(c);
+ }
+
+ protected boolean isAssignableFrom(final Type t, final Type u) {
+ if (t.equals(u)) {
+ return true;
+ }
+ if (currentClass != null && t.equals(currentClass)) {
+ if (getSuperClass(u) == null) {
+ return false;
+ } else {
+ if (isInterface) {
+ return u.getSort() == Type.OBJECT
+ || u.getSort() == Type.ARRAY;
+ }
+ return isAssignableFrom(t, getSuperClass(u));
+ }
+ }
+ if (currentClass != null && u.equals(currentClass)) {
+ if (isAssignableFrom(t, currentSuperClass)) {
+ return true;
+ }
+ if (currentClassInterfaces != null) {
+ for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+ Type v = currentClassInterfaces.get(i);
+ if (isAssignableFrom(t, v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ Class<?> tc = getClass(t);
+ if (tc.isInterface()) {
+ tc = Object.class;
+ }
+ return tc.isAssignableFrom(getClass(u));
+ }
+
+ protected Class<?> getClass(final Type t) {
+ try {
+ if (t.getSort() == Type.ARRAY) {
+ return Class.forName(t.getDescriptor().replace('/', '.'),
+ false, loader);
+ }
+ return Class.forName(t.getClassName(), false, loader);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000..2aacb42
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,134 @@
+/***
+ * 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.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ *
+ * @author Eric Bruneton
+ */
+class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+
+ // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+ E e1, e2;
+
+ static final <T> Set<T> emptySet() {
+ return new SmallSet<T>(null, null);
+ }
+
+ SmallSet(final E e1, final E e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of inherited abstract methods
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Iterator<E> iterator() {
+ return new SmallSet<E>(e1, e2);
+ }
+
+ @Override
+ public int size() {
+ return e1 == null ? 0 : (e2 == null ? 1 : 2);
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of the Iterator interface
+ // -------------------------------------------------------------------------
+
+ public boolean hasNext() {
+ return e1 != null;
+ }
+
+ public E next() {
+ if (e1 == null) {
+ throw new NoSuchElementException();
+ }
+ E e = e1;
+ e1 = e2;
+ e2 = null;
+ return e;
+ }
+
+ public void remove() {
+ }
+
+ // -------------------------------------------------------------------------
+ // Utility methods
+ // -------------------------------------------------------------------------
+
+ Set<E> union(final SmallSet<E> s) {
+ if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+ return this; // if the two sets are equal, return this
+ }
+ if (s.e1 == null) {
+ return this; // if s is empty, return this
+ }
+ if (e1 == null) {
+ return s; // if this is empty, return s
+ }
+ if (s.e2 == null) { // s contains exactly one element
+ if (e2 == null) {
+ return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
+ } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+ return this;
+ }
+ }
+ if (e2 == null) { // this contains exactly one element
+ // if (s.e2 == null) { // cannot happen
+ // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+ // } else
+ if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+ return s;
+ }
+ }
+ // here we know that there are at least 3 distinct elements
+ HashSet<E> r = new HashSet<E>(4);
+ r.add(e1);
+ if (e2 != null) {
+ r.add(e2);
+ }
+ r.add(s.e1);
+ if (s.e2 != null) {
+ r.add(s.e2);
+ }
+ return r;
+ }
+}
[05/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?"
Posted by ka...@apache.org.
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..5770364
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1542 @@
+/***
+ * 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.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.Analyzer;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicValue;
+import org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based <i>only</i> on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.apache.tapestry5.internal.plastic.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
+ * They are not performed if any other constructor is used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+ /**
+ * The class version number.
+ */
+ public int version;
+
+ /**
+ * The access flags of the method.
+ */
+ private int access;
+
+ /**
+ * <tt>true</tt> if the visitCode method has been called.
+ */
+ private boolean startCode;
+
+ /**
+ * <tt>true</tt> if the visitMaxs method has been called.
+ */
+ private boolean endCode;
+
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean endMethod;
+
+ /**
+ * Number of visited instructions.
+ */
+ private int insnCount;
+
+ /**
+ * The already visited labels. This map associate Integer values to pseudo
+ * code offsets.
+ */
+ private final Map<Label, Integer> labels;
+
+ /**
+ * The labels used in this method. Every used label must be visited with
+ * visitLabel before the end of the method (i.e. should be in #labels).
+ */
+ private Set<Label> usedLabels;
+
+ /**
+ * Number of visited frames in expanded form.
+ */
+ private int expandedFrames;
+
+ /**
+ * Number of visited frames in compressed form.
+ */
+ private int compressedFrames;
+
+ /**
+ * Number of instructions before the last visited frame.
+ */
+ private int lastFrame = -1;
+
+ /**
+ * The exception handler ranges. Each pair of list element contains the
+ * start and end labels of an exception handler block.
+ */
+ private List<Label> handlers;
+
+ /**
+ * Code of the visit method to be used for each opcode.
+ */
+ private static final int[] TYPE;
+
+ /**
+ * The Label.status field.
+ */
+ private static Field labelStatusField;
+
+ static {
+ String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+ + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+ + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+ TYPE = new int[s.length()];
+ for (int i = 0; i < TYPE.length; ++i) {
+ TYPE[i] = s.charAt(i) - 'A' - 1;
+ }
+ }
+
+ // code to generate the above string
+ // public static void main (String[] args) {
+ // int[] TYPE = new int[] {
+ // 0, //NOP
+ // 0, //ACONST_NULL
+ // 0, //ICONST_M1
+ // 0, //ICONST_0
+ // 0, //ICONST_1
+ // 0, //ICONST_2
+ // 0, //ICONST_3
+ // 0, //ICONST_4
+ // 0, //ICONST_5
+ // 0, //LCONST_0
+ // 0, //LCONST_1
+ // 0, //FCONST_0
+ // 0, //FCONST_1
+ // 0, //FCONST_2
+ // 0, //DCONST_0
+ // 0, //DCONST_1
+ // 1, //BIPUSH
+ // 1, //SIPUSH
+ // 7, //LDC
+ // -1, //LDC_W
+ // -1, //LDC2_W
+ // 2, //ILOAD
+ // 2, //LLOAD
+ // 2, //FLOAD
+ // 2, //DLOAD
+ // 2, //ALOAD
+ // -1, //ILOAD_0
+ // -1, //ILOAD_1
+ // -1, //ILOAD_2
+ // -1, //ILOAD_3
+ // -1, //LLOAD_0
+ // -1, //LLOAD_1
+ // -1, //LLOAD_2
+ // -1, //LLOAD_3
+ // -1, //FLOAD_0
+ // -1, //FLOAD_1
+ // -1, //FLOAD_2
+ // -1, //FLOAD_3
+ // -1, //DLOAD_0
+ // -1, //DLOAD_1
+ // -1, //DLOAD_2
+ // -1, //DLOAD_3
+ // -1, //ALOAD_0
+ // -1, //ALOAD_1
+ // -1, //ALOAD_2
+ // -1, //ALOAD_3
+ // 0, //IALOAD
+ // 0, //LALOAD
+ // 0, //FALOAD
+ // 0, //DALOAD
+ // 0, //AALOAD
+ // 0, //BALOAD
+ // 0, //CALOAD
+ // 0, //SALOAD
+ // 2, //ISTORE
+ // 2, //LSTORE
+ // 2, //FSTORE
+ // 2, //DSTORE
+ // 2, //ASTORE
+ // -1, //ISTORE_0
+ // -1, //ISTORE_1
+ // -1, //ISTORE_2
+ // -1, //ISTORE_3
+ // -1, //LSTORE_0
+ // -1, //LSTORE_1
+ // -1, //LSTORE_2
+ // -1, //LSTORE_3
+ // -1, //FSTORE_0
+ // -1, //FSTORE_1
+ // -1, //FSTORE_2
+ // -1, //FSTORE_3
+ // -1, //DSTORE_0
+ // -1, //DSTORE_1
+ // -1, //DSTORE_2
+ // -1, //DSTORE_3
+ // -1, //ASTORE_0
+ // -1, //ASTORE_1
+ // -1, //ASTORE_2
+ // -1, //ASTORE_3
+ // 0, //IASTORE
+ // 0, //LASTORE
+ // 0, //FASTORE
+ // 0, //DASTORE
+ // 0, //AASTORE
+ // 0, //BASTORE
+ // 0, //CASTORE
+ // 0, //SASTORE
+ // 0, //POP
+ // 0, //POP2
+ // 0, //DUP
+ // 0, //DUP_X1
+ // 0, //DUP_X2
+ // 0, //DUP2
+ // 0, //DUP2_X1
+ // 0, //DUP2_X2
+ // 0, //SWAP
+ // 0, //IADD
+ // 0, //LADD
+ // 0, //FADD
+ // 0, //DADD
+ // 0, //ISUB
+ // 0, //LSUB
+ // 0, //FSUB
+ // 0, //DSUB
+ // 0, //IMUL
+ // 0, //LMUL
+ // 0, //FMUL
+ // 0, //DMUL
+ // 0, //IDIV
+ // 0, //LDIV
+ // 0, //FDIV
+ // 0, //DDIV
+ // 0, //IREM
+ // 0, //LREM
+ // 0, //FREM
+ // 0, //DREM
+ // 0, //INEG
+ // 0, //LNEG
+ // 0, //FNEG
+ // 0, //DNEG
+ // 0, //ISHL
+ // 0, //LSHL
+ // 0, //ISHR
+ // 0, //LSHR
+ // 0, //IUSHR
+ // 0, //LUSHR
+ // 0, //IAND
+ // 0, //LAND
+ // 0, //IOR
+ // 0, //LOR
+ // 0, //IXOR
+ // 0, //LXOR
+ // 8, //IINC
+ // 0, //I2L
+ // 0, //I2F
+ // 0, //I2D
+ // 0, //L2I
+ // 0, //L2F
+ // 0, //L2D
+ // 0, //F2I
+ // 0, //F2L
+ // 0, //F2D
+ // 0, //D2I
+ // 0, //D2L
+ // 0, //D2F
+ // 0, //I2B
+ // 0, //I2C
+ // 0, //I2S
+ // 0, //LCMP
+ // 0, //FCMPL
+ // 0, //FCMPG
+ // 0, //DCMPL
+ // 0, //DCMPG
+ // 6, //IFEQ
+ // 6, //IFNE
+ // 6, //IFLT
+ // 6, //IFGE
+ // 6, //IFGT
+ // 6, //IFLE
+ // 6, //IF_ICMPEQ
+ // 6, //IF_ICMPNE
+ // 6, //IF_ICMPLT
+ // 6, //IF_ICMPGE
+ // 6, //IF_ICMPGT
+ // 6, //IF_ICMPLE
+ // 6, //IF_ACMPEQ
+ // 6, //IF_ACMPNE
+ // 6, //GOTO
+ // 6, //JSR
+ // 2, //RET
+ // 9, //TABLESWITCH
+ // 10, //LOOKUPSWITCH
+ // 0, //IRETURN
+ // 0, //LRETURN
+ // 0, //FRETURN
+ // 0, //DRETURN
+ // 0, //ARETURN
+ // 0, //RETURN
+ // 4, //GETSTATIC
+ // 4, //PUTSTATIC
+ // 4, //GETFIELD
+ // 4, //PUTFIELD
+ // 5, //INVOKEVIRTUAL
+ // 5, //INVOKESPECIAL
+ // 5, //INVOKESTATIC
+ // 5, //INVOKEINTERFACE
+ // -1, //INVOKEDYNAMIC
+ // 3, //NEW
+ // 1, //NEWARRAY
+ // 3, //ANEWARRAY
+ // 0, //ARRAYLENGTH
+ // 0, //ATHROW
+ // 3, //CHECKCAST
+ // 3, //INSTANCEOF
+ // 0, //MONITORENTER
+ // 0, //MONITOREXIT
+ // -1, //WIDE
+ // 11, //MULTIANEWARRAY
+ // 6, //IFNULL
+ // 6, //IFNONNULL
+ // -1, //GOTO_W
+ // -1 //JSR_W
+ // };
+ // for (int i = 0; i < TYPE.length; ++i) {
+ // System.out.print((char)(TYPE[i] + 1 + 'A'));
+ // }
+ // System.out.println();
+ // }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv) {
+ this(mv, new HashMap<Label, Integer>());
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv,
+ final Map<Label, Integer> labels) {
+ this(Opcodes.ASM5, mv, labels);
+ if (getClass() != CheckMethodAdapter.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ *
+ * @param mv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ protected CheckMethodAdapter(final int api, final MethodVisitor mv,
+ final Map<Label, Integer> labels) {
+ super(api, mv);
+ this.labels = labels;
+ this.usedLabels = new HashSet<Label>();
+ this.handlers = new ArrayList<Label>();
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will perform basic data flow checks. For instance in a method whose
+ * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
+ * invalid sequence IADD L2I will be detected.
+ *
+ * @param access
+ * the method's access flags.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param cmv
+ * the method visitor to which this adapter must delegate calls.
+ * @param labels
+ * a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(final int access, final String name,
+ final String desc, final MethodVisitor cmv,
+ final Map<Label, Integer> labels) {
+ this(new MethodNode(Opcodes.ASM5, access, name, desc, null, null) {
+ @Override
+ public void visitEnd() {
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(
+ new BasicVerifier());
+ try {
+ a.analyze("dummy", this);
+ } catch (Exception e) {
+ if (e instanceof IndexOutOfBoundsException
+ && maxLocals == 0 && maxStack == 0) {
+ throw new RuntimeException(
+ "Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+ }
+ e.printStackTrace();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ CheckClassAdapter.printAnalyzerResult(this, a, pw);
+ pw.close();
+ throw new RuntimeException(e.getMessage() + ' '
+ + sw.toString());
+ }
+ accept(cmv);
+ }
+ }, labels);
+ this.access = access;
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ if (name != null) {
+ checkUnqualifiedName(version, name, "name");
+ }
+ CheckClassAdapter.checkAccess(access, Opcodes.ACC_FINAL
+ + Opcodes.ACC_MANDATED + Opcodes.ACC_SYNTHETIC);
+ super.visitParameter(name, access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkEndMethod();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.METHOD_TYPE_PARAMETER
+ && sort != TypeReference.METHOD_TYPE_PARAMETER_BOUND
+ && sort != TypeReference.METHOD_RETURN
+ && sort != TypeReference.METHOD_RECEIVER
+ && sort != TypeReference.METHOD_FORMAL_PARAMETER
+ && sort != TypeReference.THROWS) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitTypeAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkEndMethod();
+ return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitParameterAnnotation(
+ parameter, desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEndMethod();
+ if (attr == null) {
+ throw new IllegalArgumentException(
+ "Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ throw new RuntimeException("Abstract methods cannot have code");
+ }
+ startCode = true;
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (insnCount == lastFrame) {
+ throw new IllegalStateException(
+ "At most one frame can be visited at a given code location.");
+ }
+ lastFrame = insnCount;
+ int mLocal;
+ int mStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mLocal = Integer.MAX_VALUE;
+ mStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ mLocal = 0;
+ mStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ mLocal = 0;
+ mStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ mLocal = 3;
+ mStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
+ }
+
+ if (nLocal > mLocal) {
+ throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+ + " for frame type " + type);
+ }
+ if (nStack > mStack) {
+ throw new IllegalArgumentException("Invalid nStack=" + nStack
+ + " for frame type " + type);
+ }
+
+ if (type != Opcodes.F_CHOP) {
+ if (nLocal > 0 && (local == null || local.length < nLocal)) {
+ throw new IllegalArgumentException(
+ "Array local[] is shorter than nLocal");
+ }
+ for (int i = 0; i < nLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
+ }
+ if (nStack > 0 && (stack == null || stack.length < nStack)) {
+ throw new IllegalArgumentException(
+ "Array stack[] is shorter than nStack");
+ }
+ for (int i = 0; i < nStack; ++i) {
+ checkFrameValue(stack[i]);
+ }
+ if (type == Opcodes.F_NEW) {
+ ++expandedFrames;
+ } else {
+ ++compressedFrames;
+ }
+ if (expandedFrames > 0 && compressedFrames > 0) {
+ throw new RuntimeException(
+ "Expanded and compressed frames must not be mixed.");
+ }
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 0);
+ super.visitInsn(opcode);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 1);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ // case Constants.NEWARRAY:
+ default:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException(
+ "Invalid operand (must be an array type code T_...): "
+ + operand);
+ }
+ }
+ super.visitIntInsn(opcode, operand);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 2);
+ checkUnsignedShort(var, "Invalid variable index");
+ super.visitVarInsn(opcode, var);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 3);
+ checkInternalName(type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException(
+ "NEW cannot be used to create arrays: " + type);
+ }
+ super.visitTypeInsn(opcode, type);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 4);
+ checkInternalName(owner, "owner");
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Deprecated
+ @Override
+ public void visitMethodInsn(int opcode, String owner, String name,
+ 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(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ doVisitMethodInsn(opcode, owner, name, desc, itf);
+ }
+
+ private void doVisitMethodInsn(int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 5);
+ if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) {
+ checkMethodIdentifier(version, name, "name");
+ }
+ checkInternalName(owner, "owner");
+ checkMethodDesc(desc);
+ if (opcode == Opcodes.INVOKEVIRTUAL && itf) {
+ throw new IllegalArgumentException(
+ "INVOKEVIRTUAL can't be used with interfaces");
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE && !itf) {
+ throw new IllegalArgumentException(
+ "INVOKEINTERFACE can't be used with classes");
+ }
+ // Calling super.visitMethodInsn requires to call the correct version
+ // depending on this.api (otherwise infinite loops can occur). To
+ // simplify and to make it easier to automatically remove the backward
+ // compatibility code, we inline the code of the overridden method here.
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ checkStartCode();
+ checkEndCode();
+ checkMethodIdentifier(version, name, "name");
+ checkMethodDesc(desc);
+ if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+ && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) {
+ throw new IllegalArgumentException("invalid handle tag "
+ + bsm.getTag());
+ }
+ for (int i = 0; i < bsmArgs.length; i++) {
+ checkLDCConstant(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 6);
+ checkLabel(label, false, "label");
+ checkNonDebugLabel(label);
+ super.visitJumpInsn(opcode, label);
+ usedLabels.add(label);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(label, false, "label");
+ if (labels.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labels.put(label, new Integer(insnCount));
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ checkStartCode();
+ checkEndCode();
+ checkLDCConstant(cst);
+ super.visitLdcInsn(cst);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(var, "Invalid variable index");
+ checkSignedShort(increment, "Invalid increment");
+ super.visitIincInsn(var, increment);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ checkStartCode();
+ checkEndCode();
+ if (max < min) {
+ throw new IllegalArgumentException("Max = " + max
+ + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException(
+ "There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ checkEndCode();
+ checkStartCode();
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException(
+ "There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ usedLabels.add(dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ checkStartCode();
+ checkEndCode();
+ checkDesc(desc, false);
+ if (desc.charAt(0) != '[') {
+ throw new IllegalArgumentException(
+ "Invalid descriptor (must be an array type descriptor): "
+ + desc);
+ }
+ if (dims < 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must be greater than 0): " + dims);
+ }
+ if (dims > desc.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException(
+ "Invalid dimensions (must not be greater than dims(desc)): "
+ + dims);
+ }
+ super.visitMultiANewArrayInsn(desc, dims);
+ ++insnCount;
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE
+ && sort != TypeReference.METHOD_REFERENCE
+ && sort != TypeReference.CAST
+ && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT
+ && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef,
+ typePath, desc, visible));
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(start, false, "start label");
+ checkLabel(end, false, "end label");
+ checkLabel(handler, false, "handler label");
+ checkNonDebugLabel(start);
+ checkNonDebugLabel(end);
+ checkNonDebugLabel(handler);
+ if (labels.get(start) != null || labels.get(end) != null
+ || labels.get(handler) != null) {
+ throw new IllegalStateException(
+ "Try catch blocks must be visited before their labels");
+ }
+ if (type != null) {
+ checkInternalName(type, "type");
+ }
+ super.visitTryCatchBlock(start, end, handler, type);
+ handlers.add(start);
+ handlers.add(end);
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.EXCEPTION_PARAMETER) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.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) {
+ checkStartCode();
+ checkEndCode();
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ checkLabel(start, true, "start label");
+ checkLabel(end, true, "end label");
+ checkUnsignedShort(index, "Invalid variable index");
+ int s = labels.get(start).intValue();
+ int e = labels.get(end).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ checkStartCode();
+ checkEndCode();
+ int sort = typeRef >>> 24;
+ if (sort != TypeReference.LOCAL_VARIABLE
+ && sort != TypeReference.RESOURCE_VARIABLE) {
+ throw new IllegalArgumentException("Invalid type reference sort 0x"
+ + Integer.toHexString(sort));
+ }
+ CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath);
+ checkDesc(desc, false);
+ if (start == null || end == null || index == null
+ || end.length != start.length || index.length != start.length) {
+ throw new IllegalArgumentException(
+ "Invalid start, end and index arrays (must be non null and of identical length");
+ }
+ for (int i = 0; i < start.length; ++i) {
+ checkLabel(start[i], true, "start label");
+ checkLabel(end[i], true, "end label");
+ checkUnsignedShort(index[i], "Invalid variable index");
+ int s = labels.get(start[i]).intValue();
+ int e = labels.get(end[i]).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException(
+ "Invalid start and end labels (end must be greater than start)");
+ }
+ }
+ return super.visitLocalVariableAnnotation(typeRef, typePath, start,
+ end, index, desc, visible);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(line, "Invalid line number");
+ checkLabel(start, true, "start label");
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ checkStartCode();
+ checkEndCode();
+ endCode = true;
+ for (Label l : usedLabels) {
+ if (labels.get(l) == null) {
+ throw new IllegalStateException("Undefined label used");
+ }
+ }
+ for (int i = 0; i < handlers.size();) {
+ Integer start = labels.get(handlers.get(i++));
+ Integer end = labels.get(handlers.get(i++));
+ if (start == null || end == null) {
+ throw new IllegalStateException(
+ "Undefined try catch block labels");
+ }
+ if (end.intValue() <= start.intValue()) {
+ throw new IllegalStateException(
+ "Emty try catch block handler range");
+ }
+ }
+ checkUnsignedShort(maxStack, "Invalid max stack");
+ checkUnsignedShort(maxLocals, "Invalid max locals");
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEndMethod();
+ endMethod = true;
+ super.visitEnd();
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks that the visitCode method has been called.
+ */
+ void checkStartCode() {
+ if (!startCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions before visitCode has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitMaxs method has not been called.
+ */
+ void checkEndCode() {
+ if (endCode) {
+ throw new IllegalStateException(
+ "Cannot visit instructions after visitMaxs has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitEnd method has not been called.
+ */
+ void checkEndMethod() {
+ if (endMethod) {
+ throw new IllegalStateException(
+ "Cannot visit elements after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks a stack frame value.
+ *
+ * @param value
+ * the value to be checked.
+ */
+ void checkFrameValue(final Object value) {
+ if (value == Opcodes.TOP || value == Opcodes.INTEGER
+ || value == Opcodes.FLOAT || value == Opcodes.LONG
+ || value == Opcodes.DOUBLE || value == Opcodes.NULL
+ || value == Opcodes.UNINITIALIZED_THIS) {
+ return;
+ }
+ if (value instanceof String) {
+ checkInternalName((String) value, "Invalid stack frame value");
+ return;
+ }
+ if (!(value instanceof Label)) {
+ throw new IllegalArgumentException("Invalid stack frame value: "
+ + value);
+ } else {
+ usedLabels.add((Label) value);
+ }
+ }
+
+ /**
+ * Checks that the type of the given opcode is equal to the given type.
+ *
+ * @param opcode
+ * the opcode to be checked.
+ * @param type
+ * the expected opcode type.
+ */
+ static void checkOpcode(final int opcode, final int type) {
+ if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+ throw new IllegalArgumentException("Invalid opcode: " + opcode);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed byte.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedByte(final int value, final String msg) {
+ if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed byte): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkSignedShort(final int value, final String msg) {
+ if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an unsigned short.
+ *
+ * @param value
+ * the value to be checked.
+ * @param msg
+ * an message to be used in case of error.
+ */
+ static void checkUnsignedShort(final int value, final String msg) {
+ if (value < 0 || value > 65535) {
+ throw new IllegalArgumentException(msg
+ + " (must be an unsigned short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an {@link Integer}, a{@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst
+ * the value to be checked.
+ */
+ static void checkConstant(final Object cst) {
+ if (!(cst instanceof Integer) && !(cst instanceof Float)
+ && !(cst instanceof Long) && !(cst instanceof Double)
+ && !(cst instanceof String)) {
+ throw new IllegalArgumentException("Invalid constant: " + cst);
+ }
+ }
+
+ void checkLDCConstant(final Object cst) {
+ if (cst instanceof Type) {
+ int s = ((Type) cst).getSort();
+ if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+ throw new IllegalArgumentException("Illegal LDC constant value");
+ }
+ if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+ throw new IllegalArgumentException(
+ "ldc of a constant class requires at least version 1.5");
+ }
+ if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a method type requires at least version 1.7");
+ }
+ } else if (cst instanceof Handle) {
+ if ((version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException(
+ "ldc of a handle requires at least version 1.7");
+ }
+ int tag = ((Handle) cst).getTag();
+ if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+ throw new IllegalArgumentException("invalid handle tag " + tag);
+ }
+ } else {
+ checkConstant(cst);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid unqualified name.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkUnqualifiedName(int version, final String name,
+ final String msg) {
+ if ((version & 0xFFFF) < Opcodes.V1_5) {
+ checkIdentifier(name, msg);
+ } else {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final String msg) {
+ checkIdentifier(name, 0, -1, msg);
+ }
+
+ /**
+ * Checks that the given substring is a valid Java identifier.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final int start,
+ final int end, final String msg) {
+ if (name == null || (end == -1 ? name.length() <= start : end <= start)) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ int max = end == -1 ? name.length() : end;
+ for (int i = start + 1; i < max; ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param version
+ * the class version.
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkMethodIdentifier(int version, final String name,
+ final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if ((version & 0xFFFF) >= Opcodes.V1_5) {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ return;
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (name.charAt(0) == '[') {
+ checkDesc(name, false);
+ } else {
+ checkInternalName(name, 0, -1, msg);
+ }
+ }
+
+ /**
+ * Checks that the given substring is a valid internal class name.
+ *
+ * @param name
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param end
+ * index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final int start,
+ final int end, final String msg) {
+ int max = end == -1 ? name.length() : end;
+ try {
+ int begin = start;
+ int slash;
+ do {
+ slash = name.indexOf('/', begin + 1);
+ if (slash == -1 || slash > max) {
+ slash = max;
+ }
+ checkIdentifier(name, begin, slash, null);
+ begin = slash + 1;
+ } while (slash != max);
+ } catch (IllegalArgumentException unused) {
+ throw new IllegalArgumentException(
+ "Invalid "
+ + msg
+ + " (must be a fully qualified class name in internal form): "
+ + name);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param canBeVoid
+ * <tt>true</tt> if <tt>V</tt> can be considered valid.
+ */
+ static void checkDesc(final String desc, final boolean canBeVoid) {
+ int end = checkDesc(desc, 0, canBeVoid);
+ if (end != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that a the given substring is a valid type descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ * @param start
+ * index of the first character of the identifier (inclusive).
+ * @param canBeVoid
+ * <tt>true</tt> if <tt>V</tt> can be considered valid.
+ * @return the index of the last character of the type decriptor, plus one.
+ */
+ static int checkDesc(final String desc, final int start,
+ final boolean canBeVoid) {
+ if (desc == null || start >= desc.length()) {
+ throw new IllegalArgumentException(
+ "Invalid type descriptor (must not be null or empty)");
+ }
+ int index;
+ switch (desc.charAt(start)) {
+ case 'V':
+ if (canBeVoid) {
+ return start + 1;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return start + 1;
+ case '[':
+ index = start + 1;
+ while (index < desc.length() && desc.charAt(index) == '[') {
+ ++index;
+ }
+ if (index < desc.length()) {
+ return checkDesc(desc, index, false);
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'L':
+ index = desc.indexOf(';', start);
+ if (index == -1 || index - start < 2) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ try {
+ checkInternalName(desc, start + 1, index, null);
+ } catch (IllegalArgumentException unused) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ return index + 1;
+ default:
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid method descriptor.
+ *
+ * @param desc
+ * the string to be checked.
+ */
+ static void checkMethodDesc(final String desc) {
+ if (desc == null || desc.length() == 0) {
+ throw new IllegalArgumentException(
+ "Invalid method descriptor (must not be null or empty)");
+ }
+ if (desc.charAt(0) != '(' || desc.length() < 3) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ int start = 1;
+ if (desc.charAt(start) != ')') {
+ do {
+ if (desc.charAt(start) == 'V') {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ start = checkDesc(desc, start, false);
+ } while (start < desc.length() && desc.charAt(start) != ')');
+ }
+ start = checkDesc(desc, start + 1, true);
+ if (start != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that the given label is not null. This method can also check that
+ * the label has been visited.
+ *
+ * @param label
+ * the label to be checked.
+ * @param checkVisited
+ * <tt>true</tt> to check that the label has been visited.
+ * @param msg
+ * a message to be used in case of error.
+ */
+ void checkLabel(final Label label, final boolean checkVisited,
+ final String msg) {
+ if (label == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null)");
+ }
+ if (checkVisited && labels.get(label) == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be visited first)");
+ }
+ }
+
+ /**
+ * Checks that the given label is not a label used only for debug purposes.
+ *
+ * @param label
+ * the label to be checked.
+ */
+ private static void checkNonDebugLabel(final Label label) {
+ Field f = getLabelStatusField();
+ int status = 0;
+ try {
+ status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+ } catch (IllegalAccessException e) {
+ throw new Error("Internal error");
+ }
+ if ((status & 0x01) != 0) {
+ throw new IllegalArgumentException(
+ "Labels used for debug info cannot be reused for control flow");
+ }
+ }
+
+ /**
+ * Returns the Field object corresponding to the Label.status field.
+ *
+ * @return the Field object corresponding to the Label.status field.
+ */
+ private static Field getLabelStatusField() {
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("a");
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("status");
+ }
+ }
+ return labelStatusField;
+ }
+
+ /**
+ * Returns the field of the Label class whose name is given.
+ *
+ * @param name
+ * a field name.
+ * @return the field of the Label class whose name is given, or null.
+ */
+ private static Field getLabelField(final String name) {
+ try {
+ Field f = Label.class.getDeclaredField(name);
+ f.setAccessible(true);
+ return f;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..cf1f98b
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,330 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.apache.tapestry5.internal.plastic.asm.util;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+ /**
+ * Type to be used to check class signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor)
+ * CheckSignatureAdapter}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ private static final int EMPTY = 1;
+
+ private static final int FORMAL = 2;
+
+ private static final int BOUND = 4;
+
+ private static final int SUPER = 8;
+
+ private static final int PARAM = 16;
+
+ private static final int RETURN = 32;
+
+ private static final int SIMPLE_TYPE = 64;
+
+ private static final int CLASS_TYPE = 128;
+
+ private static final int END = 256;
+
+ /**
+ * Type of the signature to be checked.
+ */
+ private final int type;
+
+ /**
+ * State of the automaton used to check the order of method calls.
+ */
+ private int state;
+
+ /**
+ * <tt>true</tt> if the checked type signature can be 'V'.
+ */
+ private boolean canBeVoid;
+
+ /**
+ * The visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ private final SignatureVisitor sv;
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the
+ * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
+ *
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+ this(Opcodes.ASM5, type, sv);
+ }
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param type
+ * the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv
+ * the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ protected CheckSignatureAdapter(final int api, final int type,
+ final SignatureVisitor sv) {
+ super(api);
+ this.type = type;
+ this.state = EMPTY;
+ this.sv = sv;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE
+ || (state != EMPTY && state != FORMAL && state != BOUND)) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+ state = FORMAL;
+ if (sv != null) {
+ sv.visitFormalTypeParameter(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (state != FORMAL) {
+ throw new IllegalStateException();
+ }
+ state = BOUND;
+ SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (state != FORMAL && state != BOUND) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = SUPER;
+ SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (state != SUPER) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterface();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // method signatures
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = PARAM;
+ SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) {
+ throw new IllegalArgumentException();
+ }
+ state = RETURN;
+ SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+ CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ cv.canBeVoid = true;
+ return cv;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (state != RETURN) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // type signatures
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitBaseType(descriptor);
+ }
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "type variable");
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitTypeVariable(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = SIMPLE_TYPE;
+ SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ state = CLASS_TYPE;
+ if (sv != null) {
+ sv.visitClassType(name);
+ }
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "inner class name");
+ if (sv != null) {
+ sv.visitInnerClassType(name);
+ }
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (sv != null) {
+ sv.visitTypeArgument();
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = END;
+ if (sv != null) {
+ sv.visitEnd();
+ }
+ }
+}