TAP5-2588: upgrading from ASM 6 to 7 for Java 9+ support
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/1c71aec7 Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/1c71aec7 Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/1c71aec7 Branch: refs/heads/master Commit: 1c71aec760797c7dc595351639767ae4974b1b82 Parents: cb3b34d Author: Thiago H. de Paula Figueiredo <[email protected]> Authored: Wed Nov 28 22:33:25 2018 -0200 Committer: Thiago H. de Paula Figueiredo <[email protected]> Committed: Wed Nov 28 22:33:25 2018 -0200 ---------------------------------------------------------------------- gradle/wrapper/gradle-wrapper.properties | 2 +- plastic/LICENSE-ASM-5_0.txt | 29 - plastic/LICENSE-ASM-7_0.txt | 28 + plastic/build.gradle | 2 +- .../internal/plastic/asm/AnnotationVisitor.java | 268 +- .../internal/plastic/asm/AnnotationWriter.java | 713 +- .../internal/plastic/asm/Attribute.java | 530 +- .../internal/plastic/asm/ByteVector.java | 636 +- .../internal/plastic/asm/ClassReader.java | 6213 ++++++++++-------- .../plastic/asm/ClassTooLargeException.java | 71 + .../internal/plastic/asm/ClassVisitor.java | 603 +- .../internal/plastic/asm/ClassWriter.java | 2820 +++----- .../internal/plastic/asm/ConstantDynamic.java | 178 + .../internal/plastic/asm/Constants.java | 177 + .../tapestry5/internal/plastic/asm/Context.java | 282 +- .../internal/plastic/asm/CurrentFrame.java | 112 +- .../tapestry5/internal/plastic/asm/Edge.java | 144 +- .../internal/plastic/asm/FieldVisitor.java | 243 +- .../internal/plastic/asm/FieldWriter.java | 603 +- .../tapestry5/internal/plastic/asm/Frame.java | 2812 ++++---- .../tapestry5/internal/plastic/asm/Handle.java | 373 +- .../tapestry5/internal/plastic/asm/Handler.java | 291 +- .../tapestry5/internal/plastic/asm/Item.java | 318 - .../tapestry5/internal/plastic/asm/Label.java | 1141 ++-- .../plastic/asm/MethodTooLargeException.java | 99 + .../internal/plastic/asm/MethodVisitor.java | 1646 +++-- .../internal/plastic/asm/MethodWriter.java | 4710 ++++++------- .../internal/plastic/asm/ModuleVisitor.java | 330 +- .../internal/plastic/asm/ModuleWriter.java | 518 +- .../tapestry5/internal/plastic/asm/Opcodes.java | 652 +- .../tapestry5/internal/plastic/asm/Symbol.java | 243 + .../internal/plastic/asm/SymbolTable.java | 1318 ++++ .../tapestry5/internal/plastic/asm/Type.java | 1734 +++-- .../internal/plastic/asm/TypePath.java | 397 +- .../internal/plastic/asm/TypeReference.java | 888 ++- .../plastic/asm/commons/AdviceAdapter.java | 1217 ++-- .../plastic/asm/commons/AnalyzerAdapter.java | 1770 +++-- .../plastic/asm/commons/AnnotationRemapper.java | 142 +- .../plastic/asm/commons/ClassRemapper.java | 354 +- .../plastic/asm/commons/CodeSizeEvaluator.java | 443 +- .../plastic/asm/commons/FieldRemapper.java | 124 +- .../plastic/asm/commons/GeneratorAdapter.java | 2868 ++++---- .../plastic/asm/commons/InstructionAdapter.java | 2471 +++---- .../plastic/asm/commons/JSRInlinerAdapter.java | 1173 ++-- .../asm/commons/LocalVariablesSorter.java | 650 +- .../internal/plastic/asm/commons/Method.java | 470 +- .../plastic/asm/commons/MethodRemapper.java | 432 +- .../asm/commons/ModuleHashesAttribute.java | 223 +- .../plastic/asm/commons/ModuleRemapper.java | 194 +- .../asm/commons/ModuleResolutionAttribute.java | 191 +- .../asm/commons/ModuleTargetAttribute.java | 140 +- .../internal/plastic/asm/commons/Remapper.java | 516 +- .../asm/commons/RemappingAnnotationAdapter.java | 124 +- .../asm/commons/RemappingClassAdapter.java | 270 +- .../asm/commons/RemappingFieldAdapter.java | 105 +- .../asm/commons/RemappingMethodAdapter.java | 415 +- .../asm/commons/RemappingSignatureAdapter.java | 284 +- .../asm/commons/SerialVersionUIDAdder.java | 934 ++- .../plastic/asm/commons/SignatureRemapper.java | 309 +- .../plastic/asm/commons/SimpleRemapper.java | 131 +- .../plastic/asm/commons/StaticInitMerger.java | 175 +- .../asm/commons/TableSwitchGenerator.java | 80 +- .../asm/commons/TryCatchBlockSorter.java | 171 +- .../internal/plastic/asm/commons/package.html | 0 .../tapestry5/internal/plastic/asm/package.html | 19 +- .../plastic/asm/signature/SignatureReader.java | 438 +- .../plastic/asm/signature/SignatureVisitor.java | 415 +- .../plastic/asm/signature/SignatureWriter.java | 447 +- .../internal/plastic/asm/signature/package.html | 0 .../plastic/asm/tree/AbstractInsnNode.java | 553 +- .../plastic/asm/tree/AnnotationNode.java | 463 +- .../internal/plastic/asm/tree/ClassNode.java | 813 ++- .../plastic/asm/tree/FieldInsnNode.java | 170 +- .../internal/plastic/asm/tree/FieldNode.java | 481 +- .../internal/plastic/asm/tree/FrameNode.java | 340 +- .../internal/plastic/asm/tree/IincInsnNode.java | 123 +- .../plastic/asm/tree/InnerClassNode.java | 154 +- .../internal/plastic/asm/tree/InsnList.java | 1168 ++-- .../internal/plastic/asm/tree/InsnNode.java | 131 +- .../internal/plastic/asm/tree/IntInsnNode.java | 133 +- .../plastic/asm/tree/InvokeDynamicInsnNode.java | 154 +- .../internal/plastic/asm/tree/JumpInsnNode.java | 152 +- .../internal/plastic/asm/tree/LabelNode.java | 125 +- .../internal/plastic/asm/tree/LdcInsnNode.java | 121 +- .../plastic/asm/tree/LineNumberNode.java | 126 +- .../asm/tree/LocalVariableAnnotationNode.java | 297 +- .../plastic/asm/tree/LocalVariableNode.java | 168 +- .../plastic/asm/tree/LookupSwitchInsnNode.java | 167 +- .../plastic/asm/tree/MethodInsnNode.java | 229 +- .../internal/plastic/asm/tree/MethodNode.java | 1579 +++-- .../plastic/asm/tree/ModuleExportNode.java | 133 +- .../internal/plastic/asm/tree/ModuleNode.java | 420 +- .../plastic/asm/tree/ModuleOpenNode.java | 135 +- .../plastic/asm/tree/ModuleProvideNode.java | 112 +- .../plastic/asm/tree/ModuleRequireNode.java | 134 +- .../asm/tree/MultiANewArrayInsnNode.java | 124 +- .../plastic/asm/tree/ParameterNode.java | 120 +- .../plastic/asm/tree/TableSwitchInsnNode.java | 163 +- .../plastic/asm/tree/TryCatchBlockNode.java | 235 +- .../plastic/asm/tree/TypeAnnotationNode.java | 185 +- .../internal/plastic/asm/tree/TypeInsnNode.java | 146 +- .../tree/UnsupportedClassVersionException.java | 14 + .../internal/plastic/asm/tree/Util.java | 157 + .../internal/plastic/asm/tree/VarInsnNode.java | 146 +- .../plastic/asm/tree/analysis/Analyzer.java | 1047 +-- .../asm/tree/analysis/AnalyzerException.java | 123 +- .../asm/tree/analysis/BasicInterpreter.java | 650 +- .../plastic/asm/tree/analysis/BasicValue.java | 216 +- .../asm/tree/analysis/BasicVerifier.java | 795 +-- .../plastic/asm/tree/analysis/Frame.java | 1333 ++-- .../plastic/asm/tree/analysis/Interpreter.java | 470 +- .../asm/tree/analysis/SimpleVerifier.java | 600 +- .../plastic/asm/tree/analysis/SmallSet.java | 266 +- .../asm/tree/analysis/SourceInterpreter.java | 345 +- .../plastic/asm/tree/analysis/SourceValue.java | 178 +- .../plastic/asm/tree/analysis/Subroutine.java | 157 +- .../plastic/asm/tree/analysis/Value.java | 73 +- .../plastic/asm/tree/analysis/package.html | 30 +- .../internal/plastic/asm/tree/package.html | 71 +- .../internal/plastic/asm/util/ASMifiable.java | 70 +- .../internal/plastic/asm/util/ASMifier.java | 2952 +++++---- .../asm/util/CheckAnnotationAdapter.java | 217 +- .../plastic/asm/util/CheckClassAdapter.java | 1967 +++--- .../plastic/asm/util/CheckFieldAdapter.java | 186 +- .../plastic/asm/util/CheckMethodAdapter.java | 2870 ++++---- .../plastic/asm/util/CheckModuleAdapter.java | 323 +- .../plastic/asm/util/CheckSignatureAdapter.java | 627 +- .../internal/plastic/asm/util/Printer.java | 2457 ++++--- .../internal/plastic/asm/util/Textifiable.java | 67 +- .../internal/plastic/asm/util/Textifier.java | 3143 ++++----- .../asm/util/TraceAnnotationVisitor.java | 146 +- .../plastic/asm/util/TraceClassVisitor.java | 402 +- .../plastic/asm/util/TraceFieldVisitor.java | 140 +- .../plastic/asm/util/TraceMethodVisitor.java | 582 +- .../plastic/asm/util/TraceModuleVisitor.java | 184 +- .../plastic/asm/util/TraceSignatureVisitor.java | 610 +- .../internal/plastic/asm/util/package.html | 4 +- .../plastic/asm/xml/ASMContentHandler.java | 1569 ----- .../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 | 381 -- .../plastic/asm/xml/SAXCodeAdapter.java | 415 -- .../plastic/asm/xml/SAXFieldAdapter.java | 71 - .../plastic/asm/xml/SAXModuleAdapter.java | 137 - .../internal/plastic/asm/xml/asm-xml.dtd | 363 - .../internal/plastic/asm/xml/package.html | 96 - .../plastic/InstructionBuilderImpl.java | 84 +- .../internal/plastic/PlasticClassImpl.java | 174 +- .../internal/plastic/PlasticClassPool.java | 2 +- .../org/apache/tapestry5/ioc/internal/Main.java | 38 + .../src/test/resources/hibernate.cfg.xml | 42 + 152 files changed, 42157 insertions(+), 44581 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/gradle/wrapper/gradle-wrapper.properties ---------------------------------------------------------------------- diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0e680f3..fb7ef98 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/LICENSE-ASM-5_0.txt ---------------------------------------------------------------------- diff --git a/plastic/LICENSE-ASM-5_0.txt b/plastic/LICENSE-ASM-5_0.txt deleted file mode 100644 index c5aba7b..0000000 --- a/plastic/LICENSE-ASM-5_0.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/1c71aec7/plastic/LICENSE-ASM-7_0.txt ---------------------------------------------------------------------- diff --git a/plastic/LICENSE-ASM-7_0.txt b/plastic/LICENSE-ASM-7_0.txt new file mode 100755 index 0000000..4d19185 --- /dev/null +++ b/plastic/LICENSE-ASM-7_0.txt @@ -0,0 +1,28 @@ + + 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. http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/build.gradle ---------------------------------------------------------------------- diff --git a/plastic/build.gradle b/plastic/build.gradle index 25a53f9..d292efa 100644 --- a/plastic/build.gradle +++ b/plastic/build.gradle @@ -9,7 +9,7 @@ test { useJUnit() } -// Add the source directory for the imported/repackaged ASM 3.3.1 code +// Add the source directory for the imported/repackaged ASM 7.0.1 code sourceSets.main.java.srcDir "src/external/java" http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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 old mode 100644 new mode 100755 index a3df31b..a0c6726 --- 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 @@ -1,169 +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. - */ +// 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; /** - * 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>. - * + * A visitor to visit a Java annotation. The methods of this class must be called in the following + * order: ( {@code visit} | {@code visitEnum} | {@code visitAnnotation} | {@code visitArray} )* + * {@code visitEnd}. + * * @author Eric Bruneton * @author Eugene Kuleshov */ public abstract class AnnotationVisitor { - /** - * The ASM API version implemented by this visitor. The value of this field - * must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. - */ - protected final int api; + /** + * The ASM API version implemented by this visitor. The value of this field must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + */ + protected final int api; - /** - * The annotation visitor to which this visitor must delegate method calls. - * May be null. - */ - protected AnnotationVisitor av; + /** The annotation visitor to which this visitor must delegate method calls. May be null. */ + protected AnnotationVisitor av; - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. - */ - public AnnotationVisitor(final int api) { - this(api, null); - } + /** + * Constructs a new {@link AnnotationVisitor}. + * + * @param api the ASM API version implemented by this visitor. Must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + */ + public AnnotationVisitor(final int api) { + this(api, null); + } - /** - * Constructs a new {@link AnnotationVisitor}. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. - * @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 || api > Opcodes.ASM6) { - throw new IllegalArgumentException(); - } - this.api = api; - this.av = av; + /** + * Constructs a new {@link AnnotationVisitor}. + * + * @param api the ASM API version implemented by this visitor. Must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param annotationVisitor the annotation visitor to which this visitor must delegate method + * calls. May be null. + */ + public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) { + if (api != Opcodes.ASM6 && api != Opcodes.ASM5 && api != Opcodes.ASM4 && api != Opcodes.ASM7) { + throw new IllegalArgumentException(); } + this.api = api; + this.av = annotationVisitor; + } - /** - * 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} of 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) { - av.visit(name, value); - } + /** + * 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} of {@link Type#OBJECT} or {@link Type#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} and visiting each array element in turn, + * but is more convenient). + */ + public void visit(final String name, final Object value) { + if (av != null) { + av.visit(name, value); } + } - /** - * 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. - */ - public void visitEnum(String name, String desc, String value) { - if (av != null) { - av.visitEnum(name, desc, value); - } + /** + * Visits an enumeration value of the annotation. + * + * @param name the value name. + * @param descriptor the class descriptor of the enumeration class. + * @param value the actual enumeration value. + */ + public void visitEnum(final String name, final String descriptor, final String value) { + if (av != null) { + av.visitEnum(name, descriptor, value); } + } - /** - * Visits a nested annotation value of the annotation. - * - * @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 - * visitor</i>. - */ - public AnnotationVisitor visitAnnotation(String name, String desc) { - if (av != null) { - return av.visitAnnotation(name, desc); - } - return null; + /** + * Visits a nested annotation value of the annotation. + * + * @param name the value name. + * @param descriptor the class descriptor of the nested annotation class. + * @return a visitor to visit the actual nested annotation value, or {@literal null} 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(final String name, final String descriptor) { + if (av != null) { + return av.visitAnnotation(name, descriptor); } + return null; + } - /** - * Visits an array value of the annotation. Note that arrays of primitive - * 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. - * @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 - * visitor are ignored. <i>All the array values must be visited - * before calling other methods on this annotation visitor</i>. - */ - public AnnotationVisitor visitArray(String name) { - if (av != null) { - return av.visitArray(name); - } - return null; + /** + * Visits an array value of the annotation. Note that arrays of primitive 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. + * @return a visitor to visit the actual array value elements, or {@literal null} 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>. + */ + public AnnotationVisitor visitArray(final String name) { + if (av != null) { + return av.visitArray(name); } + return null; + } - /** - * Visits the end of the annotation. - */ - public void visitEnd() { - if (av != null) { - av.visitEnd(); - } + /** Visits the end of the annotation. */ + public void visitEnd() { + if (av != null) { + av.visitEnd(); } + } } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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 old mode 100644 new mode 100755 index d0d2d4a..c55f36a --- 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 @@ -1,371 +1,418 @@ -/*** - * 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. - */ +// 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; /** - * An {@link AnnotationVisitor} that generates annotations in bytecode form. - * + * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation' + * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter + * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations + * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such + * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes. + * + * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS + * 4.7.16</a> + * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS + * 4.7.20</a> * @author Eric Bruneton * @author Eugene Kuleshov */ final class AnnotationWriter extends AnnotationVisitor { - /** - * The class writer to which this annotation must be added. - */ - private final ClassWriter cw; - - /** - * The number of values in this annotation. - */ - private int size; + /** Where the constants used in this AnnotationWriter must be stored. */ + private final SymbolTable symbolTable; - /** - * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation - * writers used for annotation default and annotation arrays use unnamed - * values. - */ - private final boolean named; + /** + * Whether values are named or not. AnnotationWriter instances used for annotation default and + * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each + * value, instead of an element_name_index followed by an element_value). + */ + private final boolean useNamedValues; - /** - * The annotation values in bytecode form. This byte vector only contains - * the values themselves, i.e. the number of values must be stored as a - * unsigned short just before these bytes. - */ - private final ByteVector bv; + /** + * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values + * visited so far. All the fields of these structures, except the last one - the + * element_value_pairs array, must be set before this ByteVector is passed to the constructor + * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link + * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit() + * methods. + * + * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a + * single element_value by definition), this ByteVector is initially empty when passed to the + * constructor, and {@link #numElementValuePairsOffset} is set to -1. + */ + private final ByteVector annotation; - /** - * The byte vector to be used to store the number of values of this - * annotation. See {@link #bv}. - */ - private final ByteVector parent; + /** + * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for + * the case of AnnotationDefault attributes). + */ + private final int numElementValuePairsOffset; - /** - * Where the number of values of this annotation must be stored in - * {@link #parent}. - */ - private final int offset; + /** The number of element value pairs visited so far. */ + private int numElementValuePairs; - /** - * Next annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter next; + /** + * The previous AnnotationWriter. This field is used to store the list of annotations of a + * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations + * (annotation values of annotation type), or for AnnotationDefault attributes. + */ + private final AnnotationWriter previousAnnotation; - /** - * Previous annotation writer. This field is used to store annotation lists. - */ - AnnotationWriter prev; + /** + * The next AnnotationWriter. This field is used to store the list of annotations of a + * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations + * (annotation values of annotation type), or for AnnotationDefault attributes. + */ + private AnnotationWriter nextAnnotation; - // ------------------------------------------------------------------------ - // Constructor - // ------------------------------------------------------------------------ + // ----------------------------------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------------------------------- - /** - * 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. - */ - AnnotationWriter(final ClassWriter cw, final boolean named, - final ByteVector bv, final ByteVector parent, final int offset) { - super(Opcodes.ASM6); - this.cw = cw; - this.named = named; - this.bv = bv; - this.parent = parent; - this.offset = offset; + /** + * Constructs a new {@link AnnotationWriter}. + * + * @param symbolTable where the constants used in this AnnotationWriter must be stored. + * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays + * use unnamed values. + * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to + * the visited content must be stored. This ByteVector must already contain all the fields of + * the structure except the last one (the element_value_pairs array). + * @param previousAnnotation the previously visited annotation of the + * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in + * other cases (e.g. nested or array annotations). + */ + AnnotationWriter( + final SymbolTable symbolTable, + final boolean useNamedValues, + final ByteVector annotation, + final AnnotationWriter previousAnnotation) { + super(Opcodes.ASM7); + this.symbolTable = symbolTable; + this.useNamedValues = useNamedValues; + this.annotation = annotation; + // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'. + this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2; + this.previousAnnotation = previousAnnotation; + if (previousAnnotation != null) { + previousAnnotation.nextAnnotation = this; } + } - // ------------------------------------------------------------------------ - // Implementation of the AnnotationVisitor abstract class - // ------------------------------------------------------------------------ + /** + * Constructs a new {@link AnnotationWriter} using named values. + * + * @param symbolTable where the constants used in this AnnotationWriter must be stored. + * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to + * the visited content must be stored. This ByteVector must already contain all the fields of + * the structure except the last one (the element_value_pairs array). + * @param previousAnnotation the previously visited annotation of the + * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in + * other cases (e.g. nested or array annotations). + */ + AnnotationWriter( + final SymbolTable symbolTable, + final ByteVector annotation, + final AnnotationWriter previousAnnotation) { + this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation); + } - @Override - public void visit(final String name, final Object value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - if (value instanceof String) { - bv.put12('s', cw.newUTF8((String) value)); - } else if (value instanceof Byte) { - bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); - } else if (value instanceof Boolean) { - int v = ((Boolean) value).booleanValue() ? 1 : 0; - bv.put12('Z', cw.newInteger(v).index); - } else if (value instanceof Character) { - bv.put12('C', cw.newInteger(((Character) value).charValue()).index); - } else if (value instanceof Short) { - bv.put12('S', cw.newInteger(((Short) value).shortValue()).index); - } else if (value instanceof Type) { - bv.put12('c', cw.newUTF8(((Type) value).getDescriptor())); - } else if (value instanceof byte[]) { - byte[] v = (byte[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('B', cw.newInteger(v[i]).index); - } - } else if (value instanceof boolean[]) { - boolean[] v = (boolean[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index); - } - } else if (value instanceof short[]) { - short[] v = (short[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('S', cw.newInteger(v[i]).index); - } - } else if (value instanceof char[]) { - char[] v = (char[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('C', cw.newInteger(v[i]).index); - } - } else if (value instanceof int[]) { - int[] v = (int[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('I', cw.newInteger(v[i]).index); - } - } else if (value instanceof long[]) { - long[] v = (long[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('J', cw.newLong(v[i]).index); - } - } else if (value instanceof float[]) { - float[] v = (float[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('F', cw.newFloat(v[i]).index); - } - } else if (value instanceof double[]) { - double[] v = (double[]) value; - bv.put12('[', v.length); - for (int i = 0; i < v.length; i++) { - bv.put12('D', cw.newDouble(v[i]).index); - } - } else { - Item i = cw.newConstItem(value); - bv.put12(".s.IFJDCS".charAt(i.type), i.index); - } + // ----------------------------------------------------------------------------------------------- + // Implementation of the AnnotationVisitor abstract class + // ----------------------------------------------------------------------------------------------- + + @Override + public void visit(final String name, final Object value) { + // Case of an element_value with a const_value_index, class_info_index or array_index field. + // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. + ++numElementValuePairs; + if (useNamedValues) { + annotation.putShort(symbolTable.addConstantUtf8(name)); + } + if (value instanceof String) { + annotation.put12('s', symbolTable.addConstantUtf8((String) value)); + } else if (value instanceof Byte) { + annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index); + } else if (value instanceof Boolean) { + int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0; + annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index); + } else if (value instanceof Character) { + annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index); + } else if (value instanceof Short) { + annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index); + } else if (value instanceof Type) { + annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor())); + } else if (value instanceof byte[]) { + byte[] byteArray = (byte[]) value; + annotation.put12('[', byteArray.length); + for (byte byteValue : byteArray) { + annotation.put12('B', symbolTable.addConstantInteger(byteValue).index); + } + } else if (value instanceof boolean[]) { + boolean[] booleanArray = (boolean[]) value; + annotation.put12('[', booleanArray.length); + for (boolean booleanValue : booleanArray) { + annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index); + } + } else if (value instanceof short[]) { + short[] shortArray = (short[]) value; + annotation.put12('[', shortArray.length); + for (short shortValue : shortArray) { + annotation.put12('S', symbolTable.addConstantInteger(shortValue).index); + } + } else if (value instanceof char[]) { + char[] charArray = (char[]) value; + annotation.put12('[', charArray.length); + for (char charValue : charArray) { + annotation.put12('C', symbolTable.addConstantInteger(charValue).index); + } + } else if (value instanceof int[]) { + int[] intArray = (int[]) value; + annotation.put12('[', intArray.length); + for (int intValue : intArray) { + annotation.put12('I', symbolTable.addConstantInteger(intValue).index); + } + } else if (value instanceof long[]) { + long[] longArray = (long[]) value; + annotation.put12('[', longArray.length); + for (long longValue : longArray) { + annotation.put12('J', symbolTable.addConstantLong(longValue).index); + } + } else if (value instanceof float[]) { + float[] floatArray = (float[]) value; + annotation.put12('[', floatArray.length); + for (float floatValue : floatArray) { + annotation.put12('F', symbolTable.addConstantFloat(floatValue).index); + } + } else if (value instanceof double[]) { + double[] doubleArray = (double[]) value; + annotation.put12('[', doubleArray.length); + for (double doubleValue : doubleArray) { + annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index); + } + } else { + Symbol symbol = symbolTable.addConstant(value); + annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index); } + } - @Override - public void visitEnum(final String name, final String desc, - final String value) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); + @Override + public void visitEnum(final String name, final String descriptor, final String value) { + // Case of an element_value with an enum_const_value field. + // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. + ++numElementValuePairs; + if (useNamedValues) { + annotation.putShort(symbolTable.addConstantUtf8(name)); } + annotation + .put12('e', symbolTable.addConstantUtf8(descriptor)) + .putShort(symbolTable.addConstantUtf8(value)); + } - @Override - public AnnotationVisitor visitAnnotation(final String name, - final String desc) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag and type, and reserve space for values count - bv.put12('@', cw.newUTF8(desc)).putShort(0); - return new AnnotationWriter(cw, true, bv, bv, bv.length - 2); + @Override + public AnnotationVisitor visitAnnotation(final String name, final String descriptor) { + // Case of an element_value with an annotation_value field. + // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. + ++numElementValuePairs; + if (useNamedValues) { + annotation.putShort(symbolTable.addConstantUtf8(name)); } + // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs. + annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0); + return new AnnotationWriter(symbolTable, annotation, null); + } - @Override - public AnnotationVisitor visitArray(final String name) { - ++size; - if (named) { - bv.putShort(cw.newUTF8(name)); - } - // write tag, and reserve space for array size - bv.put12('[', 0); - return new AnnotationWriter(cw, false, bv, bv, bv.length - 2); + @Override + public AnnotationVisitor visitArray(final String name) { + // Case of an element_value with an array_value field. + // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1 + ++numElementValuePairs; + if (useNamedValues) { + annotation.putShort(symbolTable.addConstantUtf8(name)); } + // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the + // end of an element_value of array type is similar to the end of an 'annotation' structure: an + // unsigned short num_values followed by num_values element_value, versus an unsigned short + // num_element_value_pairs, followed by num_element_value_pairs { element_name_index, + // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to + // visit the array elements. Its num_element_value_pairs will correspond to the number of array + // elements and will be stored in what is in fact num_values. + annotation.put12('[', 0); + return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null); + } - @Override - public void visitEnd() { - if (parent != null) { - byte[] data = parent.data; - data[offset] = (byte) (size >>> 8); - data[offset + 1] = (byte) size; - } + @Override + public void visitEnd() { + if (numElementValuePairsOffset != -1) { + byte[] data = annotation.data; + data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8); + data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs; } + } - // ------------------------------------------------------------------------ - // Utility methods - // ------------------------------------------------------------------------ + // ----------------------------------------------------------------------------------------------- + // Utility methods + // ----------------------------------------------------------------------------------------------- - /** - * Returns the size of this annotation writer list. - * - * @return the size of this annotation writer list. - */ - int getSize() { - int size = 0; - AnnotationWriter aw = this; - while (aw != null) { - size += aw.bv.length; - aw = aw.next; - } - return size; + /** + * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation + * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name + * to the constant pool of the class (if not null). + * + * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null. + * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this + * annotation and all its predecessors. This includes the size of the attribute_name_index and + * attribute_length fields. + */ + int computeAnnotationsSize(final String attributeName) { + if (attributeName != null) { + symbolTable.addConstantUtf8(attributeName); + } + // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes. + int attributeSize = 8; + AnnotationWriter annotationWriter = this; + while (annotationWriter != null) { + attributeSize += annotationWriter.annotation.length; + annotationWriter = annotationWriter.previousAnnotation; } + return attributeSize; + } - /** - * Puts the annotations of this annotation writer list into the given byte - * vector. - * - * @param out - * where the annotations must be put. - */ - void put(final ByteVector out) { - int n = 0; - int size = 2; - AnnotationWriter aw = this; - AnnotationWriter last = null; - while (aw != null) { - ++n; - size += aw.bv.length; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putInt(size); - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } + /** + * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its + * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are + * put in the same order they have been visited. + * + * @param attributeNameIndex the constant pool index of the attribute name (one of + * "Runtime[In]Visible[Type]Annotations"). + * @param output where the attribute must be put. + */ + void putAnnotations(final int attributeNameIndex, final ByteVector output) { + int attributeLength = 2; // For num_annotations. + int numAnnotations = 0; + AnnotationWriter annotationWriter = this; + AnnotationWriter firstAnnotation = null; + while (annotationWriter != null) { + // In case the user forgot to call visitEnd(). + annotationWriter.visitEnd(); + attributeLength += annotationWriter.annotation.length; + numAnnotations++; + firstAnnotation = annotationWriter; + annotationWriter = annotationWriter.previousAnnotation; } + output.putShort(attributeNameIndex); + output.putInt(attributeLength); + output.putShort(numAnnotations); + annotationWriter = firstAnnotation; + while (annotationWriter != null) { + output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length); + annotationWriter = annotationWriter.nextAnnotation; + } + } - /** - * 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. - */ - 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(); - } - out.putInt(size).putByte(panns.length - off); - for (int i = off; i < panns.length; ++i) { - AnnotationWriter aw = panns[i]; - AnnotationWriter last = null; - int n = 0; - while (aw != null) { - ++n; - aw.visitEnd(); // in case user forgot to call visitEnd - aw.prev = last; - last = aw; - aw = aw.next; - } - out.putShort(n); - aw = last; - while (aw != null) { - out.putByteArray(aw.bv.data, 0, aw.bv.length); - aw = aw.prev; - } - } + /** + * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the + * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the + * constant pool of the class. + * + * @param attributeName one of "Runtime[In]VisibleParameterAnnotations". + * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> + * element). + * @param annotableParameterCount the number of elements in annotationWriters to take into account + * (elements [0..annotableParameterCount[ are taken into account). + * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding + * to the given sub-array of AnnotationWriter lists. This includes the size of the + * attribute_name_index and attribute_length fields. + */ + static int computeParameterAnnotationsSize( + final String attributeName, + final AnnotationWriter[] annotationWriters, + final int annotableParameterCount) { + // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize + // below. This assumes that there is at least one non-null element in the annotationWriters + // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter). + // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each + // element of the parameter_annotations array uses 2 bytes for its num_annotations field. + int attributeSize = 7 + 2 * annotableParameterCount; + for (int i = 0; i < annotableParameterCount; ++i) { + AnnotationWriter annotationWriter = annotationWriters[i]; + attributeSize += + annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8; } + return attributeSize; + } - /** - * 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); - } + /** + * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists + * from the given AnnotationWriter sub-array in the given ByteVector. + * + * @param attributeNameIndex constant pool index of the attribute name (one of + * Runtime[In]VisibleParameterAnnotations). + * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> + * element). + * @param annotableParameterCount the number of elements in annotationWriters to put (elements + * [0..annotableParameterCount[ are put). + * @param output where the attribute must be put. + */ + static void putParameterAnnotations( + final int attributeNameIndex, + final AnnotationWriter[] annotationWriters, + final int annotableParameterCount, + final ByteVector output) { + // The num_parameters field uses 1 byte, and each element of the parameter_annotations array + // uses 2 bytes for its num_annotations field. + int attributeLength = 1 + 2 * annotableParameterCount; + for (int i = 0; i < annotableParameterCount; ++i) { + AnnotationWriter annotationWriter = annotationWriters[i]; + attributeLength += + annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8; + } + output.putShort(attributeNameIndex); + output.putInt(attributeLength); + output.putByte(annotableParameterCount); + for (int i = 0; i < annotableParameterCount; ++i) { + AnnotationWriter annotationWriter = annotationWriters[i]; + AnnotationWriter firstAnnotation = null; + int numAnnotations = 0; + while (annotationWriter != null) { + // In case user the forgot to call visitEnd(). + annotationWriter.visitEnd(); + numAnnotations++; + firstAnnotation = annotationWriter; + annotationWriter = annotationWriter.previousAnnotation; + } + output.putShort(numAnnotations); + annotationWriter = firstAnnotation; + while (annotationWriter != null) { + output.putByteArray( + annotationWriter.annotation.data, 0, annotationWriter.annotation.length); + annotationWriter = annotationWriter.nextAnnotation; + } } + } } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/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 old mode 100644 new mode 100755 index fae580f..c062ade --- 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 @@ -1,255 +1,325 @@ -/*** - * 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. - */ +// 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; /** - * A non standard class, field, method or code attribute. - * + * A non standard class, field, method or code attribute, as defined in the Java Virtual Machine + * Specification (JVMS). + * + * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS + * 4.7</a> + * @see <a href= "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS + * 4.7.3</a> * @author Eric Bruneton * @author Eugene Kuleshov */ public class Attribute { - /** - * The type of this attribute. - */ - public final String type; - - /** - * The raw value of this attribute, used only for unknown attributes. - */ - byte[] value; - - /** - * The next attribute in this attribute list. May be <tt>null</tt>. - */ - Attribute next; - - /** - * Constructs a new empty attribute. - * - * @param type - * the type of the attribute. - */ - protected Attribute(final String type) { - this.type = type; - } + /** The type of this attribute, also called its name in the JVMS. */ + public final String type; - /** - * 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() { - return true; - } + /** + * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}). + * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i> + * included. + */ + private byte[] content; - /** - * 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() { - return false; - } + /** + * The next attribute in this attribute list (Attribute instances can be linked via this field to + * store a list of class, field, method or code attributes). May be {@literal null}. + */ + Attribute nextAttribute; + + /** + * Constructs a new empty attribute. + * + * @param type the type of the attribute. + */ + protected Attribute(final String type) { + this.type = type; + } + + /** + * Returns {@literal true} if this type of attribute is unknown. This means that the attribute + * content can't be parsed to extract constant pool references, labels, etc. Instead, the + * attribute content is read as an opaque byte array, and written back as is. This can lead to + * invalid attributes, if the content actually contains constant pool references, labels, or other + * symbolic references that need to be updated when there are changes to the constant pool, the + * method bytecode, etc. The default implementation of this method always returns {@literal true}. + * + * @return {@literal true} if this type of attribute is unknown. + */ + public boolean isUnknown() { + return true; + } + + /** + * Returns {@literal true} if this type of attribute is a code attribute. + * + * @return {@literal true} if this type of attribute is a code attribute. + */ + public boolean isCodeAttribute() { + return false; + } + + /** + * Returns the labels corresponding to this attribute. + * + * @return the labels corresponding to this attribute, or {@literal null} if this attribute is not + * a code attribute that contains labels. + */ + protected Label[] getLabels() { + return new Label[0]; + } - /** - * 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. - */ - protected Label[] getLabels() { - return null; + /** + * Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object, + * of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given + * ClassReader. + * + * @param classReader the class that contains the attribute to be read. + * @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The + * 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into + * account here. + * @param length the length of the attribute's content (excluding the 6 attribute header bytes). + * @param charBuffer the buffer to be used to call the ClassReader methods requiring a + * 'charBuffer' parameter. + * @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute + * in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6 + * attribute header bytes (attribute_name_index and attribute_length) are not taken into + * account here. + * @param labels the labels of the method's code, or {@literal null} if the attribute to be read + * is not a code attribute. + * @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes. + */ + protected Attribute read( + final ClassReader classReader, + final int offset, + final int length, + final char[] charBuffer, + final int codeAttributeOffset, + final Label[] labels) { + Attribute attribute = new Attribute(type); + attribute.content = new byte[length]; + System.arraycopy(classReader.b, offset, attribute.content, 0, length); + return attribute; + } + + /** + * Returns the byte array form of the content of this attribute. The 6 header bytes + * (attribute_name_index and attribute_length) must <i>not</i> be added in the returned + * ByteVector. + * + * @param classWriter the class to which this attribute must be added. This parameter can be used + * to add the items that corresponds to this attribute to the constant pool of this class. + * @param code the bytecode of the method corresponding to this code attribute, or {@literal null} + * if this attribute is not a code attribute. Corresponds to the 'code' field of the Code + * attribute. + * @param codeLength the length of the bytecode of the method corresponding to this code + * attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length' + * field of the 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 classWriter, + final byte[] code, + final int codeLength, + final int maxStack, + final int maxLocals) { + return new ByteVector(content); + } + + /** + * Returns the number of attributes of the attribute list that begins with this attribute. + * + * @return the number of attributes of the attribute list that begins with this attribute. + */ + final int getAttributeCount() { + int count = 0; + Attribute attribute = this; + while (attribute != null) { + count += 1; + attribute = attribute.nextAttribute; } + return count; + } + + /** + * Returns the total size in bytes of all the attributes in the attribute list that begins with + * this attribute. This size includes the 6 header bytes (attribute_name_index and + * attribute_length) per attribute. Also adds the attribute type names to the constant pool. + * + * @param symbolTable where the constants used in the attributes must be stored. + * @return the size of all the attributes in this attribute list. This size includes the size of + * the attribute headers. + */ + final int computeAttributesSize(final SymbolTable symbolTable) { + final byte[] code = null; + final int codeLength = 0; + final int maxStack = -1; + final int maxLocals = -1; + return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals); + } - /** - * 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) { - Attribute attr = new Attribute(type); - attr.value = new byte[len]; - System.arraycopy(cr.b, off, attr.value, 0, len); - return attr; + /** + * Returns the total size in bytes of all the attributes in the attribute list that begins with + * this attribute. This size includes the 6 header bytes (attribute_name_index and + * attribute_length) per attribute. Also adds the attribute type names to the constant pool. + * + * @param symbolTable where the constants used in the attributes must be stored. + * @param code the bytecode of the method corresponding to these code attributes, or {@literal + * null} if they are not code attributes. Corresponds to the 'code' field of the Code + * attribute. + * @param codeLength the length of the bytecode of the method corresponding to these code + * attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of + * the Code attribute. + * @param maxStack the maximum stack size of the method corresponding to these code attributes, or + * -1 if they are not code attributes. + * @param maxLocals the maximum number of local variables of the method corresponding to these + * code attributes, or -1 if they are not code attribute. + * @return the size of all the attributes in this attribute list. This size includes the size of + * the attribute headers. + */ + final int computeAttributesSize( + final SymbolTable symbolTable, + final byte[] code, + final int codeLength, + final int maxStack, + final int maxLocals) { + final ClassWriter classWriter = symbolTable.classWriter; + int size = 0; + Attribute attribute = this; + while (attribute != null) { + symbolTable.addConstantUtf8(attribute.type); + size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length; + attribute = attribute.nextAttribute; } + return size; + } - /** - * 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. - * @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) { - ByteVector v = new ByteVector(); - v.data = value; - v.length = value.length; - return v; + /** + * Puts all the attributes of the attribute list that begins with this attribute, in the given + * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per + * attribute. + * + * @param symbolTable where the constants used in the attributes must be stored. + * @param output where the attributes must be written. + */ + final void putAttributes(final SymbolTable symbolTable, final ByteVector output) { + final byte[] code = null; + final int codeLength = 0; + final int maxStack = -1; + final int maxLocals = -1; + putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output); + } + + /** + * Puts all the attributes of the attribute list that begins with this attribute, in the given + * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per + * attribute. + * + * @param symbolTable where the constants used in the attributes must be stored. + * @param code the bytecode of the method corresponding to these code attributes, or {@literal + * null} if they are not code attributes. Corresponds to the 'code' field of the Code + * attribute. + * @param codeLength the length of the bytecode of the method corresponding to these code + * attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of + * the Code attribute. + * @param maxStack the maximum stack size of the method corresponding to these code attributes, or + * -1 if they are not code attributes. + * @param maxLocals the maximum number of local variables of the method corresponding to these + * code attributes, or -1 if they are not code attribute. + * @param output where the attributes must be written. + */ + final void putAttributes( + final SymbolTable symbolTable, + final byte[] code, + final int codeLength, + final int maxStack, + final int maxLocals, + final ByteVector output) { + final ClassWriter classWriter = symbolTable.classWriter; + Attribute attribute = this; + while (attribute != null) { + ByteVector attributeContent = + attribute.write(classWriter, code, codeLength, maxStack, maxLocals); + // Put attribute_name_index and attribute_length. + output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length); + output.putByteArray(attributeContent.data, 0, attributeContent.length); + attribute = attribute.nextAttribute; } + } + + /** A set of attribute prototypes (attributes with the same type are considered equal). */ + static final class Set { - /** - * 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() { - int count = 0; - Attribute attr = this; - while (attr != null) { - count += 1; - attr = attr.next; + private static final int SIZE_INCREMENT = 6; + + private int size; + private Attribute[] data = new Attribute[SIZE_INCREMENT]; + + void addAttributes(final Attribute attributeList) { + Attribute attribute = attributeList; + while (attribute != null) { + if (!contains(attribute)) { + add(attribute); } - return count; + attribute = attribute.nextAttribute; + } } - /** - * 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. - * @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) { - Attribute attr = this; - int size = 0; - while (attr != null) { - cw.newUTF8(attr.type); - size += attr.write(cw, code, len, maxStack, maxLocals).length + 6; - attr = attr.next; - } - return size; + Attribute[] toArray() { + Attribute[] result = new Attribute[size]; + System.arraycopy(data, 0, result, 0, size); + return result; } - /** - * 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. - */ - 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); - out.putShort(cw.newUTF8(attr.type)).putInt(b.length); - out.putByteArray(b.data, 0, b.length); - attr = attr.next; + private boolean contains(final Attribute attribute) { + for (int i = 0; i < size; ++i) { + if (data[i].type.equals(attribute.type)) { + return true; } + } + return false; + } + + private void add(final Attribute attribute) { + if (size >= data.length) { + Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + } + data[size++] = attribute; } + } }
