--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel;
+
+/**
+ * Constants for the project, mostly defined in the JVM specification.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface Constants {
+
+ /** Major version number of class files for Java 1.1.
+ * @see #MINOR_1_1
+ * */
+ public final static short MAJOR_1_1 = 45;
+
+ /** Minor version number of class files for Java 1.1.
+ * @see #MAJOR_1_1
+ * */
+ public final static short MINOR_1_1 = 3;
+
+ /** Major version number of class files for Java 1.2.
+ * @see #MINOR_1_2
+ * */
+ public final static short MAJOR_1_2 = 46;
+
+ /** Minor version number of class files for Java 1.2.
+ * @see #MAJOR_1_2
+ * */
+ public final static short MINOR_1_2 = 0;
+
+ /** Major version number of class files for Java 1.2.
+ * @see #MINOR_1_2
+ * */
+ public final static short MAJOR_1_3 = 47;
+
+ /** Minor version number of class files for Java 1.3.
+ * @see #MAJOR_1_3
+ * */
+ public final static short MINOR_1_3 = 0;
+
+ /** Major version number of class files for Java 1.3.
+ * @see #MINOR_1_3
+ * */
+ public final static short MAJOR_1_4 = 48;
+
+ /** Minor version number of class files for Java 1.4.
+ * @see #MAJOR_1_4
+ * */
+ public final static short MINOR_1_4 = 0;
+
+ /** Major version number of class files for Java 1.4.
+ * @see #MINOR_1_4
+ * */
+ public final static short MAJOR_1_5 = 49;
+
+ /** Minor version number of class files for Java 1.5.
+ * @see #MAJOR_1_5
+ * */
+ public final static short MINOR_1_5 = 0;
+
+ /** Major version number of class files for Java 1.5.
+ * @see #MINOR_1_5
+ * */
+ public final static short MAJOR_1_6 = 50;
+
+ /** Minor version number of class files for Java 1.6.
+ * @see #MAJOR_1_6
+ * */
+ public final static short MINOR_1_6 = 0;
+
+ /** Default major version number. Class file is for Java 1.1.
+ * @see #MAJOR_1_1
+ * */
+ public final static short MAJOR = MAJOR_1_1;
+
+ /** Default major version number. Class file is for Java 1.1.
+ * @see #MAJOR_1_1
+ * */
+ public final static short MINOR = MINOR_1_1;
+
+ /** Maximum value for an unsigned short.
+ */
+ public final static int MAX_SHORT = 65535; // 2^16 - 1
+
+ /** Maximum value for an unsigned byte.
+ */
+ public final static int MAX_BYTE = 255; // 2^8 - 1
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see <a href='http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#2877'>Flag definitions for Fields in the Java Virtual Machine Specification (2nd edition).</a>
+ * @see <a href='http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#1513'>Flag definitions for Methods in the Java Virtual Machine Specification (2nd edition).</a>
+ * @see <a href='http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88478'>Flag definitions for Classes in the Java Virtual Machine Specification (2nd edition).</a>
+ */
+ public final static short ACC_PUBLIC = 0x0001;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_PRIVATE = 0x0002;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_PROTECTED = 0x0004;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_STATIC = 0x0008;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_FINAL = 0x0010;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_SYNCHRONIZED = 0x0020;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_SYPER = 0x0020;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_VOLATILE = 0x0040;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_BRIDGE = 0x0040;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_TRANSIENT = 0x0080;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_VARARGS = 0x0080;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_NATIVE = 0x0100;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_INTERFACE = 0x0200;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_ABSTRACT = 0x0400;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_STRICT = 0x0800;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_SYNTHETIC = 0x1000;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_ANNOTATION = 0x2000;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_ENUM = 0x4000;
+
+ // Applies to classes compiled by new compilers only
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short ACC_SUPER = 0x0020;
+
+ /** One of the access flags for fields, methods, or classes.
+ * @see #ACC_PUBLIC
+ */
+ public final static short MAX_ACC_FLAG = ACC_ENUM;
+
+ /** The names of the access flags. */
+ public final static String[] ACCESS_NAMES = {
+ "public", "private", "protected", "static", "final", "synchronized",
+ "volatile", "transient", "native", "interface", "abstract", "strictfp",
+ "synthetic", "annotation", "enum"
+ };
+
+ /** Marks a constant pool entry as type UTF-8. */
+ public final static byte CONSTANT_Utf8 = 1;
+
+ /** Marks a constant pool entry as type Integer. */
+ public final static byte CONSTANT_Integer = 3;
+
+ /** Marks a constant pool entry as type Float. */
+ public final static byte CONSTANT_Float = 4;
+
+ /** Marks a constant pool entry as type Long. */
+ public final static byte CONSTANT_Long = 5;
+
+ /** Marks a constant pool entry as type Double. */
+ public final static byte CONSTANT_Double = 6;
+
+ /** Marks a constant pool entry as a Class. */
+ public final static byte CONSTANT_Class = 7;
+
+ /** Marks a constant pool entry as a Field Reference. */
+ public final static byte CONSTANT_Fieldref = 9;
+
+ /** Marks a constant pool entry as type String. */
+ public final static byte CONSTANT_String = 8;
+
+ /** Marks a constant pool entry as a Method Reference. */
+ public final static byte CONSTANT_Methodref = 10;
+
+ /** Marks a constant pool entry as an Interface Method Reference. */
+ public final static byte CONSTANT_InterfaceMethodref = 11;
+
+ /** Marks a constant pool entry as a name and type. */
+ public final static byte CONSTANT_NameAndType = 12;
+
+ /** The names of the types of entries in a constant pool. */
+ public final static String[] CONSTANT_NAMES = {
+ "", "CONSTANT_Utf8", "", "CONSTANT_Integer",
+ "CONSTANT_Float", "CONSTANT_Long", "CONSTANT_Double",
+ "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref",
+ "CONSTANT_Methodref", "CONSTANT_InterfaceMethodref",
+ "CONSTANT_NameAndType" };
+
+ /** The name of the static initializer, also called "class
+ * initialization method" or "interface initialization
+ * method". This is "<clinit>".
+ */
+ public final static String STATIC_INITIALIZER_NAME = "<clinit>";
+
+ /** The name of every constructor method in a class, also called
+ * "instance initialization method". This is "<init>".
+ */
+ public final static String CONSTRUCTOR_NAME = "<init>";
+
+ /** The names of the interfaces implemented by arrays */
+ public final static String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"};
+
+ /**
+ * One of the limitations of the Java Virtual Machine.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88659"> The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10.</a>
+ */
+ public static final int MAX_CP_ENTRIES = 65535;
+
+ /**
+ * One of the limitations of the Java Virtual Machine.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#88659"> The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10.</a>
+ */
+ public static final int MAX_CODE_SIZE = 65536; //bytes
+
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short NOP = 0;
+
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ACONST_NULL = 1;
+
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_M1 = 2;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_0 = 3;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_1 = 4;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_2 = 5;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_3 = 6;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_4 = 7;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ICONST_5 = 8;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LCONST_0 = 9;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LCONST_1 = 10;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FCONST_0 = 11;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FCONST_1 = 12;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FCONST_2 = 13;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DCONST_0 = 14;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DCONST_1 = 15;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short BIPUSH = 16;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short SIPUSH = 17;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LDC = 18;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LDC_W = 19;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LDC2_W = 20;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ILOAD = 21;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LLOAD = 22;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FLOAD = 23;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DLOAD = 24;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ALOAD = 25;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ILOAD_0 = 26;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ILOAD_1 = 27;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ILOAD_2 = 28;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ILOAD_3 = 29;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LLOAD_0 = 30;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LLOAD_1 = 31;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LLOAD_2 = 32;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LLOAD_3 = 33;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FLOAD_0 = 34;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FLOAD_1 = 35;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FLOAD_2 = 36;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FLOAD_3 = 37;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DLOAD_0 = 38;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DLOAD_1 = 39;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DLOAD_2 = 40;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DLOAD_3 = 41;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ALOAD_0 = 42;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ALOAD_1 = 43;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ALOAD_2 = 44;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ALOAD_3 = 45;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IALOAD = 46;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LALOAD = 47;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FALOAD = 48;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DALOAD = 49;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short AALOAD = 50;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short BALOAD = 51;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short CALOAD = 52;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short SALOAD = 53;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISTORE = 54;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSTORE = 55;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSTORE = 56;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSTORE = 57;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ASTORE = 58;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISTORE_0 = 59;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISTORE_1 = 60;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISTORE_2 = 61;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISTORE_3 = 62;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSTORE_0 = 63;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSTORE_1 = 64;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSTORE_2 = 65;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSTORE_3 = 66;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSTORE_0 = 67;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSTORE_1 = 68;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSTORE_2 = 69;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSTORE_3 = 70;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSTORE_0 = 71;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSTORE_1 = 72;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSTORE_2 = 73;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSTORE_3 = 74;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ASTORE_0 = 75;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ASTORE_1 = 76;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ASTORE_2 = 77;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ASTORE_3 = 78;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IASTORE = 79;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LASTORE = 80;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FASTORE = 81;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DASTORE = 82;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short AASTORE = 83;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short BASTORE = 84;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short CASTORE = 85;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short SASTORE = 86;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short POP = 87;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short POP2 = 88;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP = 89;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP_X1 = 90;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP_X2 = 91;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP2 = 92;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP2_X1 = 93;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DUP2_X2 = 94;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short SWAP = 95;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IADD = 96;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LADD = 97;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FADD = 98;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DADD = 99;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISUB = 100;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSUB = 101;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FSUB = 102;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DSUB = 103;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IMUL = 104;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LMUL = 105;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FMUL = 106;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DMUL = 107;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IDIV = 108;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LDIV = 109;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FDIV = 110;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DDIV = 111;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IREM = 112;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LREM = 113;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FREM = 114;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DREM = 115;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INEG = 116;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LNEG = 117;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FNEG = 118;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DNEG = 119;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISHL = 120;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSHL = 121;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ISHR = 122;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LSHR = 123;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IUSHR = 124;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LUSHR = 125;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IAND = 126;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LAND = 127;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IOR = 128;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LOR = 129;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IXOR = 130;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LXOR = 131;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IINC = 132;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2L = 133;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2F = 134;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2D = 135;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short L2I = 136;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short L2F = 137;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short L2D = 138;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short F2I = 139;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short F2L = 140;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short F2D = 141;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short D2I = 142;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short D2L = 143;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short D2F = 144;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2B = 145;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INT2BYTE = 145; // Old notion
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2C = 146;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INT2CHAR = 146; // Old notion
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short I2S = 147;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INT2SHORT = 147; // Old notion
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LCMP = 148;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FCMPL = 149;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FCMPG = 150;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DCMPL = 151;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DCMPG = 152;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFEQ = 153;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFNE = 154;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFLT = 155;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFGE = 156;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFGT = 157;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFLE = 158;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPEQ = 159;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPNE = 160;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPLT = 161;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPGE = 162;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPGT = 163;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ICMPLE = 164;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ACMPEQ = 165;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IF_ACMPNE = 166;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short GOTO = 167;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short JSR = 168;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short RET = 169;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short TABLESWITCH = 170;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LOOKUPSWITCH = 171;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IRETURN = 172;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short LRETURN = 173;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short FRETURN = 174;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short DRETURN = 175;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ARETURN = 176;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short RETURN = 177;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short GETSTATIC = 178;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short PUTSTATIC = 179;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short GETFIELD = 180;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short PUTFIELD = 181;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKEVIRTUAL = 182;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKESPECIAL = 183;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKESTATIC = 184;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKEINTERFACE = 185;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INVOKEDYNAMIC = 186;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short NEW = 187;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short NEWARRAY = 188;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ANEWARRAY = 189;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ARRAYLENGTH = 190;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short ATHROW = 191;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short CHECKCAST = 192;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short INSTANCEOF = 193;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short MONITORENTER = 194;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short MONITOREXIT = 195;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short WIDE = 196;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short MULTIANEWARRAY = 197;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFNULL = 198;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short IFNONNULL = 199;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short GOTO_W = 200;
+ /** Java VM opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc.html">Opcode definitions in The Java Virtual Machine Specification</a> */
+ public static final short JSR_W = 201;
+
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html#60105">Reserved opcodes in the Java Virtual Machine Specification</a> */
+ public static final short BREAKPOINT = 202;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short LDC_QUICK = 203;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short LDC_W_QUICK = 204;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short LDC2_W_QUICK = 205;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short GETFIELD_QUICK = 206;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short PUTFIELD_QUICK = 207;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short GETFIELD2_QUICK = 208;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short PUTFIELD2_QUICK = 209;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short GETSTATIC_QUICK = 210;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short PUTSTATIC_QUICK = 211;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short GETSTATIC2_QUICK = 212;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short PUTSTATIC2_QUICK = 213;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKEVIRTUAL_QUICK = 214;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKENONVIRTUAL_QUICK = 215;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKESUPER_QUICK = 216;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKESTATIC_QUICK = 217;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKEINTERFACE_QUICK = 218;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKEVIRTUALOBJECT_QUICK = 219;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short NEW_QUICK = 221;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short ANEWARRAY_QUICK = 222;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short MULTIANEWARRAY_QUICK = 223;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short CHECKCAST_QUICK = 224;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INSTANCEOF_QUICK = 225;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short INVOKEVIRTUAL_QUICK_W = 226;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short GETFIELD_QUICK_W = 227;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/first_edition/html/Quick.doc.html#10673">Specification of _quick opcodes in the Java Virtual Machine Specification (version 1)</a>
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ChangesAppendix.doc.html#448885">Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification.</a> */
+ public static final short PUTFIELD_QUICK_W = 228;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html#60105">Reserved opcodes in the Java Virtual Machine Specification</a> */
+ public static final short IMPDEP1 = 254;
+ /** JVM internal opcode.
+ * @see <a href="http://java.sun.com/docs/books/jvms/second_edition/html/Instructions.doc.html#60105">Reserved opcodes in the Java Virtual Machine Specification</a> */
+ public static final short IMPDEP2 = 255;
+
+ /**
+ * BCEL virtual instruction for pushing an arbitrary data type onto the stack. Will be converted to the appropriate JVM
+ * opcode when the class is dumped.
+ */
+ public static final short PUSH = 4711;
+ /**
+ * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH. Will be converted to the appropriate JVM
+ * opcode when the class is dumped.
+ */
+ public static final short SWITCH = 4712;
+
+ /** Illegal opcode. */
+ public static final short UNDEFINED = -1;
+ /** Illegal opcode. */
+ public static final short UNPREDICTABLE = -2;
+ /** Illegal opcode. */
+ public static final short RESERVED = -3;
+ /** Mnemonic for an illegal opcode. */
+ public static final String ILLEGAL_OPCODE = "<illegal opcode>";
+ /** Mnemonic for an illegal type. */
+ public static final String ILLEGAL_TYPE = "<illegal type>";
+
+ /** Boolean data type. */
+ public static final byte T_BOOLEAN = 4;
+ /** Char data type. */
+ public static final byte T_CHAR = 5;
+ /** Float data type. */
+ public static final byte T_FLOAT = 6;
+ /** Double data type. */
+ public static final byte T_DOUBLE = 7;
+ /** Byte data type. */
+ public static final byte T_BYTE = 8;
+ /** Short data type. */
+ public static final byte T_SHORT = 9;
+ /** Int data type. */
+ public static final byte T_INT = 10;
+ /** Long data type. */
+ public static final byte T_LONG = 11;
+
+ /** Void data type (non-standard). */
+ public static final byte T_VOID = 12; // Non-standard
+ /** Array data type. */
+ public static final byte T_ARRAY = 13;
+ /** Object data type. */
+ public static final byte T_OBJECT = 14;
+ /** Reference data type (deprecated). */
+ public static final byte T_REFERENCE = 14; // Deprecated
+ /** Unknown data type. */
+ public static final byte T_UNKNOWN = 15;
+ /** Address data type. */
+ public static final byte T_ADDRESS = 16;
+
+ /** The primitive type names corresponding to the T_XX constants,
+ * e.g., TYPE_NAMES[T_INT] = "int"
+ */
+ public static final String[] TYPE_NAMES = {
+ ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE,
+ "boolean", "char", "float", "double", "byte", "short", "int", "long",
+ "void", "array", "object", "unknown", "address"
+ };
+
+ /** The primitive class names corresponding to the T_XX constants,
+ * e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer"
+ */
+ public static final String[] CLASS_TYPE_NAMES = {
+ ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE,
+ "java.lang.Boolean", "java.lang.Character", "java.lang.Float",
+ "java.lang.Double", "java.lang.Byte", "java.lang.Short",
+ "java.lang.Integer", "java.lang.Long", "java.lang.Void",
+ ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE
+ };
+
+ /** The signature characters corresponding to primitive types,
+ * e.g., SHORT_TYPE_NAMES[T_INT] = "I"
+ */
+ public static final String[] SHORT_TYPE_NAMES = {
+ ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE,
+ "Z", "C", "F", "D", "B", "S", "I", "J",
+ "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE
+ };
+
+ /**
+ * Number of byte code operands for each opcode, i.e., number of bytes after the tag byte
+ * itself. Indexed by opcode, so NO_OF_OPERANDS[BIPUSH] = the number of operands for a bipush
+ * instruction.
+ */
+ public static final short[] NO_OF_OPERANDS = {
+ 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*/, 2/*sipush*/, 1/*ldc*/, 2/*ldc_w*/, 2/*ldc2_w*/,
+ 1/*iload*/, 1/*lload*/, 1/*fload*/, 1/*dload*/, 1/*aload*/,
+ 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, 0/*iload_3*/,
+ 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/,
+ 0/*fload_0*/, 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/,
+ 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, 0/*dload_3*/,
+ 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/,
+ 0/*iaload*/, 0/*laload*/, 0/*faload*/, 0/*daload*/,
+ 0/*aaload*/, 0/*baload*/, 0/*caload*/, 0/*saload*/,
+ 1/*istore*/, 1/*lstore*/, 1/*fstore*/, 1/*dstore*/,
+ 1/*astore*/, 0/*istore_0*/, 0/*istore_1*/, 0/*istore_2*/,
+ 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, 0/*lstore_2*/,
+ 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/,
+ 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/,
+ 0/*dstore_3*/, 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/,
+ 0/*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*/,
+ 2/*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*/, 2/*ifeq*/, 2/*ifne*/,
+ 2/*iflt*/, 2/*ifge*/, 2/*ifgt*/, 2/*ifle*/, 2/*if_icmpeq*/,
+ 2/*if_icmpne*/, 2/*if_icmplt*/, 2/*if_icmpge*/, 2/*if_icmpgt*/,
+ 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, 2/*goto*/,
+ 2/*jsr*/, 1/*ret*/, UNPREDICTABLE/*tableswitch*/, UNPREDICTABLE/*lookupswitch*/,
+ 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/,
+ 0/*dreturn*/, 0/*areturn*/, 0/*return*/,
+ 2/*getstatic*/, 2/*putstatic*/, 2/*getfield*/,
+ 2/*putfield*/, 2/*invokevirtual*/, 2/*invokespecial*/, 2/*invokestatic*/,
+ 4/*invokeinterface*/, UNDEFINED, 2/*new*/,
+ 1/*newarray*/, 2/*anewarray*/,
+ 0/*arraylength*/, 0/*athrow*/, 2/*checkcast*/,
+ 2/*instanceof*/, 0/*monitorenter*/,
+ 0/*monitorexit*/, UNPREDICTABLE/*wide*/, 3/*multianewarray*/,
+ 2/*ifnull*/, 2/*ifnonnull*/, 4/*goto_w*/,
+ 4/*jsr_w*/, 0/*breakpoint*/, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, RESERVED/*impdep1*/, RESERVED/*impdep2*/
+ };
+
+ /**
+ * How the byte code operands are to be interpreted for each opcode.
+ * Indexed by opcode. TYPE_OF_OPERANDS[ILOAD] = an array of shorts
+ * describing the data types for the instruction.
+ */
+ public static final short[][] TYPE_OF_OPERANDS = {
+ {}/*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*/,
+ {T_BYTE}/*bipush*/, {T_SHORT}/*sipush*/, {T_BYTE}/*ldc*/,
+ {T_SHORT}/*ldc_w*/, {T_SHORT}/*ldc2_w*/,
+ {T_BYTE}/*iload*/, {T_BYTE}/*lload*/, {T_BYTE}/*fload*/,
+ {T_BYTE}/*dload*/, {T_BYTE}/*aload*/, {}/*iload_0*/,
+ {}/*iload_1*/, {}/*iload_2*/, {}/*iload_3*/, {}/*lload_0*/,
+ {}/*lload_1*/, {}/*lload_2*/, {}/*lload_3*/, {}/*fload_0*/,
+ {}/*fload_1*/, {}/*fload_2*/, {}/*fload_3*/, {}/*dload_0*/,
+ {}/*dload_1*/, {}/*dload_2*/, {}/*dload_3*/, {}/*aload_0*/,
+ {}/*aload_1*/, {}/*aload_2*/, {}/*aload_3*/, {}/*iaload*/,
+ {}/*laload*/, {}/*faload*/, {}/*daload*/, {}/*aaload*/,
+ {}/*baload*/, {}/*caload*/, {}/*saload*/, {T_BYTE}/*istore*/,
+ {T_BYTE}/*lstore*/, {T_BYTE}/*fstore*/, {T_BYTE}/*dstore*/,
+ {T_BYTE}/*astore*/, {}/*istore_0*/, {}/*istore_1*/,
+ {}/*istore_2*/, {}/*istore_3*/, {}/*lstore_0*/, {}/*lstore_1*/,
+ {}/*lstore_2*/, {}/*lstore_3*/, {}/*fstore_0*/, {}/*fstore_1*/,
+ {}/*fstore_2*/, {}/*fstore_3*/, {}/*dstore_0*/, {}/*dstore_1*/,
+ {}/*dstore_2*/, {}/*dstore_3*/, {}/*astore_0*/, {}/*astore_1*/,
+ {}/*astore_2*/, {}/*astore_3*/, {}/*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*/, {T_BYTE, T_BYTE}/*iinc*/,
+ {}/*i2l*/, {}/*i2f*/, {}/*i2d*/, {}/*l2i*/, {}/*l2f*/, {}/*l2d*/,
+ {}/*f2i*/, {}/*f2l*/, {}/*f2d*/, {}/*d2i*/, {}/*d2l*/, {}/*d2f*/,
+ {}/*i2b*/, {}/*i2c*/,{}/*i2s*/, {}/*lcmp*/, {}/*fcmpl*/,
+ {}/*fcmpg*/, {}/*dcmpl*/, {}/*dcmpg*/, {T_SHORT}/*ifeq*/,
+ {T_SHORT}/*ifne*/, {T_SHORT}/*iflt*/, {T_SHORT}/*ifge*/,
+ {T_SHORT}/*ifgt*/, {T_SHORT}/*ifle*/, {T_SHORT}/*if_icmpeq*/,
+ {T_SHORT}/*if_icmpne*/, {T_SHORT}/*if_icmplt*/,
+ {T_SHORT}/*if_icmpge*/, {T_SHORT}/*if_icmpgt*/,
+ {T_SHORT}/*if_icmple*/, {T_SHORT}/*if_acmpeq*/,
+ {T_SHORT}/*if_acmpne*/, {T_SHORT}/*goto*/, {T_SHORT}/*jsr*/,
+ {T_BYTE}/*ret*/, {}/*tableswitch*/, {}/*lookupswitch*/,
+ {}/*ireturn*/, {}/*lreturn*/, {}/*freturn*/, {}/*dreturn*/,
+ {}/*areturn*/, {}/*return*/, {T_SHORT}/*getstatic*/,
+ {T_SHORT}/*putstatic*/, {T_SHORT}/*getfield*/,
+ {T_SHORT}/*putfield*/, {T_SHORT}/*invokevirtual*/,
+ {T_SHORT}/*invokespecial*/, {T_SHORT}/*invokestatic*/,
+ {T_SHORT, T_BYTE, T_BYTE}/*invokeinterface*/, {},
+ {T_SHORT}/*new*/, {T_BYTE}/*newarray*/,
+ {T_SHORT}/*anewarray*/, {}/*arraylength*/, {}/*athrow*/,
+ {T_SHORT}/*checkcast*/, {T_SHORT}/*instanceof*/,
+ {}/*monitorenter*/, {}/*monitorexit*/, {T_BYTE}/*wide*/,
+ {T_SHORT, T_BYTE}/*multianewarray*/, {T_SHORT}/*ifnull*/,
+ {T_SHORT}/*ifnonnull*/, {T_INT}/*goto_w*/, {T_INT}/*jsr_w*/,
+ {}/*breakpoint*/, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
+ {}/*impdep1*/, {}/*impdep2*/
+ };
+
+ /**
+ * Names of opcodes. Indexed by opcode. OPCODE_NAMES[ALOAD] = "aload".
+ */
+ public static final String[] OPCODE_NAMES = {
+ "nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1",
+ "iconst_2", "iconst_3", "iconst_4", "iconst_5", "lconst_0",
+ "lconst_1", "fconst_0", "fconst_1", "fconst_2", "dconst_0",
+ "dconst_1", "bipush", "sipush", "ldc", "ldc_w", "ldc2_w", "iload",
+ "lload", "fload", "dload", "aload", "iload_0", "iload_1", "iload_2",
+ "iload_3", "lload_0", "lload_1", "lload_2", "lload_3", "fload_0",
+ "fload_1", "fload_2", "fload_3", "dload_0", "dload_1", "dload_2",
+ "dload_3", "aload_0", "aload_1", "aload_2", "aload_3", "iaload",
+ "laload", "faload", "daload", "aaload", "baload", "caload", "saload",
+ "istore", "lstore", "fstore", "dstore", "astore", "istore_0",
+ "istore_1", "istore_2", "istore_3", "lstore_0", "lstore_1",
+ "lstore_2", "lstore_3", "fstore_0", "fstore_1", "fstore_2",
+ "fstore_3", "dstore_0", "dstore_1", "dstore_2", "dstore_3",
+ "astore_0", "astore_1", "astore_2", "astore_3", "iastore", "lastore",
+ "fastore", "dastore", "aastore", "bastore", "castore", "sastore",
+ "pop", "pop2", "dup", "dup_x1", "dup_x2", "dup2", "dup2_x1",
+ "dup2_x2", "swap", "iadd", "ladd", "fadd", "dadd", "isub", "lsub",
+ "fsub", "dsub", "imul", "lmul", "fmul", "dmul", "idiv", "ldiv",
+ "fdiv", "ddiv", "irem", "lrem", "frem", "drem", "ineg", "lneg",
+ "fneg", "dneg", "ishl", "lshl", "ishr", "lshr", "iushr", "lushr",
+ "iand", "land", "ior", "lor", "ixor", "lxor", "iinc", "i2l", "i2f",
+ "i2d", "l2i", "l2f", "l2d", "f2i", "f2l", "f2d", "d2i", "d2l", "d2f",
+ "i2b", "i2c", "i2s", "lcmp", "fcmpl", "fcmpg",
+ "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge", "ifgt", "ifle",
+ "if_icmpeq", "if_icmpne", "if_icmplt", "if_icmpge", "if_icmpgt",
+ "if_icmple", "if_acmpeq", "if_acmpne", "goto", "jsr", "ret",
+ "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn",
+ "dreturn", "areturn", "return", "getstatic", "putstatic", "getfield",
+ "putfield", "invokevirtual", "invokespecial", "invokestatic",
+ "invokeinterface", ILLEGAL_OPCODE, "new", "newarray", "anewarray",
+ "arraylength", "athrow", "checkcast", "instanceof", "monitorenter",
+ "monitorexit", "wide", "multianewarray", "ifnull", "ifnonnull",
+ "goto_w", "jsr_w", "breakpoint", ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE,
+ ILLEGAL_OPCODE, "impdep1", "impdep2"
+ };
+
+ /**
+ * Number of words consumed on operand stack by instructions.
+ * Indexed by opcode. CONSUME_STACK[FALOAD] = number of words
+ * consumed from the stack by a faload instruction.
+ */
+ public static final int[] CONSUME_STACK = {
+ 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*/, 0/*bipush*/, 0/*sipush*/, 0/*ldc*/, 0/*ldc_w*/, 0/*ldc2_w*/, 0/*iload*/,
+ 0/*lload*/, 0/*fload*/, 0/*dload*/, 0/*aload*/, 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/,
+ 0/*iload_3*/, 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, 0/*fload_0*/,
+ 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/,
+ 0/*dload_3*/, 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, 2/*iaload*/,
+ 2/*laload*/, 2/*faload*/, 2/*daload*/, 2/*aaload*/, 2/*baload*/, 2/*caload*/, 2/*saload*/,
+ 1/*istore*/, 2/*lstore*/, 1/*fstore*/, 2/*dstore*/, 1/*astore*/, 1/*istore_0*/,
+ 1/*istore_1*/, 1/*istore_2*/, 1/*istore_3*/, 2/*lstore_0*/, 2/*lstore_1*/,
+ 2/*lstore_2*/, 2/*lstore_3*/, 1/*fstore_0*/, 1/*fstore_1*/, 1/*fstore_2*/,
+ 1/*fstore_3*/, 2/*dstore_0*/, 2/*dstore_1*/, 2/*dstore_2*/, 2/*dstore_3*/,
+ 1/*astore_0*/, 1/*astore_1*/, 1/*astore_2*/, 1/*astore_3*/, 3/*iastore*/, 4/*lastore*/,
+ 3/*fastore*/, 4/*dastore*/, 3/*aastore*/, 3/*bastore*/, 3/*castore*/, 3/*sastore*/,
+ 1/*pop*/, 2/*pop2*/, 1/*dup*/, 2/*dup_x1*/, 3/*dup_x2*/, 2/*dup2*/, 3/*dup2_x1*/,
+ 4/*dup2_x2*/, 2/*swap*/, 2/*iadd*/, 4/*ladd*/, 2/*fadd*/, 4/*dadd*/, 2/*isub*/, 4/*lsub*/,
+ 2/*fsub*/, 4/*dsub*/, 2/*imul*/, 4/*lmul*/, 2/*fmul*/, 4/*dmul*/, 2/*idiv*/, 4/*ldiv*/,
+ 2/*fdiv*/, 4/*ddiv*/, 2/*irem*/, 4/*lrem*/, 2/*frem*/, 4/*drem*/, 1/*ineg*/, 2/*lneg*/,
+ 1/*fneg*/, 2/*dneg*/, 2/*ishl*/, 3/*lshl*/, 2/*ishr*/, 3/*lshr*/, 2/*iushr*/, 3/*lushr*/,
+ 2/*iand*/, 4/*land*/, 2/*ior*/, 4/*lor*/, 2/*ixor*/, 4/*lxor*/, 0/*iinc*/,
+ 1/*i2l*/, 1/*i2f*/, 1/*i2d*/, 2/*l2i*/, 2/*l2f*/, 2/*l2d*/, 1/*f2i*/, 1/*f2l*/,
+ 1/*f2d*/, 2/*d2i*/, 2/*d2l*/, 2/*d2f*/, 1/*i2b*/, 1/*i2c*/, 1/*i2s*/,
+ 4/*lcmp*/, 2/*fcmpl*/, 2/*fcmpg*/, 4/*dcmpl*/, 4/*dcmpg*/, 1/*ifeq*/, 1/*ifne*/,
+ 1/*iflt*/, 1/*ifge*/, 1/*ifgt*/, 1/*ifle*/, 2/*if_icmpeq*/, 2/*if_icmpne*/, 2/*if_icmplt*/,
+ 2 /*if_icmpge*/, 2/*if_icmpgt*/, 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/,
+ 0/*goto*/, 0/*jsr*/, 0/*ret*/, 1/*tableswitch*/, 1/*lookupswitch*/, 1/*ireturn*/,
+ 2/*lreturn*/, 1/*freturn*/, 2/*dreturn*/, 1/*areturn*/, 0/*return*/, 0/*getstatic*/,
+ UNPREDICTABLE/*putstatic*/, 1/*getfield*/, UNPREDICTABLE/*putfield*/,
+ UNPREDICTABLE/*invokevirtual*/, UNPREDICTABLE/*invokespecial*/,
+ UNPREDICTABLE/*invokestatic*/,
+ UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 0/*new*/, 1/*newarray*/, 1/*anewarray*/,
+ 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 1/*monitorenter*/,
+ 1/*monitorexit*/, 0/*wide*/, UNPREDICTABLE/*multianewarray*/, 1/*ifnull*/, 1/*ifnonnull*/,
+ 0/*goto_w*/, 0/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/
+ };
+
+ /**
+ * Number of words produced onto operand stack by instructions.
+ * Indexed by opcode. CONSUME_STACK[DALOAD] = number of words
+ * consumed from the stack by a daload instruction.
+ */
+ public static final int[] PRODUCE_STACK = {
+ 0/*nop*/, 1/*aconst_null*/, 1/*iconst_m1*/, 1/*iconst_0*/, 1/*iconst_1*/,
+ 1/*iconst_2*/, 1/*iconst_3*/, 1/*iconst_4*/, 1/*iconst_5*/, 2/*lconst_0*/,
+ 2/*lconst_1*/, 1/*fconst_0*/, 1/*fconst_1*/, 1/*fconst_2*/, 2/*dconst_0*/,
+ 2/*dconst_1*/, 1/*bipush*/, 1/*sipush*/, 1/*ldc*/, 1/*ldc_w*/, 2/*ldc2_w*/, 1/*iload*/,
+ 2/*lload*/, 1/*fload*/, 2/*dload*/, 1/*aload*/, 1/*iload_0*/, 1/*iload_1*/, 1/*iload_2*/,
+ 1/*iload_3*/, 2/*lload_0*/, 2/*lload_1*/, 2/*lload_2*/, 2/*lload_3*/, 1/*fload_0*/,
+ 1/*fload_1*/, 1/*fload_2*/, 1/*fload_3*/, 2/*dload_0*/, 2/*dload_1*/, 2/*dload_2*/,
+ 2/*dload_3*/, 1/*aload_0*/, 1/*aload_1*/, 1/*aload_2*/, 1/*aload_3*/, 1/*iaload*/,
+ 2/*laload*/, 1/*faload*/, 2/*daload*/, 1/*aaload*/, 1/*baload*/, 1/*caload*/, 1/*saload*/,
+ 0/*istore*/, 0/*lstore*/, 0/*fstore*/, 0/*dstore*/, 0/*astore*/, 0/*istore_0*/,
+ 0/*istore_1*/, 0/*istore_2*/, 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/,
+ 0/*lstore_2*/, 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/,
+ 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, 0/*dstore_3*/,
+ 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/,
+ 0/*fastore*/, 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, 0/*sastore*/,
+ 0/*pop*/, 0/*pop2*/, 2/*dup*/, 3/*dup_x1*/, 4/*dup_x2*/, 4/*dup2*/, 5/*dup2_x1*/,
+ 6/*dup2_x2*/, 2/*swap*/, 1/*iadd*/, 2/*ladd*/, 1/*fadd*/, 2/*dadd*/, 1/*isub*/, 2/*lsub*/,
+ 1/*fsub*/, 2/*dsub*/, 1/*imul*/, 2/*lmul*/, 1/*fmul*/, 2/*dmul*/, 1/*idiv*/, 2/*ldiv*/,
+ 1/*fdiv*/, 2/*ddiv*/, 1/*irem*/, 2/*lrem*/, 1/*frem*/, 2/*drem*/, 1/*ineg*/, 2/*lneg*/,
+ 1/*fneg*/, 2/*dneg*/, 1/*ishl*/, 2/*lshl*/, 1/*ishr*/, 2/*lshr*/, 1/*iushr*/, 2/*lushr*/,
+ 1/*iand*/, 2/*land*/, 1/*ior*/, 2/*lor*/, 1/*ixor*/, 2/*lxor*/,
+ 0/*iinc*/, 2/*i2l*/, 1/*i2f*/, 2/*i2d*/, 1/*l2i*/, 1/*l2f*/, 2/*l2d*/, 1/*f2i*/,
+ 2/*f2l*/, 2/*f2d*/, 1/*d2i*/, 2/*d2l*/, 1/*d2f*/,
+ 1/*i2b*/, 1/*i2c*/, 1/*i2s*/, 1/*lcmp*/, 1/*fcmpl*/, 1/*fcmpg*/,
+ 1/*dcmpl*/, 1/*dcmpg*/, 0/*ifeq*/, 0/*ifne*/, 0/*iflt*/, 0/*ifge*/, 0/*ifgt*/, 0/*ifle*/,
+ 0/*if_icmpeq*/, 0/*if_icmpne*/, 0/*if_icmplt*/, 0/*if_icmpge*/, 0/*if_icmpgt*/,
+ 0/*if_icmple*/, 0/*if_acmpeq*/, 0/*if_acmpne*/, 0/*goto*/, 1/*jsr*/, 0/*ret*/,
+ 0/*tableswitch*/, 0/*lookupswitch*/, 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/,
+ 0/*dreturn*/, 0/*areturn*/, 0/*return*/, UNPREDICTABLE/*getstatic*/, 0/*putstatic*/,
+ UNPREDICTABLE/*getfield*/, 0/*putfield*/, UNPREDICTABLE/*invokevirtual*/,
+ UNPREDICTABLE/*invokespecial*/, UNPREDICTABLE/*invokestatic*/,
+ UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 1/*new*/, 1/*newarray*/, 1/*anewarray*/,
+ 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 0/*monitorenter*/,
+ 0/*monitorexit*/, 0/*wide*/, 1/*multianewarray*/, 0/*ifnull*/, 0/*ifnonnull*/,
+ 0/*goto_w*/, 1/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED,
+ UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/
+ };
+
+ /** Attributes and their corresponding names.
+ */
+ public static final byte ATTR_UNKNOWN = -1;
+ public static final byte ATTR_SOURCE_FILE = 0;
+ public static final byte ATTR_CONSTANT_VALUE = 1;
+ public static final byte ATTR_CODE = 2;
+ public static final byte ATTR_EXCEPTIONS = 3;
+ public static final byte ATTR_LINE_NUMBER_TABLE = 4;
+ public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5;
+ public static final byte ATTR_INNER_CLASSES = 6;
+ public static final byte ATTR_SYNTHETIC = 7;
+ public static final byte ATTR_DEPRECATED = 8;
+ public static final byte ATTR_PMG = 9;
+ public static final byte ATTR_SIGNATURE = 10;
+ public static final byte ATTR_STACK_MAP = 11;
+ public static final byte ATTR_RUNTIME_VISIBLE_ANNOTATIONS = 12;
+ public static final byte ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS = 13;
+ public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = 14;
+ public static final byte ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS = 15;
+ public static final byte ATTR_ANNOTATION_DEFAULT = 16;
+ public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 17;
+ public static final byte ATTR_ENCLOSING_METHOD = 18;
+ public static final byte ATTR_STACK_MAP_TABLE = 19;
+
+ public static final short KNOWN_ATTRIBUTES = 20;
+
+ // TOFO: FIXXXXX
+ public static final String[] ATTRIBUTE_NAMES = {
+ "SourceFile", "ConstantValue", "Code", "Exceptions",
+ "LineNumberTable", "LocalVariableTable",
+ "InnerClasses", "Synthetic", "Deprecated",
+ "PMGClass", "Signature", "StackMap",
+ "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations",
+ "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations",
+ "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", "StackMapTable"
+ };
+
+ /** Constants used in the StackMap attribute.
+ */
+ public static final byte ITEM_Bogus = 0;
+ public static final byte ITEM_Integer = 1;
+ public static final byte ITEM_Float = 2;
+ public static final byte ITEM_Double = 3;
+ public static final byte ITEM_Long = 4;
+ public static final byte ITEM_Null = 5;
+ public static final byte ITEM_InitObject = 6;
+ public static final byte ITEM_Object = 7;
+ public static final byte ITEM_NewObject = 8;
+
+ public static final String[] ITEM_NAMES = {
+ "Bogus", "Integer", "Float", "Double", "Long",
+ "Null", "InitObject", "Object", "NewObject"
+ };
+
+ /** Constants used to identify StackMapEntry types.
+ *
+ * For those types which can specify a range, the
+ * constant names the lowest value.
+ */
+ public static final int SAME_FRAME = 0;
+ public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64;
+ public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247;
+ public static final int CHOP_FRAME = 248;
+ public static final int SAME_FRAME_EXTENDED = 251;
+ public static final int APPEND_FRAME = 252;
+ public static final int FULL_FRAME = 255;
+
+ /** Constants that define the maximum value of
+ * those constants which store ranges. */
+
+ public static final int SAME_FRAME_MAX = 63;
+ public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_MAX = 127;
+ public static final int CHOP_FRAME_MAX = 250;
+ public static final int APPEND_FRAME_MAX = 254;
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel;
+
+/**
+ * Exception constants.
+ *
+ * @version $Id$
+ * @author E. Haase
+ */
+public interface ExceptionConstants {
+
+ /** The mother of all exceptions
+ */
+ public static final Class THROWABLE = Throwable.class;
+ /** Super class of any run-time exception
+ */
+ public static final Class RUNTIME_EXCEPTION = RuntimeException.class;
+ /** Super class of any linking exception (aka Linkage Error)
+ */
+ public static final Class LINKING_EXCEPTION = LinkageError.class;
+ /** Linking Exceptions
+ */
+ public static final Class CLASS_CIRCULARITY_ERROR = ClassCircularityError.class;
+ public static final Class CLASS_FORMAT_ERROR = ClassFormatError.class;
+ public static final Class EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class;
+ public static final Class INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class;
+ public static final Class ABSTRACT_METHOD_ERROR = AbstractMethodError.class;
+ public static final Class ILLEGAL_ACCESS_ERROR = IllegalAccessError.class;
+ public static final Class INSTANTIATION_ERROR = InstantiationError.class;
+ public static final Class NO_SUCH_FIELD_ERROR = NoSuchFieldError.class;
+ public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class;
+ public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class;
+ public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class;
+ public static final Class VERIFY_ERROR = VerifyError.class;
+ /* UnsupportedClassVersionError is new in JDK 1.2 */
+ //public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class;
+ /** Run-Time Exceptions
+ */
+ public static final Class NULL_POINTER_EXCEPTION = NullPointerException.class;
+ public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
+ public static final Class ARITHMETIC_EXCEPTION = ArithmeticException.class;
+ public static final Class NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
+ public static final Class CLASS_CAST_EXCEPTION = ClassCastException.class;
+ public static final Class ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
+ /** Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual
+ * Machine Specification
+ */
+ public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {
+ NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
+ EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR
+ }; // Chapter 5.1
+ public static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = {
+ NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR
+ }; // Chapter 5.2
+ public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
+ public static final Class[] EXCS_STRING_RESOLUTION = new Class[0];
+ // Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
+ public static final Class[] EXCS_ARRAY_EXCEPTION = {
+ NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
+ };
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel;
+
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.bcel.util.ClassPath;
+import org.apache.tomcat.util.bcel.util.SyntheticRepository;
+
+/**
+ * The repository maintains informations about class interdependencies, e.g.,
+ * whether a class is a sub-class of another. Delegates actual class loading
+ * to SyntheticRepository with current class path by default.
+ *
+ * @see org.apache.tomcat.util.bcel.util.Repository
+ * @see org.apache.tomcat.util.bcel.util.SyntheticRepository
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class Repository {
+
+ private static org.apache.tomcat.util.bcel.util.Repository _repository = SyntheticRepository.getInstance();
+
+
+ /** @return currently used repository instance
+ */
+ public static org.apache.tomcat.util.bcel.util.Repository getRepository() {
+ return _repository;
+ }
+
+
+ /** Set repository instance to be used for class loading
+ */
+ public static void setRepository( org.apache.tomcat.util.bcel.util.Repository rep ) {
+ _repository = rep;
+ }
+
+
+ /** Lookup class somewhere found on your CLASSPATH, or whereever the
+ * repository instance looks for it.
+ *
+ * @return class object for given fully qualified class name
+ * @throws ClassNotFoundException if the class could not be found or
+ * parsed correctly
+ */
+ public static JavaClass lookupClass( String class_name ) throws ClassNotFoundException {
+ return _repository.loadClass(class_name);
+ }
+
+
+ /**
+ * Try to find class source using the internal repository instance.
+ * @see Class
+ * @return JavaClass object for given runtime class
+ * @throws ClassNotFoundException if the class could not be found or
+ * parsed correctly
+ */
+ public static JavaClass lookupClass( Class clazz ) throws ClassNotFoundException {
+ return _repository.loadClass(clazz);
+ }
+
+
+ /**
+ * @return class file object for given Java class by looking on the
+ * system class path; returns null if the class file can't be
+ * found
+ */
+ public static ClassPath.ClassFile lookupClassFile( String class_name ) {
+ try {
+ ClassPath path = _repository.getClassPath();
+ if (path == null) {
+ return null;
+ }
+ return path.getClassFile(class_name);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+
+ /** Clear the repository.
+ */
+ public static void clearCache() {
+ _repository.clear();
+ }
+
+
+ /**
+ * Add clazz to repository if there isn't an equally named class already in there.
+ *
+ * @return old entry in repository
+ */
+ public static JavaClass addClass( JavaClass clazz ) {
+ JavaClass old = _repository.findClass(clazz.getClassName());
+ _repository.storeClass(clazz);
+ return old;
+ }
+
+
+ /**
+ * Remove class with given (fully qualified) name from repository.
+ */
+ public static void removeClass( String clazz ) {
+ _repository.removeClass(_repository.findClass(clazz));
+ }
+
+
+ /**
+ * Remove given class from repository.
+ */
+ public static void removeClass( JavaClass clazz ) {
+ _repository.removeClass(clazz);
+ }
+
+
+ /**
+ * @return list of super classes of clazz in ascending order, i.e.,
+ * Object is always the last element
+ * @throws ClassNotFoundException if any of the superclasses can't be found
+ */
+ public static JavaClass[] getSuperClasses( JavaClass clazz ) throws ClassNotFoundException {
+ return clazz.getSuperClasses();
+ }
+
+
+ /**
+ * @return list of super classes of clazz in ascending order, i.e.,
+ * Object is always the last element.
+ * @throws ClassNotFoundException if the named class or any of its
+ * superclasses can't be found
+ */
+ public static JavaClass[] getSuperClasses( String class_name ) throws ClassNotFoundException {
+ JavaClass jc = lookupClass(class_name);
+ return getSuperClasses(jc);
+ }
+
+
+ /**
+ * @return all interfaces implemented by class and its super
+ * classes and the interfaces that those interfaces extend, and so on.
+ * (Some people call this a transitive hull).
+ * @throws ClassNotFoundException if any of the class's
+ * superclasses or superinterfaces can't be found
+ */
+ public static JavaClass[] getInterfaces( JavaClass clazz ) throws ClassNotFoundException {
+ return clazz.getAllInterfaces();
+ }
+
+
+ /**
+ * @return all interfaces implemented by class and its super
+ * classes and the interfaces that extend those interfaces, and so on
+ * @throws ClassNotFoundException if the named class can't be found,
+ * or if any of its superclasses or superinterfaces can't be found
+ */
+ public static JavaClass[] getInterfaces( String class_name ) throws ClassNotFoundException {
+ return getInterfaces(lookupClass(class_name));
+ }
+
+
+ /**
+ * Equivalent to runtime "instanceof" operator.
+ * @return true, if clazz is an instance of super_class
+ * @throws ClassNotFoundException if any superclasses or superinterfaces
+ * of clazz can't be found
+ */
+ public static boolean instanceOf( JavaClass clazz, JavaClass super_class )
+ throws ClassNotFoundException {
+ return clazz.instanceOf(super_class);
+ }
+
+
+ /**
+ * @return true, if clazz is an instance of super_class
+ * @throws ClassNotFoundException if either clazz or super_class
+ * can't be found
+ */
+ public static boolean instanceOf( String clazz, String super_class )
+ throws ClassNotFoundException {
+ return instanceOf(lookupClass(clazz), lookupClass(super_class));
+ }
+
+
+ /**
+ * @return true, if clazz is an instance of super_class
+ * @throws ClassNotFoundException if super_class can't be found
+ */
+ public static boolean instanceOf( JavaClass clazz, String super_class )
+ throws ClassNotFoundException {
+ return instanceOf(clazz, lookupClass(super_class));
+ }
+
+
+ /**
+ * @return true, if clazz is an instance of super_class
+ * @throws ClassNotFoundException if clazz can't be found
+ */
+ public static boolean instanceOf( String clazz, JavaClass super_class )
+ throws ClassNotFoundException {
+ return instanceOf(lookupClass(clazz), super_class);
+ }
+
+
+ /**
+ * @return true, if clazz is an implementation of interface inter
+ * @throws ClassNotFoundException if any superclasses or superinterfaces
+ * of clazz can't be found
+ */
+ public static boolean implementationOf( JavaClass clazz, JavaClass inter )
+ throws ClassNotFoundException {
+ return clazz.implementationOf(inter);
+ }
+
+
+ /**
+ * @return true, if clazz is an implementation of interface inter
+ * @throws ClassNotFoundException if clazz, inter, or any superclasses
+ * or superinterfaces of clazz can't be found
+ */
+ public static boolean implementationOf( String clazz, String inter )
+ throws ClassNotFoundException {
+ return implementationOf(lookupClass(clazz), lookupClass(inter));
+ }
+
+
+ /**
+ * @return true, if clazz is an implementation of interface inter
+ * @throws ClassNotFoundException if inter or any superclasses
+ * or superinterfaces of clazz can't be found
+ */
+ public static boolean implementationOf( JavaClass clazz, String inter )
+ throws ClassNotFoundException {
+ return implementationOf(clazz, lookupClass(inter));
+ }
+
+
+ /**
+ * @return true, if clazz is an implementation of interface inter
+ * @throws ClassNotFoundException if clazz or any superclasses or
+ * superinterfaces of clazz can't be found
+ */
+ public static boolean implementationOf( String clazz, JavaClass inter )
+ throws ClassNotFoundException {
+ return implementationOf(lookupClass(clazz), inter);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Super class for all objects that have modifiers like private, final, ...
+ * I.e. classes, fields, and methods.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class AccessFlags implements java.io.Serializable {
+
+ protected int access_flags;
+
+
+ public AccessFlags() {
+ }
+
+
+ /**
+ * @param a inital access flags
+ */
+ public AccessFlags(int a) {
+ access_flags = a;
+ }
+
+
+ /**
+ * @return Access flags of the object aka. "modifiers".
+ */
+ public final int getAccessFlags() {
+ return access_flags;
+ }
+
+
+ /**
+ * @return Access flags of the object aka. "modifiers".
+ */
+ public final int getModifiers() {
+ return access_flags;
+ }
+
+
+ /** Set access flags aka "modifiers".
+ * @param access_flags Access flags of the object.
+ */
+ public final void setAccessFlags( int access_flags ) {
+ this.access_flags = access_flags;
+ }
+
+
+ /** Set access flags aka "modifiers".
+ * @param access_flags Access flags of the object.
+ */
+ public final void setModifiers( int access_flags ) {
+ setAccessFlags(access_flags);
+ }
+
+
+ private final void setFlag( int flag, boolean set ) {
+ if ((access_flags & flag) != 0) { // Flag is set already
+ if (!set) {
+ access_flags ^= flag;
+ }
+ } else { // Flag not set
+ if (set) {
+ access_flags |= flag;
+ }
+ }
+ }
+
+
+ public final void isPublic( boolean flag ) {
+ setFlag(Constants.ACC_PUBLIC, flag);
+ }
+
+
+ public final boolean isPublic() {
+ return (access_flags & Constants.ACC_PUBLIC) != 0;
+ }
+
+
+ public final void isPrivate( boolean flag ) {
+ setFlag(Constants.ACC_PRIVATE, flag);
+ }
+
+
+ public final boolean isPrivate() {
+ return (access_flags & Constants.ACC_PRIVATE) != 0;
+ }
+
+
+ public final void isProtected( boolean flag ) {
+ setFlag(Constants.ACC_PROTECTED, flag);
+ }
+
+
+ public final boolean isProtected() {
+ return (access_flags & Constants.ACC_PROTECTED) != 0;
+ }
+
+
+ public final void isStatic( boolean flag ) {
+ setFlag(Constants.ACC_STATIC, flag);
+ }
+
+
+ public final boolean isStatic() {
+ return (access_flags & Constants.ACC_STATIC) != 0;
+ }
+
+
+ public final void isFinal( boolean flag ) {
+ setFlag(Constants.ACC_FINAL, flag);
+ }
+
+
+ public final boolean isFinal() {
+ return (access_flags & Constants.ACC_FINAL) != 0;
+ }
+
+
+ public final void isSynchronized( boolean flag ) {
+ setFlag(Constants.ACC_SYNCHRONIZED, flag);
+ }
+
+
+ public final boolean isSynchronized() {
+ return (access_flags & Constants.ACC_SYNCHRONIZED) != 0;
+ }
+
+
+ public final void isVolatile( boolean flag ) {
+ setFlag(Constants.ACC_VOLATILE, flag);
+ }
+
+
+ public final boolean isVolatile() {
+ return (access_flags & Constants.ACC_VOLATILE) != 0;
+ }
+
+
+ public final void isTransient( boolean flag ) {
+ setFlag(Constants.ACC_TRANSIENT, flag);
+ }
+
+
+ public final boolean isTransient() {
+ return (access_flags & Constants.ACC_TRANSIENT) != 0;
+ }
+
+
+ public final void isNative( boolean flag ) {
+ setFlag(Constants.ACC_NATIVE, flag);
+ }
+
+
+ public final boolean isNative() {
+ return (access_flags & Constants.ACC_NATIVE) != 0;
+ }
+
+
+ public final void isInterface( boolean flag ) {
+ setFlag(Constants.ACC_INTERFACE, flag);
+ }
+
+
+ public final boolean isInterface() {
+ return (access_flags & Constants.ACC_INTERFACE) != 0;
+ }
+
+
+ public final void isAbstract( boolean flag ) {
+ setFlag(Constants.ACC_ABSTRACT, flag);
+ }
+
+
+ public final boolean isAbstract() {
+ return (access_flags & Constants.ACC_ABSTRACT) != 0;
+ }
+
+
+ public final void isStrictfp( boolean flag ) {
+ setFlag(Constants.ACC_STRICT, flag);
+ }
+
+
+ public final boolean isStrictfp() {
+ return (access_flags & Constants.ACC_STRICT) != 0;
+ }
+
+
+ public final void isSynthetic( boolean flag ) {
+ setFlag(Constants.ACC_SYNTHETIC, flag);
+ }
+
+
+ public final boolean isSynthetic() {
+ return (access_flags & Constants.ACC_SYNTHETIC) != 0;
+ }
+
+
+ public final void isAnnotation( boolean flag ) {
+ setFlag(Constants.ACC_ANNOTATION, flag);
+ }
+
+
+ public final boolean isAnnotation() {
+ return (access_flags & Constants.ACC_ANNOTATION) != 0;
+ }
+
+
+ public final void isEnum( boolean flag ) {
+ setFlag(Constants.ACC_ENUM, flag);
+ }
+
+
+ public final boolean isEnum() {
+ return (access_flags & Constants.ACC_ENUM) != 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents the default value of a annotation for a method info
+ *
+ * @version $Id: AnnotationDefault 1 2005-02-13 03:15:08Z dbrosius $
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class AnnotationDefault extends Attribute
+{
+ ElementValue default_value;
+
+ /**
+ * @param annotation_type
+ * the subclass type of the annotation
+ * @param name_index
+ * Index pointing to the name <em>Code</em>
+ * @param length
+ * Content length in bytes
+ * @param file
+ * Input stream
+ * @param constant_pool
+ * Array of constants
+ */
+ public AnnotationDefault(int name_index, int length,
+ DataInputStream file, ConstantPool constant_pool)
+ throws IOException
+ {
+ this(name_index, length, (ElementValue) null,
+ constant_pool);
+ default_value = ElementValue.readElementValue(file, constant_pool);
+ }
+
+ /**
+ * @param annotation_type
+ * the subclass type of the annotation
+ * @param name_index
+ * Index pointing to the name <em>Code</em>
+ * @param length
+ * Content length in bytes
+ * @param defaultValue
+ * the annotation's default value
+ * @param constant_pool
+ * Array of constants
+ */
+ public AnnotationDefault(int name_index, int length,
+ ElementValue defaultValue, ConstantPool constant_pool)
+ {
+ super(Constants.ATTR_ANNOTATION_DEFAULT, name_index, length, constant_pool);
+ setDefaultValue(defaultValue);
+ }
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v
+ * Visitor object
+ */
+ public void accept(Visitor v)
+ {
+ // v.visitAnnotationDefault(this);
+ }
+
+ /**
+ * @param defaultValue
+ * the default value of this methodinfo's annotation
+ */
+ public final void setDefaultValue(ElementValue defaultValue)
+ {
+ default_value = defaultValue;
+ }
+
+ /**
+ * @return the default value
+ */
+ public final ElementValue getDefaultValue()
+ {
+ return default_value;
+ }
+
+ public Attribute copy(ConstantPool _constant_pool)
+ {
+ throw new RuntimeException("Not implemented yet!");
+ }
+
+ public final void dump(DataOutputStream dos) throws IOException
+ {
+ super.dump(dos);
+ default_value.dump(dos);
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class AnnotationElementValue extends ElementValue
+{
+ // For annotation element values, this is the annotation
+ private AnnotationEntry annotationEntry;
+
+ public AnnotationElementValue(int type, AnnotationEntry annotationEntry,
+ ConstantPool cpool)
+ {
+ super(type, cpool);
+ if (type != ANNOTATION)
+ throw new RuntimeException(
+ "Only element values of type annotation can be built with this ctor - type specified: " + type);
+ this.annotationEntry = annotationEntry;
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ANNOTATION == '@')
+ annotationEntry.dump(dos);
+ }
+
+ public String stringifyValue()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(annotationEntry.toString());
+ return sb.toString();
+ }
+
+ public String toString()
+ {
+ return stringifyValue();
+ }
+
+ public AnnotationEntry getAnnotationEntry()
+ {
+ return annotationEntry;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents one annotation in the annotation table
+ *
+ * @version $Id: AnnotationEntry
+ * @author <A HREF="mailto:dbrosius@mebigfatguy.com">D. Brosius</A>
+ * @since 5.3
+ */
+public class AnnotationEntry implements Node, Constants, Serializable {
+
+ private int type_index;
+ private int num_element_value_pairs;
+ private List element_value_pairs;
+ private ConstantPool constant_pool;
+ private boolean isRuntimeVisible;
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ */
+ public AnnotationEntry(int type_index, ConstantPool constant_pool, boolean isRuntimeVisible) {
+ this.type_index = type_index;
+
+ this.constant_pool = constant_pool;
+ this.isRuntimeVisible = isRuntimeVisible;
+ }
+
+ public static AnnotationEntry read(DataInputStream file, ConstantPool constant_pool, boolean isRuntimeVisible) throws IOException
+ {
+ AnnotationEntry annotationEntry = new AnnotationEntry(file.readUnsignedShort(), constant_pool, isRuntimeVisible);
+ annotationEntry.num_element_value_pairs = (file.readUnsignedShort());
+ annotationEntry.element_value_pairs = new ArrayList();
+ for (int i = 0; i < annotationEntry.num_element_value_pairs; i++) {
+ annotationEntry.element_value_pairs.add(new ElementValuePair(file.readUnsignedShort(), ElementValue.readElementValue(file, constant_pool), constant_pool));
+ }
+ return annotationEntry;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ // v.visitAnnotationEntry(this);
+ }
+
+
+ /**
+ * @return the annotation type name
+ */
+ public String getAnnotationType() {
+ ConstantUtf8 c;
+ c = (ConstantUtf8) constant_pool.getConstant(type_index, CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ /**
+ * @return the annotation type index
+ */
+ public int getAnnotationTypeIndex()
+ {
+ return type_index;
+ }
+
+
+ /**
+ * @return the number of element value pairs in this annotation entry
+ */
+ public final int getNumElementValuePairs() {
+ return num_element_value_pairs;
+ }
+
+
+ /**
+ * @return the element value pairs in this annotation entry
+ */
+ public ElementValuePair[] getElementValuePairs() {
+ // TOFO return List
+ return (ElementValuePair[]) element_value_pairs.toArray(new ElementValuePair[element_value_pairs.size()]);
+ }
+
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeShort(type_index); // u2 index of type name in cpool
+ dos.writeShort(element_value_pairs.size()); // u2 element_value pair count
+ for (int i = 0 ; i<element_value_pairs.size();i++) {
+ ElementValuePair envp = (ElementValuePair) element_value_pairs.get(i);
+ envp.dump(dos);
+ }
+ }
+
+
+ public boolean isRuntimeVisible()
+ {
+ return isRuntimeVisible;
+ }
+
+ public void addElementNameValuePair(ElementValuePair elementNameValuePair)
+ {
+ element_value_pairs.add(elementNameValuePair);
+ }
+
+ public String toShortString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append("@");
+ result.append(getAnnotationType());
+ if (getElementValuePairs().length > 0)
+ {
+ result.append("(");
+ for (int i = 0; i < getElementValuePairs().length; i++)
+ {
+ ElementValuePair element = getElementValuePairs()[i];
+ result.append(element.toShortString());
+ }
+ result.append(")");
+ }
+ return result.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * base class for annotations
+ *
+ * @version $Id: Annotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public abstract class Annotations extends Attribute {
+
+ private int annotation_table_length;
+ private AnnotationEntry[] annotation_table; // Table of annotations
+ private boolean isRuntimeVisible;
+
+
+ /**
+ * @param annotation_type the subclass type of the annotation
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ */
+ public Annotations(byte annotation_type, int name_index, int length, DataInputStream file,
+ ConstantPool constant_pool, boolean isRuntimeVisible) throws IOException {
+ this(annotation_type, name_index, length, (AnnotationEntry[]) null, constant_pool, isRuntimeVisible);
+ annotation_table_length = (file.readUnsignedShort());
+ annotation_table = new AnnotationEntry[annotation_table_length];
+ for (int i = 0; i < annotation_table_length; i++) {
+ annotation_table[i] = AnnotationEntry.read(file, constant_pool, isRuntimeVisible);
+ }
+ }
+
+
+ /**
+ * @param annotation_type the subclass type of the annotation
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param annotation_table the actual annotations
+ * @param constant_pool Array of constants
+ */
+ public Annotations(byte annotation_type, int name_index, int length,
+ AnnotationEntry[] annotation_table, ConstantPool constant_pool , boolean isRuntimeVisible) {
+ super(annotation_type, name_index, length, constant_pool);
+ setAnnotationTable(annotation_table);
+ this.isRuntimeVisible = isRuntimeVisible;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitAnnotation(this);
+ }
+
+
+ /**
+ * @param annotation_table the entries to set in this annotation
+ */
+ public final void setAnnotationTable( AnnotationEntry[] annotation_table ) {
+ this.annotation_table = annotation_table;
+ annotation_table_length = (annotation_table == null) ? 0 : annotation_table.length;
+ }
+
+
+ // TODO: update method names
+ /**
+ * @return the annotation entry table
+ */
+ /*
+ public final AnnotationEntry[] getAnnotationTable() {
+ return annotation_table;
+ }*/
+
+
+ /**
+ * returns the array of annotation entries in this annotation
+ */
+ public AnnotationEntry[] getAnnotationEntries() {
+ return annotation_table;
+ }
+
+
+ /**
+ * @return the number of annotation entries in this annotation
+ */
+ public final int getNumAnnotations() {
+ return annotation_table_length;
+ }
+
+ public boolean isRuntimeVisible()
+ {
+ return isRuntimeVisible;
+ }
+
+ protected void writeAnnotations(DataOutputStream dos) throws IOException
+ {
+ dos.writeShort(annotation_table_length);
+ for (int i = 0; i < annotation_table_length; i++)
+ annotation_table[i].dump(dos);
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class ArrayElementValue extends ElementValue
+{
+ // For array types, this is the array
+ private ElementValue[] evalues;
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("{");
+ for (int i = 0; i < evalues.length; i++)
+ {
+ sb.append(evalues[i].toString());
+ if ((i + 1) < evalues.length)
+ sb.append(",");
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ public ArrayElementValue(int type, ElementValue[] datums, ConstantPool cpool)
+ {
+ super(type, cpool);
+ if (type != ARRAY)
+ throw new RuntimeException(
+ "Only element values of type array can be built with this ctor - type specified: " + type);
+ this.evalues = datums;
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ARRAY == '[')
+ dos.writeShort(evalues.length);
+ for (int i = 0; i < evalues.length; i++)
+ {
+ evalues[i].dump(dos);
+ }
+ }
+
+ public String stringifyValue()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[");
+ for (int i = 0; i < evalues.length; i++)
+ {
+ sb.append(evalues[i].stringifyValue());
+ if ((i + 1) < evalues.length)
+ sb.append(",");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public ElementValue[] getElementValuesArray()
+ {
+ return evalues;
+ }
+
+ public int getElementValuesArraySize()
+ {
+ return evalues.length;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+
+/**
+ * Abstract super class for <em>Attribute</em> objects. Currently the
+ * <em>ConstantValue</em>, <em>SourceFile</em>, <em>Code</em>,
+ * <em>Exceptiontable</em>, <em>LineNumberTable</em>,
+ * <em>LocalVariableTable</em>, <em>InnerClasses</em> and
+ * <em>Synthetic</em> attributes are supported. The <em>Unknown</em>
+ * attribute stands for non-standard-attributes.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see ConstantValue
+ * @see SourceFile
+ * @see Code
+ * @see Unknown
+ * @see ExceptionTable
+ * @see LineNumberTable
+ * @see LocalVariableTable
+ * @see InnerClasses
+ * @see Synthetic
+ * @see Deprecated
+ * @see Signature
+ */
+public abstract class Attribute implements Cloneable, Node, Serializable
+{
+ protected int name_index; // Points to attribute name in constant pool
+
+ protected int length; // Content length of attribute field
+
+ protected byte tag; // Tag to distiguish subclasses
+
+ protected ConstantPool constant_pool;
+
+ protected Attribute(byte tag, int name_index, int length,
+ ConstantPool constant_pool)
+ {
+ this.tag = tag;
+ this.name_index = name_index;
+ this.length = length;
+ this.constant_pool = constant_pool;
+ }
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v
+ * Visitor object
+ */
+ public abstract void accept(Visitor v);
+
+ /**
+ * Dump attribute to file stream in binary format.
+ *
+ * @param file
+ * Output file stream
+ * @throws IOException
+ */
+ public void dump(DataOutputStream file) throws IOException
+ {
+ file.writeShort(name_index);
+ file.writeInt(length);
+ }
+
+ private static Map readers = new HashMap();
+
+ /**
+ * Add an Attribute reader capable of parsing (user-defined) attributes
+ * named "name". You should not add readers for the standard attributes such
+ * as "LineNumberTable", because those are handled internally.
+ *
+ * @param name
+ * the name of the attribute as stored in the class file
+ * @param r
+ * the reader object
+ */
+ public static void addAttributeReader(String name, AttributeReader r)
+ {
+ readers.put(name, r);
+ }
+
+ /**
+ * Remove attribute reader
+ *
+ * @param name
+ * the name of the attribute as stored in the class file
+ */
+ public static void removeAttributeReader(String name)
+ {
+ readers.remove(name);
+ }
+
+ /*
+ * Class method reads one attribute from the input data stream. This method
+ * must not be accessible from the outside. It is called by the Field and
+ * Method constructor methods.
+ *
+ * @see Field
+ * @see Method @param file Input stream @param constant_pool Array of
+ * constants @return Attribute @throws IOException @throws
+ * ClassFormatException
+ */
+ public static final Attribute readAttribute(DataInputStream file,
+ ConstantPool constant_pool) throws IOException,
+ ClassFormatException
+ {
+ ConstantUtf8 c;
+ String name;
+ int name_index;
+ int length;
+ byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute
+ // Get class name from constant pool via `name_index' indirection
+ name_index = file.readUnsignedShort();
+ c = (ConstantUtf8) constant_pool.getConstant(name_index,
+ Constants.CONSTANT_Utf8);
+ name = c.getBytes();
+ // Length of data in bytes
+ length = file.readInt();
+ // Compare strings to find known attribute
+ // System.out.println(name);
+ for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++)
+ {
+ if (name.equals(Constants.ATTRIBUTE_NAMES[i]))
+ {
+ tag = i; // found!
+ break;
+ }
+ }
+ // Call proper constructor, depending on `tag'
+ switch (tag)
+ {
+ case Constants.ATTR_UNKNOWN:
+ AttributeReader r = (AttributeReader) readers.get(name);
+ if (r != null)
+ {
+ return r.createAttribute(name_index, length, file,
+ constant_pool);
+ }
+ return new Unknown(name_index, length, file, constant_pool);
+ case Constants.ATTR_CONSTANT_VALUE:
+ return new ConstantValue(name_index, length, file, constant_pool);
+ case Constants.ATTR_SOURCE_FILE:
+ return new SourceFile(name_index, length, file, constant_pool);
+ case Constants.ATTR_CODE:
+ return new Code(name_index, length, file, constant_pool);
+ case Constants.ATTR_EXCEPTIONS:
+ return new ExceptionTable(name_index, length, file, constant_pool);
+ case Constants.ATTR_LINE_NUMBER_TABLE:
+ return new LineNumberTable(name_index, length, file, constant_pool);
+ case Constants.ATTR_LOCAL_VARIABLE_TABLE:
+ return new LocalVariableTable(name_index, length, file,
+ constant_pool);
+ case Constants.ATTR_INNER_CLASSES:
+ return new InnerClasses(name_index, length, file, constant_pool);
+ case Constants.ATTR_SYNTHETIC:
+ return new Synthetic(name_index, length, file, constant_pool);
+ case Constants.ATTR_DEPRECATED:
+ return new Deprecated(name_index, length, file, constant_pool);
+ case Constants.ATTR_PMG:
+ return new PMGClass(name_index, length, file, constant_pool);
+ case Constants.ATTR_SIGNATURE:
+ return new Signature(name_index, length, file, constant_pool);
+ case Constants.ATTR_STACK_MAP:
+ return new StackMap(name_index, length, file, constant_pool);
+ case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
+ return new RuntimeVisibleAnnotations(name_index, length, file,
+ constant_pool);
+ case Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS:
+ return new RuntimeInvisibleAnnotations(name_index, length, file,
+ constant_pool);
+ case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
+ return new RuntimeVisibleParameterAnnotations(name_index, length,
+ file, constant_pool);
+ case Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS:
+ return new RuntimeInvisibleParameterAnnotations(name_index, length,
+ file, constant_pool);
+ case Constants.ATTR_ANNOTATION_DEFAULT:
+ return new AnnotationDefault(name_index, length, file,
+ constant_pool);
+ case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
+ return new LocalVariableTypeTable(name_index, length, file,
+ constant_pool);
+ case Constants.ATTR_ENCLOSING_METHOD:
+ return new EnclosingMethod(name_index, length, file, constant_pool);
+ case Constants.ATTR_STACK_MAP_TABLE:
+ return new StackMapTable(name_index, length, file, constant_pool);
+ default: // Never reached
+ throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
+ }
+ }
+
+ /**
+ * @return Name of attribute
+ */
+ public String getName()
+ {
+ ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ /**
+ * @return Length of attribute field in bytes.
+ */
+ public final int getLength()
+ {
+ return length;
+ }
+
+ /**
+ * @param length
+ * length in bytes.
+ */
+ public final void setLength(int length)
+ {
+ this.length = length;
+ }
+
+ /**
+ * @param name_index
+ * of attribute.
+ */
+ public final void setNameIndex(int name_index)
+ {
+ this.name_index = name_index;
+ }
+
+ /**
+ * @return Name index in constant pool of attribute name.
+ */
+ public final int getNameIndex()
+ {
+ return name_index;
+ }
+
+ /**
+ * @return Tag of attribute, i.e., its type. Value may not be altered, thus
+ * there is no setTag() method.
+ */
+ public final byte getTag()
+ {
+ return tag;
+ }
+
+ /**
+ * @return Constant pool used by this object.
+ * @see ConstantPool
+ */
+ public final ConstantPool getConstantPool()
+ {
+ return constant_pool;
+ }
+
+ /**
+ * @param constant_pool
+ * Constant pool to be used for this object.
+ * @see ConstantPool
+ */
+ public final void setConstantPool(ConstantPool constant_pool)
+ {
+ this.constant_pool = constant_pool;
+ }
+
+ /**
+ * Use copy() if you want to have a deep copy(), i.e., with all references
+ * copied correctly.
+ *
+ * @return shallow copy of this attribute
+ */
+ public Object clone()
+ {
+ Object o = null;
+ try
+ {
+ o = super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ e.printStackTrace(); // Never occurs
+ }
+ return o;
+ }
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public abstract Attribute copy(ConstantPool _constant_pool);
+
+ /**
+ * @return attribute name.
+ */
+ public String toString()
+ {
+ return Constants.ATTRIBUTE_NAMES[tag];
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * Unknown (non-standard) attributes may be read via user-defined factory
+ * objects that can be registered with the Attribute.addAttributeReader
+ * method. These factory objects should implement this interface.
+
+ * @see Attribute
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface AttributeReader {
+
+ /**
+ When this attribute reader is added via the static method
+ Attribute.addAttributeReader, an attribute name is associated with it.
+ As the class file parser parses attributes, it will call various
+ AttributeReaders based on the name of the attributes it is
+ constructing.
+
+ @param name_index An index into the constant pool, indexing a
+ ConstantUtf8 that represents the name of the attribute.
+
+ @param length The length of the data contained in the attribute. This
+ is written into the constant pool and should agree with what the
+ factory expects the length to be.
+
+ @param file This is the data input stream that the factory needs to read
+ its data from.
+
+ @param constant_pool This is the constant pool associated with the
+ Attribute that we are constructing.
+
+ @return The user-defined AttributeReader should take this data and use
+ it to construct an attribute. In the case of errors, a null can be
+ returned which will cause the parsing of the class file to fail.
+
+ @see Attribute#addAttributeReader( String, AttributeReader )
+ */
+ public Attribute createAttribute( int name_index, int length, java.io.DataInputStream file,
+ ConstantPool constant_pool );
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+public class ClassElementValue extends ElementValue
+{
+ // For primitive types and string type, this points to the value entry in
+ // the cpool
+ // For 'class' this points to the class entry in the cpool
+ private int idx;
+
+ public ClassElementValue(int type, int idx, ConstantPool cpool)
+ {
+ super(type, cpool);
+ this.idx = idx;
+ }
+
+ public int getIndex()
+ {
+ return idx;
+ }
+
+ public String getClassString()
+ {
+ ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(idx,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ public String stringifyValue()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(idx,
+ Constants.CONSTANT_Utf8);
+ return cu8.getBytes();
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 kind of value
+ dos.writeShort(idx);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * Thrown when the BCEL attempts to read a class file and determines
+ * that the file is malformed or otherwise cannot be interpreted as a
+ * class file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ClassFormatException extends RuntimeException {
+
+ public ClassFormatException() {
+ super();
+ }
+
+
+ public ClassFormatException(String s) {
+ super(s);
+ }
+
+ public ClassFormatException(String s, Throwable initCause) {
+ super(s, initCause);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Wrapper class that parses a given Java .class file. The method <A
+ * href ="#parse">parse</A> returns a <A href ="JavaClass.html">
+ * JavaClass</A> object on success. When an I/O error or an
+ * inconsistency occurs an appropiate exception is propagated back to
+ * the caller.
+ *
+ * The structure and the names comply, except for a few conveniences,
+ * exactly with the <A href="ftp://java.sun.com/docs/specs/vmspec.ps">
+ * JVM specification 1.0</a>. See this paper for
+ * further details about the structure of a bytecode file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ClassParser {
+
+ private DataInputStream file;
+ private boolean fileOwned;
+ private String file_name;
+ private String zip_file;
+ private int class_name_index, superclass_name_index;
+ private int major, minor; // Compiler version
+ private int access_flags; // Access rights of parsed class
+ private int[] interfaces; // Names of implemented interfaces
+ private ConstantPool constant_pool; // collection of constants
+ private Field[] fields; // class fields, i.e., its variables
+ private Method[] methods; // methods defined in the class
+ private Attribute[] attributes; // attributes defined in the class
+ private boolean is_zip; // Loaded from zip file
+ private static final int BUFSIZE = 8192;
+
+
+ /**
+ * Parse class from the given stream.
+ *
+ * @param file Input stream
+ * @param file_name File name
+ */
+ public ClassParser(InputStream file, String file_name) {
+ this.file_name = file_name;
+ fileOwned = false;
+ String clazz = file.getClass().getName(); // Not a very clean solution ...
+ is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar.");
+ if (file instanceof DataInputStream) {
+ this.file = (DataInputStream) file;
+ } else {
+ this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE));
+ }
+ }
+
+
+ /** Parse class from given .class file.
+ *
+ * @param file_name file name
+ */
+ public ClassParser(String file_name) {
+ is_zip = false;
+ this.file_name = file_name;
+ fileOwned = true;
+ }
+
+
+ /** Parse class from given .class file in a ZIP-archive
+ *
+ * @param zip_file zip file name
+ * @param file_name file name
+ */
+ public ClassParser(String zip_file, String file_name) {
+ is_zip = true;
+ fileOwned = true;
+ this.zip_file = zip_file;
+ this.file_name = file_name;
+ }
+
+
+ /**
+ * Parse the given Java class file and return an object that represents
+ * the contained data, i.e., constants, methods, fields and commands.
+ * A <em>ClassFormatException</em> is raised, if the file is not a valid
+ * .class file. (This does not include verification of the byte code as it
+ * is performed by the java interpreter).
+ *
+ * @return Class object representing the parsed class file
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ public JavaClass parse() throws IOException, ClassFormatException {
+ ZipFile zip = null;
+ try {
+ if (fileOwned) {
+ if (is_zip) {
+ zip = new ZipFile(zip_file);
+ ZipEntry entry = zip.getEntry(file_name);
+ file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry),
+ BUFSIZE));
+ } else {
+ file = new DataInputStream(new BufferedInputStream(new FileInputStream(
+ file_name), BUFSIZE));
+ }
+ }
+ /****************** Read headers ********************************/
+ // Check magic tag of class file
+ readID();
+ // Get compiler version
+ readVersion();
+ /****************** Read constant pool and related **************/
+ // Read constant pool entries
+ readConstantPool();
+ // Get class information
+ readClassInfo();
+ // Get interface information, i.e., implemented interfaces
+ readInterfaces();
+ /****************** Read class fields and methods ***************/
+ // Read class fields, i.e., the variables of the class
+ readFields();
+ // Read class methods, i.e., the functions in the class
+ readMethods();
+ // Read class attributes
+ readAttributes();
+ // Check for unknown variables
+ //Unknown[] u = Unknown.getUnknownAttributes();
+ //for(int i=0; i < u.length; i++)
+ // System.err.println("WARNING: " + u[i]);
+ // Everything should have been read now
+ // if(file.available() > 0) {
+ // int bytes = file.available();
+ // byte[] buf = new byte[bytes];
+ // file.read(buf);
+ // if(!(is_zip && (buf.length == 1))) {
+ // System.err.println("WARNING: Trailing garbage at end of " + file_name);
+ // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
+ // }
+ // }
+ } finally {
+ // Read everything of interest, so close the file
+ if (fileOwned) {
+ try {
+ if (file != null) {
+ file.close();
+ }
+ if (zip != null) {
+ zip.close();
+ }
+ } catch (IOException ioe) {
+ //ignore close exceptions
+ }
+ }
+ }
+ // Return the information we have gathered in a new object
+ return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
+ access_flags, constant_pool, interfaces, fields, methods, attributes, is_zip
+ ? JavaClass.ZIP
+ : JavaClass.FILE);
+ }
+
+
+ /**
+ * Read information about the attributes of the class.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readAttributes() throws IOException, ClassFormatException {
+ int attributes_count;
+ attributes_count = file.readUnsignedShort();
+ attributes = new Attribute[attributes_count];
+ for (int i = 0; i < attributes_count; i++) {
+ attributes[i] = Attribute.readAttribute(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * Read information about the class and its super class.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readClassInfo() throws IOException, ClassFormatException {
+ access_flags = file.readUnsignedShort();
+ /* Interfaces are implicitely abstract, the flag should be set
+ * according to the JVM specification.
+ */
+ if ((access_flags & Constants.ACC_INTERFACE) != 0) {
+ access_flags |= Constants.ACC_ABSTRACT;
+ }
+ if (((access_flags & Constants.ACC_ABSTRACT) != 0)
+ && ((access_flags & Constants.ACC_FINAL) != 0)) {
+ throw new ClassFormatException("Class " + file_name + " can't be both final and abstract");
+ }
+ class_name_index = file.readUnsignedShort();
+ superclass_name_index = file.readUnsignedShort();
+ }
+
+
+ /**
+ * Read constant pool entries.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readConstantPool() throws IOException, ClassFormatException {
+ constant_pool = new ConstantPool(file);
+ }
+
+
+ /**
+ * Read information about the fields of the class, i.e., its variables.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readFields() throws IOException, ClassFormatException {
+ int fields_count;
+ fields_count = file.readUnsignedShort();
+ fields = new Field[fields_count];
+ for (int i = 0; i < fields_count; i++) {
+ fields[i] = new Field(file, constant_pool);
+ }
+ }
+
+
+ /******************** Private utility methods **********************/
+ /**
+ * Check whether the header of the file is ok.
+ * Of course, this has to be the first action on successive file reads.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readID() throws IOException, ClassFormatException {
+ int magic = 0xCAFEBABE;
+ if (file.readInt() != magic) {
+ throw new ClassFormatException(file_name + " is not a Java .class file");
+ }
+ }
+
+
+ /**
+ * Read information about the interfaces implemented by this class.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readInterfaces() throws IOException, ClassFormatException {
+ int interfaces_count;
+ interfaces_count = file.readUnsignedShort();
+ interfaces = new int[interfaces_count];
+ for (int i = 0; i < interfaces_count; i++) {
+ interfaces[i] = file.readUnsignedShort();
+ }
+ }
+
+
+ /**
+ * Read information about the methods of the class.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readMethods() throws IOException, ClassFormatException {
+ int methods_count;
+ methods_count = file.readUnsignedShort();
+ methods = new Method[methods_count];
+ for (int i = 0; i < methods_count; i++) {
+ methods[i] = new Method(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * Read major and minor version of compiler which created the file.
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ private final void readVersion() throws IOException, ClassFormatException {
+ minor = file.readUnsignedShort();
+ major = file.readUnsignedShort();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a chunk of Java byte code contained in a
+ * method. It is instantiated by the
+ * <em>Attribute.readAttribute()</em> method. A <em>Code</em>
+ * attribute contains informations about operand stack, local
+ * variables, byte code and the exceptions handled within this
+ * method.
+ *
+ * This attribute has attributes itself, namely <em>LineNumberTable</em> which
+ * is used for debugging purposes and <em>LocalVariableTable</em> which
+ * contains information about the local variables.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ * @see CodeException
+ * @see LineNumberTable
+ * @see LocalVariableTable
+ */
+public final class Code extends Attribute {
+
+ private int max_stack; // Maximum size of stack used by this method
+ private int max_locals; // Number of local variables
+ private int code_length; // Length of code in bytes
+ private byte[] code; // Actual byte code
+ private int exception_table_length;
+ private CodeException[] exception_table; // Table of handled exceptions
+ private int attributes_count; // Attributes of code: LineNumber
+ private Attribute[] attributes; // or LocalVariable
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public Code(Code c) {
+ this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c
+ .getExceptionTable(), c.getAttributes(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ */
+ Code(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ // Initialize with some default values which will be overwritten later
+ this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null,
+ (CodeException[]) null, (Attribute[]) null, constant_pool);
+ code_length = file.readInt();
+ code = new byte[code_length]; // Read byte code
+ file.readFully(code);
+ /* Read exception table that contains all regions where an exception
+ * handler is active, i.e., a try { ... } catch() block.
+ */
+ exception_table_length = file.readUnsignedShort();
+ exception_table = new CodeException[exception_table_length];
+ for (int i = 0; i < exception_table_length; i++) {
+ exception_table[i] = new CodeException(file);
+ }
+ /* Read all attributes, currently `LineNumberTable' and
+ * `LocalVariableTable'
+ */
+ attributes_count = file.readUnsignedShort();
+ attributes = new Attribute[attributes_count];
+ for (int i = 0; i < attributes_count; i++) {
+ attributes[i] = Attribute.readAttribute(file, constant_pool);
+ }
+ /* Adjust length, because of setAttributes in this(), s.b. length
+ * is incorrect, because it didn't take the internal attributes
+ * into account yet! Very subtle bug, fixed in 3.1.1.
+ */
+ this.length = length;
+ }
+
+
+ /**
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param max_stack Maximum size of stack
+ * @param max_locals Number of local variables
+ * @param code Actual byte code
+ * @param exception_table Table of handled exceptions
+ * @param attributes Attributes of code: LineNumber or LocalVariable
+ * @param constant_pool Array of constants
+ */
+ public Code(int name_index, int length, int max_stack, int max_locals, byte[] code,
+ CodeException[] exception_table, Attribute[] attributes, ConstantPool constant_pool) {
+ super(Constants.ATTR_CODE, name_index, length, constant_pool);
+ this.max_stack = max_stack;
+ this.max_locals = max_locals;
+ setCode(code);
+ setExceptionTable(exception_table);
+ setAttributes(attributes); // Overwrites length!
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitCode(this);
+ }
+
+
+ /**
+ * Dump code attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(max_stack);
+ file.writeShort(max_locals);
+ file.writeInt(code_length);
+ file.write(code, 0, code_length);
+ file.writeShort(exception_table_length);
+ for (int i = 0; i < exception_table_length; i++) {
+ exception_table[i].dump(file);
+ }
+ file.writeShort(attributes_count);
+ for (int i = 0; i < attributes_count; i++) {
+ attributes[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Collection of code attributes.
+ * @see Attribute
+ */
+ public final Attribute[] getAttributes() {
+ return attributes;
+ }
+
+
+ /**
+ * @return LineNumberTable of Code, if it has one
+ */
+ public LineNumberTable getLineNumberTable() {
+ for (int i = 0; i < attributes_count; i++) {
+ if (attributes[i] instanceof LineNumberTable) {
+ return (LineNumberTable) attributes[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @return LocalVariableTable of Code, if it has one
+ */
+ public LocalVariableTable getLocalVariableTable() {
+ for (int i = 0; i < attributes_count; i++) {
+ if (attributes[i] instanceof LocalVariableTable) {
+ return (LocalVariableTable) attributes[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @return Actual byte code of the method.
+ */
+ public final byte[] getCode() {
+ return code;
+ }
+
+
+ /**
+ * @return Table of handled exceptions.
+ * @see CodeException
+ */
+ public final CodeException[] getExceptionTable() {
+ return exception_table;
+ }
+
+
+ /**
+ * @return Number of local variables.
+ */
+ public final int getMaxLocals() {
+ return max_locals;
+ }
+
+
+ /**
+ * @return Maximum size of stack used by this method.
+ */
+ public final int getMaxStack() {
+ return max_stack;
+ }
+
+
+ /**
+ * @return the internal length of this code attribute (minus the first 6 bytes)
+ * and excluding all its attributes
+ */
+ private final int getInternalLength() {
+ return 2 /*max_stack*/+ 2 /*max_locals*/+ 4 /*code length*/
+ + code_length /*byte-code*/
+ + 2 /*exception-table length*/
+ + 8 * exception_table_length /* exception table */
+ + 2 /* attributes count */;
+ }
+
+
+ /**
+ * @return the full size of this code attribute, minus its first 6 bytes,
+ * including the size of all its contained attributes
+ */
+ private final int calculateLength() {
+ int len = 0;
+ for (int i = 0; i < attributes_count; i++) {
+ len += attributes[i].length + 6 /*attribute header size*/;
+ }
+ return len + getInternalLength();
+ }
+
+
+ /**
+ * @param attributes the attributes to set for this Code
+ */
+ public final void setAttributes( Attribute[] attributes ) {
+ this.attributes = attributes;
+ attributes_count = (attributes == null) ? 0 : attributes.length;
+ length = calculateLength(); // Adjust length
+ }
+
+
+ /**
+ * @param code byte code
+ */
+ public final void setCode( byte[] code ) {
+ this.code = code;
+ code_length = (code == null) ? 0 : code.length;
+ }
+
+
+ /**
+ * @param exception_table exception table
+ */
+ public final void setExceptionTable( CodeException[] exception_table ) {
+ this.exception_table = exception_table;
+ exception_table_length = (exception_table == null) ? 0 : exception_table.length;
+ }
+
+
+ /**
+ * @param max_locals maximum number of local variables
+ */
+ public final void setMaxLocals( int max_locals ) {
+ this.max_locals = max_locals;
+ }
+
+
+ /**
+ * @param max_stack maximum stack size
+ */
+ public final void setMaxStack( int max_stack ) {
+ this.max_stack = max_stack;
+ }
+
+
+ /**
+ * @return String representation of code chunk.
+ */
+ public final String toString( boolean verbose ) {
+ StringBuffer buf;
+ buf = new StringBuffer(100);
+ buf.append("Code(max_stack = ").append(max_stack).append(", max_locals = ").append(
+ max_locals).append(", code_length = ").append(code_length).append(")\n").append(
+ Utility.codeToString(code, constant_pool, 0, -1, verbose));
+ if (exception_table_length > 0) {
+ buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
+ for (int i = 0; i < exception_table_length; i++) {
+ buf.append(exception_table[i].toString(constant_pool, verbose)).append("\n");
+ }
+ }
+ if (attributes_count > 0) {
+ buf.append("\nAttribute(s) = \n");
+ for (int i = 0; i < attributes_count; i++) {
+ buf.append(attributes[i].toString()).append("\n");
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return String representation of code chunk.
+ */
+ public final String toString() {
+ return toString(true);
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ *
+ * @param _constant_pool the constant pool to duplicate
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ Code c = (Code) clone();
+ if (code != null) {
+ c.code = new byte[code.length];
+ System.arraycopy(code, 0, c.code, 0, code.length);
+ }
+ c.constant_pool = _constant_pool;
+ c.exception_table = new CodeException[exception_table_length];
+ for (int i = 0; i < exception_table_length; i++) {
+ c.exception_table[i] = exception_table[i].copy();
+ }
+ c.attributes = new Attribute[attributes_count];
+ for (int i = 0; i < attributes_count; i++) {
+ c.attributes[i] = attributes[i].copy(_constant_pool);
+ }
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents an entry in the exception table of the <em>Code</em>
+ * attribute and is used only there. It contains a range in which a
+ * particular exception handler is active.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ */
+public final class CodeException implements Cloneable, Constants, Node, Serializable {
+
+ private int start_pc; // Range in the code the exception handler is
+ private int end_pc; // active. start_pc is inclusive, end_pc exclusive
+ private int handler_pc; /* Starting address of exception handler, i.e.,
+ * an offset from start of code.
+ */
+ private int catch_type; /* If this is zero the handler catches any
+ * exception, otherwise it points to the
+ * exception class which is to be caught.
+ */
+
+
+ /**
+ * Initialize from another object.
+ */
+ public CodeException(CodeException c) {
+ this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ CodeException(DataInput file) throws IOException {
+ this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
+ .readUnsignedShort());
+ }
+
+
+ /**
+ * @param start_pc Range in the code the exception handler is active,
+ * start_pc is inclusive while
+ * @param end_pc is exclusive
+ * @param handler_pc Starting address of exception handler, i.e.,
+ * an offset from start of code.
+ * @param catch_type If zero the handler catches any
+ * exception, otherwise it points to the exception class which is
+ * to be caught.
+ */
+ public CodeException(int start_pc, int end_pc, int handler_pc, int catch_type) {
+ this.start_pc = start_pc;
+ this.end_pc = end_pc;
+ this.handler_pc = handler_pc;
+ this.catch_type = catch_type;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitCodeException(this);
+ }
+
+
+ /**
+ * Dump code exception to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(start_pc);
+ file.writeShort(end_pc);
+ file.writeShort(handler_pc);
+ file.writeShort(catch_type);
+ }
+
+
+ /**
+ * @return 0, if the handler catches any exception, otherwise it points to
+ * the exception class which is to be caught.
+ */
+ public final int getCatchType() {
+ return catch_type;
+ }
+
+
+ /**
+ * @return Exclusive end index of the region where the handler is active.
+ */
+ public final int getEndPC() {
+ return end_pc;
+ }
+
+
+ /**
+ * @return Starting address of exception handler, relative to the code.
+ */
+ public final int getHandlerPC() {
+ return handler_pc;
+ }
+
+
+ /**
+ * @return Inclusive start index of the region where the handler is active.
+ */
+ public final int getStartPC() {
+ return start_pc;
+ }
+
+
+ /**
+ * @param catch_type the type of exception that is caught
+ */
+ public final void setCatchType( int catch_type ) {
+ this.catch_type = catch_type;
+ }
+
+
+ /**
+ * @param end_pc end of handled block
+ */
+ public final void setEndPC( int end_pc ) {
+ this.end_pc = end_pc;
+ }
+
+
+ /**
+ * @param handler_pc where the actual code is
+ */
+ public final void setHandlerPC( int handler_pc ) {
+ this.handler_pc = handler_pc;
+ }
+
+
+ /**
+ * @param start_pc start of handled block
+ */
+ public final void setStartPC( int start_pc ) {
+ this.start_pc = start_pc;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return "CodeException(start_pc = " + start_pc + ", end_pc = " + end_pc + ", handler_pc = "
+ + handler_pc + ", catch_type = " + catch_type + ")";
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString( ConstantPool cp, boolean verbose ) {
+ String str;
+ if (catch_type == 0) {
+ str = "<Any exception>(0)";
+ } else {
+ str = Utility.compactClassName(cp.getConstantString(catch_type, CONSTANT_Class), false)
+ + (verbose ? "(" + catch_type + ")" : "");
+ }
+ return start_pc + "\t" + end_pc + "\t" + handler_pc + "\t" + str;
+ }
+
+
+ public final String toString( ConstantPool cp ) {
+ return toString(cp, true);
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public CodeException copy() {
+ try {
+ return (CodeException) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * Abstract superclass for classes to represent the different constant types
+ * in the constant pool of a class file. The classes keep closely to
+ * the JVM specification.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class Constant implements Cloneable, Node, Serializable {
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ Constant THIS = (Constant) o1;
+ Constant THAT = (Constant) o2;
+ return THIS.toString().equals(THAT.toString());
+ }
+
+
+ public int hashCode( Object o ) {
+ Constant THIS = (Constant) o;
+ return THIS.toString().hashCode();
+ }
+ };
+ /* In fact this tag is redundant since we can distinguish different
+ * `Constant' objects by their type, i.e., via `instanceof'. In some
+ * places we will use the tag for switch()es anyway.
+ *
+ * First, we want match the specification as closely as possible. Second we
+ * need the tag as an index to select the corresponding class name from the
+ * `CONSTANT_NAMES' array.
+ */
+ protected byte tag;
+
+
+ Constant(byte tag) {
+ this.tag = tag;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public abstract void accept( Visitor v );
+
+
+ public abstract void dump( DataOutputStream file ) throws IOException;
+
+
+ /**
+ * @return Tag of constant, i.e., its type. No setTag() method to avoid
+ * confusion.
+ */
+ public final byte getTag() {
+ return tag;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public String toString() {
+ return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]";
+ }
+
+
+ /**
+ * @return deep copy of this constant
+ */
+ public Constant copy() {
+ try {
+ return (Constant) super.clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+
+
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+
+ /**
+ * Read one constant from the given file, the type depends on a tag byte.
+ *
+ * @param file Input stream
+ * @return Constant object
+ */
+ static final Constant readConstant( DataInputStream file ) throws IOException,
+ ClassFormatException {
+ byte b = file.readByte(); // Read tag byte
+ switch (b) {
+ case Constants.CONSTANT_Class:
+ return new ConstantClass(file);
+ case Constants.CONSTANT_Fieldref:
+ return new ConstantFieldref(file);
+ case Constants.CONSTANT_Methodref:
+ return new ConstantMethodref(file);
+ case Constants.CONSTANT_InterfaceMethodref:
+ return new ConstantInterfaceMethodref(file);
+ case Constants.CONSTANT_String:
+ return new ConstantString(file);
+ case Constants.CONSTANT_Integer:
+ return new ConstantInteger(file);
+ case Constants.CONSTANT_Float:
+ return new ConstantFloat(file);
+ case Constants.CONSTANT_Long:
+ return new ConstantLong(file);
+ case Constants.CONSTANT_Double:
+ return new ConstantDouble(file);
+ case Constants.CONSTANT_NameAndType:
+ return new ConstantNameAndType(file);
+ case Constants.CONSTANT_Utf8:
+ return new ConstantUtf8(file);
+ default:
+ throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
+ }
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two Constant objects are said to be equal when
+ * the result of toString() is equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the result of toString().
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Abstract super class for Fieldref and Methodref constants.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see ConstantFieldref
+ * @see ConstantMethodref
+ * @see ConstantInterfaceMethodref
+ */
+public abstract class ConstantCP extends Constant {
+
+ /** References to the constants containing the class and the field signature
+ */
+ protected int class_index, name_and_type_index;
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantCP(ConstantCP c) {
+ this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param tag Constant type tag
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantCP(byte tag, DataInput file) throws IOException {
+ this(tag, file.readUnsignedShort(), file.readUnsignedShort());
+ }
+
+
+ /**
+ * @param class_index Reference to the class containing the field
+ * @param name_and_type_index and the field signature
+ */
+ protected ConstantCP(byte tag, int class_index, int name_and_type_index) {
+ super(tag);
+ this.class_index = class_index;
+ this.name_and_type_index = name_and_type_index;
+ }
+
+
+ /**
+ * Dump constant field reference to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(class_index);
+ file.writeShort(name_and_type_index);
+ }
+
+
+ /**
+ * @return Reference (index) to class this field or method belongs to.
+ */
+ public final int getClassIndex() {
+ return class_index;
+ }
+
+
+ /**
+ * @return Reference (index) to signature of the field.
+ */
+ public final int getNameAndTypeIndex() {
+ return name_and_type_index;
+ }
+
+
+ /**
+ * @param class_index points to Constant_class
+ */
+ public final void setClassIndex( int class_index ) {
+ this.class_index = class_index;
+ }
+
+
+ /**
+ * @return Class this field belongs to.
+ */
+ public String getClass( ConstantPool cp ) {
+ return cp.constantToString(class_index, Constants.CONSTANT_Class);
+ }
+
+
+ /**
+ * @param name_and_type_index points to Constant_NameAndType
+ */
+ public final void setNameAndTypeIndex( int name_and_type_index ) {
+ this.name_and_type_index = name_and_type_index;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(class_index = " + class_index + ", name_and_type_index = "
+ + name_and_type_index + ")";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a (external) class.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantClass extends Constant implements ConstantObject {
+
+ private int name_index; // Identical to ConstantString except for the name
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantClass(ConstantClass c) {
+ this(c.getNameIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantClass(DataInput file) throws IOException {
+ this(file.readUnsignedShort());
+ }
+
+
+ /**
+ * @param name_index Name index in constant pool. Should refer to a
+ * ConstantUtf8.
+ */
+ public ConstantClass(int name_index) {
+ super(Constants.CONSTANT_Class);
+ this.name_index = name_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantClass(this);
+ }
+
+
+ /**
+ * Dump constant class to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(name_index);
+ }
+
+
+ /**
+ * @return Name index in constant pool of class name.
+ */
+ public final int getNameIndex() {
+ return name_index;
+ }
+
+
+ /**
+ * @param name_index the name index in the constant pool of this Constant Class
+ */
+ public final void setNameIndex( int name_index ) {
+ this.name_index = name_index;
+ }
+
+
+ /** @return String object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ Constant c = cp.getConstant(name_index, Constants.CONSTANT_Utf8);
+ return ((ConstantUtf8) c).getBytes();
+ }
+
+
+ /** @return dereferenced string
+ */
+ public String getBytes( ConstantPool cp ) {
+ return (String) getConstantValue(cp);
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(name_index = " + name_index + ")";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a Double object.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantDouble extends Constant implements ConstantObject {
+
+ private double bytes;
+
+
+ /**
+ * @param bytes Data
+ */
+ public ConstantDouble(double bytes) {
+ super(Constants.CONSTANT_Double);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantDouble(ConstantDouble c) {
+ this(c.getBytes());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantDouble(DataInput file) throws IOException {
+ this(file.readDouble());
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantDouble(this);
+ }
+
+
+ /**
+ * Dump constant double to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeDouble(bytes);
+ }
+
+
+ /**
+ * @return data, i.e., 8 bytes.
+ */
+ public final double getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes the raw bytes that represent the double value
+ */
+ public final void setBytes( double bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(bytes = " + bytes + ")";
+ }
+
+
+ /** @return Double object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ return new Double(bytes);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a constant pool reference to a field.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ConstantFieldref extends ConstantCP {
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantFieldref(ConstantFieldref c) {
+ super(Constants.CONSTANT_Fieldref, c.getClassIndex(), c.getNameAndTypeIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file input stream
+ * @throws IOException
+ */
+ ConstantFieldref(DataInputStream file) throws IOException {
+ super(Constants.CONSTANT_Fieldref, file);
+ }
+
+
+ /**
+ * @param class_index Reference to the class containing the Field
+ * @param name_and_type_index and the Field signature
+ */
+ public ConstantFieldref(int class_index, int name_and_type_index) {
+ super(Constants.CONSTANT_Fieldref, class_index, name_and_type_index);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of Fields,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantFieldref(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a float object.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantFloat extends Constant implements ConstantObject {
+
+ private float bytes;
+
+
+ /**
+ * @param bytes Data
+ */
+ public ConstantFloat(float bytes) {
+ super(Constants.CONSTANT_Float);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public ConstantFloat(ConstantFloat c) {
+ this(c.getBytes());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantFloat(DataInput file) throws IOException {
+ this(file.readFloat());
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantFloat(this);
+ }
+
+
+ /**
+ * Dump constant float to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeFloat(bytes);
+ }
+
+
+ /**
+ * @return data, i.e., 4 bytes.
+ */
+ public final float getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes the raw bytes that represent this float
+ */
+ public final void setBytes( float bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(bytes = " + bytes + ")";
+ }
+
+
+ /** @return Float object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ return new Float(bytes);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to an int object.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantInteger extends Constant implements ConstantObject {
+
+ private int bytes;
+
+
+ /**
+ * @param bytes Data
+ */
+ public ConstantInteger(int bytes) {
+ super(Constants.CONSTANT_Integer);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantInteger(ConstantInteger c) {
+ this(c.getBytes());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantInteger(DataInput file) throws IOException {
+ this(file.readInt());
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantInteger(this);
+ }
+
+
+ /**
+ * Dump constant integer to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeInt(bytes);
+ }
+
+
+ /**
+ * @return data, i.e., 4 bytes.
+ */
+ public final int getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes the raw bytes that represent this integer
+ */
+ public final void setBytes( int bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(bytes = " + bytes + ")";
+ }
+
+
+ /** @return Integer object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ return new Integer(bytes);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a constant pool reference to an interface method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ConstantInterfaceMethodref extends ConstantCP {
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantInterfaceMethodref(ConstantInterfaceMethodref c) {
+ super(Constants.CONSTANT_InterfaceMethodref, c.getClassIndex(), c.getNameAndTypeIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file input stream
+ * @throws IOException
+ */
+ ConstantInterfaceMethodref(DataInputStream file) throws IOException {
+ super(Constants.CONSTANT_InterfaceMethodref, file);
+ }
+
+
+ /**
+ * @param class_index Reference to the class containing the method
+ * @param name_and_type_index and the method signature
+ */
+ public ConstantInterfaceMethodref(int class_index, int name_and_type_index) {
+ super(Constants.CONSTANT_InterfaceMethodref, class_index, name_and_type_index);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantInterfaceMethodref(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a long object.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantLong extends Constant implements ConstantObject {
+
+ private long bytes;
+
+
+ /**
+ * @param bytes Data
+ */
+ public ConstantLong(long bytes) {
+ super(Constants.CONSTANT_Long);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantLong(ConstantLong c) {
+ this(c.getBytes());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantLong(DataInput file) throws IOException {
+ this(file.readLong());
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantLong(this);
+ }
+
+
+ /**
+ * Dump constant long to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeLong(bytes);
+ }
+
+
+ /**
+ * @return data, i.e., 8 bytes.
+ */
+ public final long getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes thr raw bytes that represent this long
+ */
+ public final void setBytes( long bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(bytes = " + bytes + ")";
+ }
+
+
+ /** @return Long object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ return new Long(bytes);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a constant pool reference to a method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ConstantMethodref extends ConstantCP {
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantMethodref(ConstantMethodref c) {
+ super(Constants.CONSTANT_Methodref, c.getClassIndex(), c.getNameAndTypeIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file input stream
+ * @throws IOException
+ */
+ ConstantMethodref(DataInputStream file) throws IOException {
+ super(Constants.CONSTANT_Methodref, file);
+ }
+
+
+ /**
+ * @param class_index Reference to the class containing the method
+ * @param name_and_type_index and the method signature
+ */
+ public ConstantMethodref(int class_index, int name_and_type_index) {
+ super(Constants.CONSTANT_Methodref, class_index, name_and_type_index);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantMethodref(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to the name and signature
+ * of a field or method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantNameAndType extends Constant {
+
+ private int name_index; // Name of field/method
+ private int signature_index; // and its signature.
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantNameAndType(ConstantNameAndType c) {
+ this(c.getNameIndex(), c.getSignatureIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantNameAndType(DataInput file) throws IOException {
+ this(file.readUnsignedShort(), file.readUnsignedShort());
+ }
+
+
+ /**
+ * @param name_index Name of field/method
+ * @param signature_index and its signature
+ */
+ public ConstantNameAndType(int name_index, int signature_index) {
+ super(Constants.CONSTANT_NameAndType);
+ this.name_index = name_index;
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantNameAndType(this);
+ }
+
+
+ /**
+ * Dump name and signature index to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(name_index);
+ file.writeShort(signature_index);
+ }
+
+
+ /**
+ * @return Name index in constant pool of field/method name.
+ */
+ public final int getNameIndex() {
+ return name_index;
+ }
+
+
+ /** @return name
+ */
+ public final String getName( ConstantPool cp ) {
+ return cp.constantToString(getNameIndex(), Constants.CONSTANT_Utf8);
+ }
+
+
+ /**
+ * @return Index in constant pool of field/method signature.
+ */
+ public final int getSignatureIndex() {
+ return signature_index;
+ }
+
+
+ /** @return signature
+ */
+ public final String getSignature( ConstantPool cp ) {
+ return cp.constantToString(getSignatureIndex(), Constants.CONSTANT_Utf8);
+ }
+
+
+ /**
+ * @param name_index the name index of this constant
+ */
+ public final void setNameIndex( int name_index ) {
+ this.name_index = name_index;
+ }
+
+
+ /**
+ * @param signature_index the signature index in the constant pool of this type
+ */
+ public final void setSignatureIndex( int signature_index ) {
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return super.toString() + "(name_index = " + name_index + ", signature_index = "
+ + signature_index + ")";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * This interface denotes those constants that have a "natural" value,
+ * such as ConstantLong, ConstantString, etc..
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public interface ConstantObject {
+
+ /** @return object representing the constant, e.g., Long for ConstantLong
+ */
+ public abstract Object getConstantValue( ConstantPool cp );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents the constant pool, i.e., a table of constants, of
+ * a parsed classfile. It may contain null references, due to the JVM
+ * specification that skips an entry after an 8-byte constant (double,
+ * long) entry. Those interested in generating constant pools
+ * programatically should see <a href="../generic/ConstantPoolGen.html">
+ * ConstantPoolGen</a>.
+
+ * @version $Id$
+ * @see Constant
+ * @see org.apache.tomcat.util.bcel.generic.ConstantPoolGen
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ConstantPool implements Cloneable, Node, Serializable {
+
+ private int constant_pool_count;
+ private Constant[] constant_pool;
+
+
+ /**
+ * @param constant_pool Array of constants
+ */
+ public ConstantPool(Constant[] constant_pool) {
+ setConstantPool(constant_pool);
+ }
+
+
+ /**
+ * Read constants from given file stream.
+ *
+ * @param file Input stream
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ ConstantPool(DataInputStream file) throws IOException, ClassFormatException {
+ byte tag;
+ constant_pool_count = file.readUnsignedShort();
+ constant_pool = new Constant[constant_pool_count];
+ /* constant_pool[0] is unused by the compiler and may be used freely
+ * by the implementation.
+ */
+ for (int i = 1; i < constant_pool_count; i++) {
+ constant_pool[i] = Constant.readConstant(file);
+ /* Quote from the JVM specification:
+ * "All eight byte constants take up two spots in the constant pool.
+ * If this is the n'th byte in the constant pool, then the next item
+ * will be numbered n+2"
+ *
+ * Thus we have to increment the index counter.
+ */
+ tag = constant_pool[i].getTag();
+ if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) {
+ i++;
+ }
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantPool(this);
+ }
+
+
+ /**
+ * Resolve constant to a string representation.
+ *
+ * @param c Constant to be printed
+ * @return String representation
+ */
+ public String constantToString( Constant c ) throws ClassFormatException {
+ String str;
+ int i;
+ byte tag = c.getTag();
+ switch (tag) {
+ case Constants.CONSTANT_Class:
+ i = ((ConstantClass) c).getNameIndex();
+ c = getConstant(i, Constants.CONSTANT_Utf8);
+ str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
+ break;
+ case Constants.CONSTANT_String:
+ i = ((ConstantString) c).getStringIndex();
+ c = getConstant(i, Constants.CONSTANT_Utf8);
+ str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
+ break;
+ case Constants.CONSTANT_Utf8:
+ str = ((ConstantUtf8) c).getBytes();
+ break;
+ case Constants.CONSTANT_Double:
+ str = String.valueOf(((ConstantDouble) c).getBytes());
+ break;
+ case Constants.CONSTANT_Float:
+ str = String.valueOf(((ConstantFloat) c).getBytes());
+ break;
+ case Constants.CONSTANT_Long:
+ str = String.valueOf(((ConstantLong) c).getBytes());
+ break;
+ case Constants.CONSTANT_Integer:
+ str = String.valueOf(((ConstantInteger) c).getBytes());
+ break;
+ case Constants.CONSTANT_NameAndType:
+ str = (constantToString(((ConstantNameAndType) c).getNameIndex(),
+ Constants.CONSTANT_Utf8)
+ + " " + constantToString(((ConstantNameAndType) c).getSignatureIndex(),
+ Constants.CONSTANT_Utf8));
+ break;
+ case Constants.CONSTANT_InterfaceMethodref:
+ case Constants.CONSTANT_Methodref:
+ case Constants.CONSTANT_Fieldref:
+ str = (constantToString(((ConstantCP) c).getClassIndex(), Constants.CONSTANT_Class)
+ + "." + constantToString(((ConstantCP) c).getNameAndTypeIndex(),
+ Constants.CONSTANT_NameAndType));
+ break;
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + tag);
+ }
+ return str;
+ }
+
+
+ private static final String escape( String str ) {
+ int len = str.length();
+ StringBuffer buf = new StringBuffer(len + 5);
+ char[] ch = str.toCharArray();
+ for (int i = 0; i < len; i++) {
+ switch (ch[i]) {
+ case '\n':
+ buf.append("\\n");
+ break;
+ case '\r':
+ buf.append("\\r");
+ break;
+ case '\t':
+ buf.append("\\t");
+ break;
+ case '\b':
+ buf.append("\\b");
+ break;
+ case '"':
+ buf.append("\\\"");
+ break;
+ default:
+ buf.append(ch[i]);
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Retrieve constant at `index' from constant pool and resolve it to
+ * a string representation.
+ *
+ * @param index of constant in constant pool
+ * @param tag expected type
+ * @return String representation
+ */
+ public String constantToString( int index, byte tag ) throws ClassFormatException {
+ Constant c = getConstant(index, tag);
+ return constantToString(c);
+ }
+
+
+ /**
+ * Dump constant pool to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(constant_pool_count);
+ for (int i = 1; i < constant_pool_count; i++) {
+ if (constant_pool[i] != null) {
+ constant_pool[i].dump(file);
+ }
+ }
+ }
+
+
+ /**
+ * Get constant from constant pool.
+ *
+ * @param index Index in constant pool
+ * @return Constant value
+ * @see Constant
+ */
+ public Constant getConstant( int index ) {
+ if (index >= constant_pool.length || index < 0) {
+ throw new ClassFormatException("Invalid constant pool reference: " + index
+ + ". Constant pool size is: " + constant_pool.length);
+ }
+ return constant_pool[index];
+ }
+
+
+ /**
+ * Get constant from constant pool and check whether it has the
+ * expected type.
+ *
+ * @param index Index in constant pool
+ * @param tag Tag of expected constant, i.e., its type
+ * @return Constant value
+ * @see Constant
+ * @throws ClassFormatException
+ */
+ public Constant getConstant( int index, byte tag ) throws ClassFormatException {
+ Constant c;
+ c = getConstant(index);
+ if (c == null) {
+ throw new ClassFormatException("Constant pool at index " + index + " is null.");
+ }
+ if (c.getTag() != tag) {
+ throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag]
+ + "' at index " + index + " and got " + c);
+ }
+ return c;
+ }
+
+
+ /**
+ * @return Array of constants.
+ * @see Constant
+ */
+ public Constant[] getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * Get string from constant pool and bypass the indirection of
+ * `ConstantClass' and `ConstantString' objects. I.e. these classes have
+ * an index field that points to another entry of the constant pool of
+ * type `ConstantUtf8' which contains the real data.
+ *
+ * @param index Index in constant pool
+ * @param tag Tag of expected constant, either ConstantClass or ConstantString
+ * @return Contents of string reference
+ * @see ConstantClass
+ * @see ConstantString
+ * @throws ClassFormatException
+ */
+ public String getConstantString( int index, byte tag ) throws ClassFormatException {
+ Constant c;
+ int i;
+ c = getConstant(index, tag);
+ /* This switch() is not that elegant, since the two classes have the
+ * same contents, they just differ in the name of the index
+ * field variable.
+ * But we want to stick to the JVM naming conventions closely though
+ * we could have solved these more elegantly by using the same
+ * variable name or by subclassing.
+ */
+ switch (tag) {
+ case Constants.CONSTANT_Class:
+ i = ((ConstantClass) c).getNameIndex();
+ break;
+ case Constants.CONSTANT_String:
+ i = ((ConstantString) c).getStringIndex();
+ break;
+ default:
+ throw new RuntimeException("getConstantString called with illegal tag " + tag);
+ }
+ // Finally get the string from the constant pool
+ c = getConstant(i, Constants.CONSTANT_Utf8);
+ return ((ConstantUtf8) c).getBytes();
+ }
+
+
+ /**
+ * @return Length of constant pool.
+ */
+ public int getLength() {
+ return constant_pool_count;
+ }
+
+
+ /**
+ * @param constant Constant to set
+ */
+ public void setConstant( int index, Constant constant ) {
+ constant_pool[index] = constant;
+ }
+
+
+ /**
+ * @param constant_pool
+ */
+ public void setConstantPool( Constant[] constant_pool ) {
+ this.constant_pool = constant_pool;
+ constant_pool_count = (constant_pool == null) ? 0 : constant_pool.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 1; i < constant_pool_count; i++) {
+ buf.append(i).append(")").append(constant_pool[i]).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this constant pool
+ */
+ public ConstantPool copy() {
+ ConstantPool c = null;
+ try {
+ c = (ConstantPool) clone();
+ c.constant_pool = new Constant[constant_pool_count];
+ for (int i = 1; i < constant_pool_count; i++) {
+ if (constant_pool[i] != null) {
+ c.constant_pool[i] = constant_pool[i].copy();
+ }
+ }
+ } catch (CloneNotSupportedException e) {
+ }
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a String object.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantString extends Constant implements ConstantObject {
+
+ private int string_index; // Identical to ConstantClass except for this name
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantString(ConstantString c) {
+ this(c.getStringIndex());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantString(DataInput file) throws IOException {
+ this(file.readUnsignedShort());
+ }
+
+
+ /**
+ * @param string_index Index of Constant_Utf8 in constant pool
+ */
+ public ConstantString(int string_index) {
+ super(Constants.CONSTANT_String);
+ this.string_index = string_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantString(this);
+ }
+
+
+ /**
+ * Dump constant field reference to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeShort(string_index);
+ }
+
+
+ /**
+ * @return Index in constant pool of the string (ConstantUtf8).
+ */
+ public final int getStringIndex() {
+ return string_index;
+ }
+
+
+ /**
+ * @param string_index the index into the constant of the string value
+ */
+ public final void setStringIndex( int string_index ) {
+ this.string_index = string_index;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return super.toString() + "(string_index = " + string_index + ")";
+ }
+
+
+ /** @return String object
+ */
+ public Object getConstantValue( ConstantPool cp ) {
+ Constant c = cp.getConstant(string_index, Constants.CONSTANT_Utf8);
+ return ((ConstantUtf8) c).getBytes();
+ }
+
+
+ /** @return dereferenced string
+ */
+ public String getBytes( ConstantPool cp ) {
+ return (String) getConstantValue(cp);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from the abstract
+ * <A HREF="org.apache.tomcat.util.bcel.classfile.Constant.html">Constant</A> class
+ * and represents a reference to a Utf8 encoded string.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public final class ConstantUtf8 extends Constant {
+
+ private String bytes;
+
+
+ /**
+ * Initialize from another object.
+ */
+ public ConstantUtf8(ConstantUtf8 c) {
+ this(c.getBytes());
+ }
+
+
+ /**
+ * Initialize instance from file data.
+ *
+ * @param file Input stream
+ * @throws IOException
+ */
+ ConstantUtf8(DataInput file) throws IOException {
+ super(Constants.CONSTANT_Utf8);
+ bytes = file.readUTF();
+ }
+
+
+ /**
+ * @param bytes Data
+ */
+ public ConstantUtf8(String bytes) {
+ super(Constants.CONSTANT_Utf8);
+ if (bytes == null) {
+ throw new IllegalArgumentException("bytes must not be null!");
+ }
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantUtf8(this);
+ }
+
+
+ /**
+ * Dump String in Utf8 format to file stream.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(tag);
+ file.writeUTF(bytes);
+ }
+
+
+ /**
+ * @return Data converted to string.
+ */
+ public final String getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes the raw bytes of this Utf-8
+ */
+ public final void setBytes( String bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return super.toString() + "(\"" + Utility.replace(bytes, "\n", "\\n") + "\")";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and represents a constant
+ * value, i.e., a default value for initializing a class field.
+ * This class is instantiated by the <em>Attribute.readAttribute()</em> method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class ConstantValue extends Attribute {
+
+ private int constantvalue_index;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public ConstantValue(ConstantValue c) {
+ this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Name index in constant pool
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ ConstantValue(int name_index, int length, DataInput file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, file.readUnsignedShort(), constant_pool);
+ }
+
+
+ /**
+ * @param name_index Name index in constant pool
+ * @param length Content length in bytes
+ * @param constantvalue_index Index in constant pool
+ * @param constant_pool Array of constants
+ */
+ public ConstantValue(int name_index, int length, int constantvalue_index,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_CONSTANT_VALUE, name_index, length, constant_pool);
+ this.constantvalue_index = constantvalue_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitConstantValue(this);
+ }
+
+
+ /**
+ * Dump constant value attribute to file stream on binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(constantvalue_index);
+ }
+
+
+ /**
+ * @return Index in constant pool of constant value.
+ */
+ public final int getConstantValueIndex() {
+ return constantvalue_index;
+ }
+
+
+ /**
+ * @param constantvalue_index the index info the constant pool of this constant value
+ */
+ public final void setConstantValueIndex( int constantvalue_index ) {
+ this.constantvalue_index = constantvalue_index;
+ }
+
+
+ /**
+ * @return String representation of constant value.
+ */
+ public final String toString() {
+ Constant c = constant_pool.getConstant(constantvalue_index);
+ String buf;
+ int i;
+ // Print constant to string depending on its type
+ switch (c.getTag()) {
+ case Constants.CONSTANT_Long:
+ buf = String.valueOf(((ConstantLong) c).getBytes());
+ break;
+ case Constants.CONSTANT_Float:
+ buf = String.valueOf(((ConstantFloat) c).getBytes());
+ break;
+ case Constants.CONSTANT_Double:
+ buf = String.valueOf(((ConstantDouble) c).getBytes());
+ break;
+ case Constants.CONSTANT_Integer:
+ buf = String.valueOf(((ConstantInteger) c).getBytes());
+ break;
+ case Constants.CONSTANT_String:
+ i = ((ConstantString) c).getStringIndex();
+ c = constant_pool.getConstant(i, Constants.CONSTANT_Utf8);
+ buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
+ break;
+ default:
+ throw new IllegalStateException("Type of ConstValue invalid: " + c);
+ }
+ return buf;
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ ConstantValue c = (ConstantValue) clone();
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and denotes that this is a
+ * deprecated method.
+ * It is instantiated from the <em>Attribute.readAttribute()</em> method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class Deprecated extends Attribute {
+
+ private byte[] bytes;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public Deprecated(Deprecated c) {
+ this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param bytes Attribute contents
+ * @param constant_pool Array of constants
+ */
+ public Deprecated(int name_index, int length, byte[] bytes, ConstantPool constant_pool) {
+ super(Constants.ATTR_DEPRECATED, name_index, length, constant_pool);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ Deprecated(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (byte[]) null, constant_pool);
+ if (length > 0) {
+ bytes = new byte[length];
+ file.readFully(bytes);
+ System.err.println("Deprecated attribute with length > 0");
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitDeprecated(this);
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ if (length > 0) {
+ file.write(bytes, 0, length);
+ }
+ }
+
+
+ /**
+ * @return data bytes.
+ */
+ public final byte[] getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes the raw bytes that represents this byte array
+ */
+ public final void setBytes( byte[] bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return attribute name
+ */
+ public final String toString() {
+ return Constants.ATTRIBUTE_NAMES[Constants.ATTR_DEPRECATED];
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ Deprecated c = (Deprecated) clone();
+ if (bytes != null) {
+ c.bytes = new byte[bytes.length];
+ System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.util.Stack;
+
+/**
+ * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
+ * applied to all components of a JavaClass object. I.e. this class supplies the
+ * traversal strategy, other classes can make use of it.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DescendingVisitor implements Visitor
+{
+ private JavaClass clazz;
+
+ private Visitor visitor;
+
+ private Stack stack = new Stack();
+
+ /**
+ * @return container of current entitity, i.e., predecessor during traversal
+ */
+ public Object predecessor()
+ {
+ return predecessor(0);
+ }
+
+ /**
+ * @param level
+ * nesting level, i.e., 0 returns the direct predecessor
+ * @return container of current entitity, i.e., predecessor during traversal
+ */
+ public Object predecessor(int level)
+ {
+ int size = stack.size();
+ if ((size < 2) || (level < 0))
+ {
+ return null;
+ }
+ else
+ {
+ return stack.elementAt(size - (level + 2)); // size - 1 == current
+ }
+ }
+
+ /**
+ * @return current object
+ */
+ public Object current()
+ {
+ return stack.peek();
+ }
+
+ /**
+ * @param clazz
+ * Class to traverse
+ * @param visitor
+ * visitor object to apply to all components
+ */
+ public DescendingVisitor(JavaClass clazz, Visitor visitor)
+ {
+ this.clazz = clazz;
+ this.visitor = visitor;
+ }
+
+ /**
+ * Start traversal.
+ */
+ public void visit()
+ {
+ clazz.accept(this);
+ }
+
+ public void visitJavaClass(JavaClass _clazz)
+ {
+ stack.push(_clazz);
+ _clazz.accept(visitor);
+ Field[] fields = _clazz.getFields();
+ for (int i = 0; i < fields.length; i++)
+ {
+ fields[i].accept(this);
+ }
+ Method[] methods = _clazz.getMethods();
+ for (int i = 0; i < methods.length; i++)
+ {
+ methods[i].accept(this);
+ }
+ Attribute[] attributes = _clazz.getAttributes();
+ for (int i = 0; i < attributes.length; i++)
+ {
+ attributes[i].accept(this);
+ }
+ _clazz.getConstantPool().accept(this);
+ stack.pop();
+ }
+
+ public void visitAnnotation(Annotations annotation)
+ {
+ stack.push(annotation);
+ annotation.accept(visitor);
+ AnnotationEntry[] entries = annotation.getAnnotationEntries();
+ for (int i = 0; i < entries.length; i++)
+ {
+ entries[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitAnnotationEntry(AnnotationEntry annotationEntry)
+ {
+ stack.push(annotationEntry);
+ annotationEntry.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitField(Field field)
+ {
+ stack.push(field);
+ field.accept(visitor);
+ Attribute[] attributes = field.getAttributes();
+ for (int i = 0; i < attributes.length; i++)
+ {
+ attributes[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitConstantValue(ConstantValue cv)
+ {
+ stack.push(cv);
+ cv.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitMethod(Method method)
+ {
+ stack.push(method);
+ method.accept(visitor);
+ Attribute[] attributes = method.getAttributes();
+ for (int i = 0; i < attributes.length; i++)
+ {
+ attributes[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitExceptionTable(ExceptionTable table)
+ {
+ stack.push(table);
+ table.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitCode(Code code)
+ {
+ stack.push(code);
+ code.accept(visitor);
+ CodeException[] table = code.getExceptionTable();
+ for (int i = 0; i < table.length; i++)
+ {
+ table[i].accept(this);
+ }
+ Attribute[] attributes = code.getAttributes();
+ for (int i = 0; i < attributes.length; i++)
+ {
+ attributes[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitCodeException(CodeException ce)
+ {
+ stack.push(ce);
+ ce.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitLineNumberTable(LineNumberTable table)
+ {
+ stack.push(table);
+ table.accept(visitor);
+ LineNumber[] numbers = table.getLineNumberTable();
+ for (int i = 0; i < numbers.length; i++)
+ {
+ numbers[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitLineNumber(LineNumber number)
+ {
+ stack.push(number);
+ number.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitLocalVariableTable(LocalVariableTable table)
+ {
+ stack.push(table);
+ table.accept(visitor);
+ LocalVariable[] vars = table.getLocalVariableTable();
+ for (int i = 0; i < vars.length; i++)
+ {
+ vars[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitStackMap(StackMap table)
+ {
+ stack.push(table);
+ table.accept(visitor);
+ StackMapEntry[] vars = table.getStackMap();
+ for (int i = 0; i < vars.length; i++)
+ {
+ vars[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitStackMapEntry(StackMapEntry var)
+ {
+ stack.push(var);
+ var.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitStackMapTable(StackMapTable table)
+ {
+ stack.push(table);
+ table.accept(visitor);
+ StackMapTableEntry[] vars = table.getStackMapTable();
+ for (int i = 0; i < vars.length; i++)
+ {
+ vars[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitStackMapTableEntry(StackMapTableEntry var)
+ {
+ stack.push(var);
+ var.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitLocalVariable(LocalVariable var)
+ {
+ stack.push(var);
+ var.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantPool(ConstantPool cp)
+ {
+ stack.push(cp);
+ cp.accept(visitor);
+ Constant[] constants = cp.getConstantPool();
+ for (int i = 1; i < constants.length; i++)
+ {
+ if (constants[i] != null)
+ {
+ constants[i].accept(this);
+ }
+ }
+ stack.pop();
+ }
+
+ public void visitConstantClass(ConstantClass constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantDouble(ConstantDouble constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantFieldref(ConstantFieldref constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantFloat(ConstantFloat constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantInteger(ConstantInteger constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantInterfaceMethodref(
+ ConstantInterfaceMethodref constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantLong(ConstantLong constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantMethodref(ConstantMethodref constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantNameAndType(ConstantNameAndType constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantString(ConstantString constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitConstantUtf8(ConstantUtf8 constant)
+ {
+ stack.push(constant);
+ constant.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitInnerClasses(InnerClasses ic)
+ {
+ stack.push(ic);
+ ic.accept(visitor);
+ InnerClass[] ics = ic.getInnerClasses();
+ for (int i = 0; i < ics.length; i++)
+ {
+ ics[i].accept(this);
+ }
+ stack.pop();
+ }
+
+ public void visitInnerClass(InnerClass inner)
+ {
+ stack.push(inner);
+ inner.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitDeprecated(Deprecated attribute)
+ {
+ stack.push(attribute);
+ attribute.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitSignature(Signature attribute)
+ {
+ stack.push(attribute);
+ attribute.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitSourceFile(SourceFile attribute)
+ {
+ stack.push(attribute);
+ attribute.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitSynthetic(Synthetic attribute)
+ {
+ stack.push(attribute);
+ attribute.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitUnknown(Unknown attribute)
+ {
+ stack.push(attribute);
+ attribute.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitAnnotationDefault(AnnotationDefault obj)
+ {
+ stack.push(obj);
+ obj.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitEnclosingMethod(EnclosingMethod obj)
+ {
+ stack.push(obj);
+ obj.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitLocalVariableTypeTable(LocalVariableTypeTable obj)
+ {
+ stack.push(obj);
+ obj.accept(visitor);
+ stack.pop();
+ }
+
+ public void visitParameterAnnotation(ParameterAnnotations obj)
+ {
+ stack.push(obj);
+ obj.accept(visitor);
+ stack.pop();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * @version $Id: ElementValue
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public abstract class ElementValue
+{
+ protected int type;
+
+ protected ConstantPool cpool;
+
+ public String toString()
+ {
+ return stringifyValue();
+ }
+
+ protected ElementValue(int type, ConstantPool cpool)
+ {
+ this.type = type;
+ this.cpool = cpool;
+ }
+
+ public int getElementValueType()
+ {
+ return type;
+ }
+
+ public abstract String stringifyValue();
+
+ public abstract void dump(DataOutputStream dos) throws IOException;
+
+ public static final int STRING = 's';
+
+ public static final int ENUM_CONSTANT = 'e';
+
+ public static final int CLASS = 'c';
+
+ public static final int ANNOTATION = '@';
+
+ public static final int ARRAY = '[';
+
+ public static final int PRIMITIVE_INT = 'I';
+
+ public static final int PRIMITIVE_BYTE = 'B';
+
+ public static final int PRIMITIVE_CHAR = 'C';
+
+ public static final int PRIMITIVE_DOUBLE = 'D';
+
+ public static final int PRIMITIVE_FLOAT = 'F';
+
+ public static final int PRIMITIVE_LONG = 'J';
+
+ public static final int PRIMITIVE_SHORT = 'S';
+
+ public static final int PRIMITIVE_BOOLEAN = 'Z';
+
+ public static ElementValue readElementValue(DataInputStream dis,
+ ConstantPool cpool) throws IOException
+ {
+ byte type = dis.readByte();
+ switch (type)
+ {
+ case 'B': // byte
+ return new SimpleElementValue(PRIMITIVE_BYTE, dis
+ .readUnsignedShort(), cpool);
+ case 'C': // char
+ return new SimpleElementValue(PRIMITIVE_CHAR, dis
+ .readUnsignedShort(), cpool);
+ case 'D': // double
+ return new SimpleElementValue(PRIMITIVE_DOUBLE, dis
+ .readUnsignedShort(), cpool);
+ case 'F': // float
+ return new SimpleElementValue(PRIMITIVE_FLOAT, dis
+ .readUnsignedShort(), cpool);
+ case 'I': // int
+ return new SimpleElementValue(PRIMITIVE_INT, dis
+ .readUnsignedShort(), cpool);
+ case 'J': // long
+ return new SimpleElementValue(PRIMITIVE_LONG, dis
+ .readUnsignedShort(), cpool);
+ case 'S': // short
+ return new SimpleElementValue(PRIMITIVE_SHORT, dis
+ .readUnsignedShort(), cpool);
+ case 'Z': // boolean
+ return new SimpleElementValue(PRIMITIVE_BOOLEAN, dis
+ .readUnsignedShort(), cpool);
+ case 's': // String
+ return new SimpleElementValue(STRING, dis.readUnsignedShort(),
+ cpool);
+ case 'e': // Enum constant
+ return new EnumElementValue(ENUM_CONSTANT, dis.readUnsignedShort(),
+ dis.readUnsignedShort(), cpool);
+ case 'c': // Class
+ return new ClassElementValue(CLASS, dis.readUnsignedShort(), cpool);
+ case '@': // Annotation
+ // TODO isRuntimeVisible
+ return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(
+ dis, cpool, false), cpool);
+ case '[': // Array
+ int numArrayVals = dis.readUnsignedShort();
+ ElementValue[] evalues = new ElementValue[numArrayVals];
+ for (int j = 0; j < numArrayVals; j++)
+ {
+ evalues[j] = ElementValue.readElementValue(dis, cpool);
+ }
+ return new ArrayElementValue(ARRAY, evalues, cpool);
+ default:
+ throw new RuntimeException(
+ "Unexpected element value kind in annotation: " + type);
+ }
+ }
+
+ public String toShortString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(stringifyValue());
+ return result.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * an annotation's element value pair
+ *
+ * @version $Id: ElementValuePair
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class ElementValuePair
+{
+ private ElementValue elementValue;
+
+ private ConstantPool constantPool;
+
+ private int elementNameIndex;
+
+ public ElementValuePair(int elementNameIndex, ElementValue elementValue,
+ ConstantPool constantPool)
+ {
+ this.elementValue = elementValue;
+ this.elementNameIndex = elementNameIndex;
+ this.constantPool = constantPool;
+ }
+
+ public String getNameString()
+ {
+ ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant(
+ elementNameIndex, Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ public final ElementValue getValue()
+ {
+ return elementValue;
+ }
+
+ public int getNameIndex()
+ {
+ return elementNameIndex;
+ }
+
+ public String toShortString()
+ {
+ StringBuffer result = new StringBuffer();
+ result.append(getNameString()).append("=").append(
+ getValue().toShortString());
+ return result.toString();
+ }
+
+ protected void dump(DataOutputStream dos) throws IOException {
+ dos.writeShort(elementNameIndex); // u2 name of the element
+ elementValue.dump(dos);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * Visitor with empty method bodies, can be extended and used in conjunction
+ * with the DescendingVisitor class, e.g. By courtesy of David Spencer.
+ *
+ * @see DescendingVisitor
+ * @version $Id$
+ */
+public class EmptyVisitor implements Visitor
+{
+ protected EmptyVisitor()
+ {
+ }
+
+ public void visitAnnotation(Annotations obj)
+ {
+ }
+
+ public void visitParameterAnnotation(ParameterAnnotations obj)
+ {
+ }
+
+ public void visitAnnotationEntry(AnnotationEntry obj)
+ {
+ }
+
+ public void visitAnnotationDefault(AnnotationDefault obj)
+ {
+ }
+
+ public void visitCode(Code obj)
+ {
+ }
+
+ public void visitCodeException(CodeException obj)
+ {
+ }
+
+ public void visitConstantClass(ConstantClass obj)
+ {
+ }
+
+ public void visitConstantDouble(ConstantDouble obj)
+ {
+ }
+
+ public void visitConstantFieldref(ConstantFieldref obj)
+ {
+ }
+
+ public void visitConstantFloat(ConstantFloat obj)
+ {
+ }
+
+ public void visitConstantInteger(ConstantInteger obj)
+ {
+ }
+
+ public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj)
+ {
+ }
+
+ public void visitConstantLong(ConstantLong obj)
+ {
+ }
+
+ public void visitConstantMethodref(ConstantMethodref obj)
+ {
+ }
+
+ public void visitConstantNameAndType(ConstantNameAndType obj)
+ {
+ }
+
+ public void visitConstantPool(ConstantPool obj)
+ {
+ }
+
+ public void visitConstantString(ConstantString obj)
+ {
+ }
+
+ public void visitConstantUtf8(ConstantUtf8 obj)
+ {
+ }
+
+ public void visitConstantValue(ConstantValue obj)
+ {
+ }
+
+ public void visitDeprecated(Deprecated obj)
+ {
+ }
+
+ public void visitExceptionTable(ExceptionTable obj)
+ {
+ }
+
+ public void visitField(Field obj)
+ {
+ }
+
+ public void visitInnerClass(InnerClass obj)
+ {
+ }
+
+ public void visitInnerClasses(InnerClasses obj)
+ {
+ }
+
+ public void visitJavaClass(JavaClass obj)
+ {
+ }
+
+ public void visitLineNumber(LineNumber obj)
+ {
+ }
+
+ public void visitLineNumberTable(LineNumberTable obj)
+ {
+ }
+
+ public void visitLocalVariable(LocalVariable obj)
+ {
+ }
+
+ public void visitLocalVariableTable(LocalVariableTable obj)
+ {
+ }
+
+ public void visitMethod(Method obj)
+ {
+ }
+
+ public void visitSignature(Signature obj)
+ {
+ }
+
+ public void visitSourceFile(SourceFile obj)
+ {
+ }
+
+ public void visitSynthetic(Synthetic obj)
+ {
+ }
+
+ public void visitUnknown(Unknown obj)
+ {
+ }
+
+ public void visitStackMap(StackMap obj)
+ {
+ }
+
+ public void visitStackMapEntry(StackMapEntry obj)
+ {
+ }
+
+ public void visitStackMapTable(StackMapTable obj)
+ {
+ }
+
+ public void visitStackMapTableEntry(StackMapTableEntry obj)
+ {
+ }
+
+ public void visitEnclosingMethod(EnclosingMethod obj)
+ {
+ }
+
+ public void visitLocalVariableTypeTable(LocalVariableTypeTable obj)
+ {
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ *
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This attribute exists for local or
+ * anonymous classes and ... there can be only one.
+ */
+public class EnclosingMethod extends Attribute {
+
+ // Pointer to the CONSTANT_Class_info structure representing the
+ // innermost class that encloses the declaration of the current class.
+ private int classIndex;
+
+ // If the current class is not immediately enclosed by a method or
+ // constructor, then the value of the method_index item must be zero.
+ // Otherwise, the value of the method_index item must point to a
+ // CONSTANT_NameAndType_info structure representing the name and the
+ // type of a method in the class referenced by the class we point
+ // to in the class_index. *It is the compiler responsibility* to
+ // ensure that the method identified by this index is the closest
+ // lexically enclosing method that includes the local/anonymous class.
+ private int methodIndex;
+
+ // Ctors - and code to read an attribute in.
+ public EnclosingMethod(int nameIndex, int len, DataInput dis, ConstantPool cpool) throws IOException {
+ this(nameIndex, len, dis.readUnsignedShort(), dis.readUnsignedShort(), cpool);
+ }
+
+ private EnclosingMethod(int nameIndex, int len, int classIdx,int methodIdx, ConstantPool cpool) {
+ super(Constants.ATTR_ENCLOSING_METHOD, nameIndex, len, cpool);
+ classIndex = classIdx;
+ methodIndex = methodIdx;
+ }
+
+ public void accept(Visitor v) {
+ v.visitEnclosingMethod(this);
+ }
+
+ public Attribute copy(ConstantPool constant_pool) {
+ throw new RuntimeException("Not implemented yet!");
+ // is this next line sufficient?
+ // return (EnclosingMethod)clone();
+ }
+
+ // Accessors
+ public final int getEnclosingClassIndex() { return classIndex; }
+ public final int getEnclosingMethodIndex(){ return methodIndex;}
+
+ public final void setEnclosingClassIndex(int idx) {classIndex = idx;}
+ public final void setEnclosingMethodIndex(int idx){methodIndex= idx;}
+
+ public final ConstantClass getEnclosingClass() {
+ ConstantClass c =
+ (ConstantClass)constant_pool.getConstant(classIndex,Constants.CONSTANT_Class);
+ return c;
+ }
+
+ public final ConstantNameAndType getEnclosingMethod() {
+ if (methodIndex == 0) return null;
+ ConstantNameAndType nat =
+ (ConstantNameAndType)constant_pool.getConstant(methodIndex,Constants.CONSTANT_NameAndType);
+ return nat;
+ }
+
+ public final void dump(DataOutputStream file) throws IOException {
+ super.dump(file);
+ file.writeShort(classIndex);
+ file.writeShort(methodIndex);
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+public class EnumElementValue extends ElementValue
+{
+ // For enum types, these two indices point to the type and value
+ private int typeIdx;
+
+ private int valueIdx;
+
+ public EnumElementValue(int type, int typeIdx, int valueIdx,
+ ConstantPool cpool)
+ {
+ super(type, cpool);
+ if (type != ENUM_CONSTANT)
+ throw new RuntimeException(
+ "Only element values of type enum can be built with this ctor - type specified: " + type);
+ this.typeIdx = typeIdx;
+ this.valueIdx = valueIdx;
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e')
+ dos.writeShort(typeIdx); // u2
+ dos.writeShort(valueIdx); // u2
+ }
+
+ public String stringifyValue()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(valueIdx,
+ Constants.CONSTANT_Utf8);
+ return cu8.getBytes();
+ }
+
+ public String getEnumTypeString()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(typeIdx,
+ Constants.CONSTANT_Utf8);
+ return cu8.getBytes();// Utility.signatureToString(cu8.getBytes());
+ }
+
+ public String getEnumValueString()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(valueIdx,
+ Constants.CONSTANT_Utf8);
+ return cu8.getBytes();
+ }
+
+ public int getValueIndex()
+ {
+ return valueIdx;
+ }
+
+ public int getTypeIndex()
+ {
+ return typeIdx;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents the table of exceptions that are thrown by a
+ * method. This attribute may be used once per method. The name of
+ * this class is <em>ExceptionTable</em> for historical reasons; The
+ * Java Virtual Machine Specification, Second Edition defines this
+ * attribute using the name <em>Exceptions</em> (which is inconsistent
+ * with the other classes).
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ */
+public final class ExceptionTable extends Attribute {
+
+ private int number_of_exceptions; // Table of indices into
+ private int[] exception_index_table; // constant pool
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public ExceptionTable(ExceptionTable c) {
+ this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index in constant pool
+ * @param length Content length in bytes
+ * @param exception_index_table Table of indices in constant pool
+ * @param constant_pool Array of constants
+ */
+ public ExceptionTable(int name_index, int length, int[] exception_index_table,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_EXCEPTIONS, name_index, length, constant_pool);
+ setExceptionIndexTable(exception_index_table);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ ExceptionTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (int[]) null, constant_pool);
+ number_of_exceptions = file.readUnsignedShort();
+ exception_index_table = new int[number_of_exceptions];
+ for (int i = 0; i < number_of_exceptions; i++) {
+ exception_index_table[i] = file.readUnsignedShort();
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionTable(this);
+ }
+
+
+ /**
+ * Dump exceptions attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(number_of_exceptions);
+ for (int i = 0; i < number_of_exceptions; i++) {
+ file.writeShort(exception_index_table[i]);
+ }
+ }
+
+
+ /**
+ * @return Array of indices into constant pool of thrown exceptions.
+ */
+ public final int[] getExceptionIndexTable() {
+ return exception_index_table;
+ }
+
+
+ /**
+ * @return Length of exception table.
+ */
+ public final int getNumberOfExceptions() {
+ return number_of_exceptions;
+ }
+
+
+ /**
+ * @return class names of thrown exceptions
+ */
+ public final String[] getExceptionNames() {
+ String[] names = new String[number_of_exceptions];
+ for (int i = 0; i < number_of_exceptions; i++) {
+ names[i] = constant_pool.getConstantString(exception_index_table[i],
+ Constants.CONSTANT_Class).replace('/', '.');
+ }
+ return names;
+ }
+
+
+ /**
+ * @param exception_index_table the list of exception indexes
+ * Also redefines number_of_exceptions according to table length.
+ */
+ public final void setExceptionIndexTable( int[] exception_index_table ) {
+ this.exception_index_table = exception_index_table;
+ number_of_exceptions = (exception_index_table == null) ? 0 : exception_index_table.length;
+ }
+
+
+ /**
+ * @return String representation, i.e., a list of thrown exceptions.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+ String str;
+ for (int i = 0; i < number_of_exceptions; i++) {
+ str = constant_pool.getConstantString(exception_index_table[i],
+ Constants.CONSTANT_Class);
+ buf.append(Utility.compactClassName(str, false));
+ if (i < number_of_exceptions - 1) {
+ buf.append(", ");
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ ExceptionTable c = (ExceptionTable) clone();
+ if (exception_index_table != null) {
+ c.exception_index_table = new int[exception_index_table.length];
+ System.arraycopy(exception_index_table, 0, c.exception_index_table, 0,
+ exception_index_table.length);
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.generic.Type;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * This class represents the field info structure, i.e., the representation
+ * for a variable in the class. See JVM specification for details.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class Field extends FieldOrMethod {
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ Field THIS = (Field) o1;
+ Field THAT = (Field) o2;
+ return THIS.getName().equals(THAT.getName())
+ && THIS.getSignature().equals(THAT.getSignature());
+ }
+
+
+ public int hashCode( Object o ) {
+ Field THIS = (Field) o;
+ return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ }
+ };
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public Field(Field c) {
+ super(c);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ */
+ Field(DataInputStream file, ConstantPool constant_pool) throws IOException,
+ ClassFormatException {
+ super(file, constant_pool);
+ }
+
+
+ /**
+ * @param access_flags Access rights of field
+ * @param name_index Points to field name in constant pool
+ * @param signature_index Points to encoded signature
+ * @param attributes Collection of attributes
+ * @param constant_pool Array of constants
+ */
+ public Field(int access_flags, int name_index, int signature_index, Attribute[] attributes,
+ ConstantPool constant_pool) {
+ super(access_flags, name_index, signature_index, attributes, constant_pool);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitField(this);
+ }
+
+
+ /**
+ * @return constant value associated with this field (may be null)
+ */
+ public final ConstantValue getConstantValue() {
+ for (int i = 0; i < attributes_count; i++) {
+ if (attributes[i].getTag() == Constants.ATTR_CONSTANT_VALUE) {
+ return (ConstantValue) attributes[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Return string representation close to declaration format,
+ * `public static final short MAX = 100', e.g..
+ *
+ * @return String representation of field, including the signature.
+ */
+ public final String toString() {
+ String name, signature, access; // Short cuts to constant pool
+ // Get names from constant pool
+ access = Utility.accessToString(access_flags);
+ access = access.equals("") ? "" : (access + " ");
+ signature = Utility.signatureToString(getSignature());
+ name = getName();
+ StringBuffer buf = new StringBuffer(64);
+ buf.append(access).append(signature).append(" ").append(name);
+ ConstantValue cv = getConstantValue();
+ if (cv != null) {
+ buf.append(" = ").append(cv);
+ }
+ for (int i = 0; i < attributes_count; i++) {
+ Attribute a = attributes[i];
+ if (!(a instanceof ConstantValue)) {
+ buf.append(" [").append(a.toString()).append("]");
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this field
+ */
+ public final Field copy( ConstantPool _constant_pool ) {
+ return (Field) copy_(_constant_pool);
+ }
+
+
+ /**
+ * @return type of field
+ */
+ public Type getType() {
+ return Type.getReturnType(getSignature());
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two Field objects are said to be equal when
+ * their names and signatures are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the field's name XOR signature.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Signature;
+
+/**
+ * Abstract super class for fields and methods.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
+
+ protected int name_index; // Points to field name in constant pool
+ protected int signature_index; // Points to encoded signature
+ protected int attributes_count; // No. of attributes
+ protected Attribute[] attributes; // Collection of attributes
+ protected AnnotationEntry[] annotationEntries; // annotations defined on the field or method
+ protected ConstantPool constant_pool;
+
+ private String signatureAttributeString = null;
+ private boolean searchedForSignatureAttribute = false;
+
+
+ // Annotations are collected from certain attributes, don't do it more than necessary!
+ private boolean annotationsOutOfDate = true;
+
+ FieldOrMethod() {
+ }
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ protected FieldOrMethod(FieldOrMethod c) {
+ this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c
+ .getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ protected FieldOrMethod(DataInputStream file, ConstantPool constant_pool) throws IOException,
+ ClassFormatException {
+ this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
+ constant_pool);
+ attributes_count = file.readUnsignedShort();
+ attributes = new Attribute[attributes_count];
+ for (int i = 0; i < attributes_count; i++) {
+ attributes[i] = Attribute.readAttribute(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * @param access_flags Access rights of method
+ * @param name_index Points to field name in constant pool
+ * @param signature_index Points to encoded signature
+ * @param attributes Collection of attributes
+ * @param constant_pool Array of constants
+ */
+ protected FieldOrMethod(int access_flags, int name_index, int signature_index,
+ Attribute[] attributes, ConstantPool constant_pool) {
+ this.access_flags = access_flags;
+ this.name_index = name_index;
+ this.signature_index = signature_index;
+ this.constant_pool = constant_pool;
+ setAttributes(attributes);
+ }
+
+
+ /**
+ * Dump object to file stream on binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(access_flags);
+ file.writeShort(name_index);
+ file.writeShort(signature_index);
+ file.writeShort(attributes_count);
+ for (int i = 0; i < attributes_count; i++) {
+ attributes[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Collection of object attributes.
+ */
+ public final Attribute[] getAttributes() {
+ return attributes;
+ }
+
+
+ /**
+ * @param attributes Collection of object attributes.
+ */
+ public final void setAttributes( Attribute[] attributes ) {
+ this.attributes = attributes;
+ attributes_count = (attributes == null) ? 0 : attributes.length;
+ }
+
+
+ /**
+ * @return Constant pool used by this object.
+ */
+ public final ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @param constant_pool Constant pool to be used for this object.
+ */
+ public final void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * @return Index in constant pool of object's name.
+ */
+ public final int getNameIndex() {
+ return name_index;
+ }
+
+
+ /**
+ * @param name_index Index in constant pool of object's name.
+ */
+ public final void setNameIndex( int name_index ) {
+ this.name_index = name_index;
+ }
+
+
+ /**
+ * @return Index in constant pool of field signature.
+ */
+ public final int getSignatureIndex() {
+ return signature_index;
+ }
+
+
+ /**
+ * @param signature_index Index in constant pool of field signature.
+ */
+ public final void setSignatureIndex( int signature_index ) {
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * @return Name of object, i.e., method name or field name
+ */
+ public final String getName() {
+ ConstantUtf8 c;
+ c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return String representation of object's type signature (java style)
+ */
+ public final String getSignature() {
+ ConstantUtf8 c;
+ c = (ConstantUtf8) constant_pool.getConstant(signature_index, Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return deep copy of this field
+ */
+ protected FieldOrMethod copy_( ConstantPool _constant_pool ) {
+ FieldOrMethod c = null;
+
+ try {
+ c = (FieldOrMethod)clone();
+ } catch(CloneNotSupportedException e) {}
+
+ c.constant_pool = constant_pool;
+ c.attributes = new Attribute[attributes_count];
+
+ for(int i=0; i < attributes_count; i++)
+ c.attributes[i] = attributes[i].copy(constant_pool);
+
+ return c;
+ }
+
+ /**
+ * Ensure we have unpacked any attributes that contain annotations.
+ * We don't remove these annotation attributes from the attributes list, they
+ * remain there.
+ */
+ private void ensureAnnotationsUpToDate()
+ {
+ if (annotationsOutOfDate)
+ {
+ // Find attributes that contain annotation data
+ Attribute[] attrs = getAttributes();
+ List accumulatedAnnotations = new ArrayList();
+ for (int i = 0; i < attrs.length; i++)
+ {
+ Attribute attribute = attrs[i];
+ if (attribute instanceof Annotations)
+ {
+ Annotations annotations = (Annotations) attribute;
+ for (int j = 0; j < annotations.getAnnotationEntries().length; j++)
+ {
+ accumulatedAnnotations.add(annotations
+ .getAnnotationEntries()[j]);
+ }
+ }
+ }
+ annotationEntries = (AnnotationEntry[]) accumulatedAnnotations
+ .toArray(new AnnotationEntry[accumulatedAnnotations.size()]);
+ annotationsOutOfDate = false;
+ }
+ }
+
+ public AnnotationEntry[] getAnnotationEntries()
+ {
+ ensureAnnotationsUpToDate();
+ return annotationEntries;
+ }
+
+ public void addAnnotationEntry(AnnotationEntry a)
+ {
+ ensureAnnotationsUpToDate();
+ int len = annotationEntries.length;
+ AnnotationEntry[] newAnnotations = new AnnotationEntry[len + 1];
+ System.arraycopy(annotationEntries, 0, newAnnotations, 0, len);
+ newAnnotations[len] = a;
+ annotationEntries = newAnnotations;
+ }
+
+ /**
+ * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature
+ * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;'
+ * Coded for performance - searches for the attribute only when requested - only searches for it once.
+ */
+ public final String getGenericSignature()
+ {
+ if (!searchedForSignatureAttribute)
+ {
+ boolean found = false;
+ for (int i = 0; !found && i < attributes_count; i++)
+ {
+ if (attributes[i] instanceof Signature)
+ {
+ signatureAttributeString = ((Signature) attributes[i])
+ .getSignature();
+ found = true;
+ }
+ }
+ searchedForSignatureAttribute = true;
+ }
+ return signatureAttributeString;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a inner class attribute, i.e., the class
+ * indices of the inner and outer classes, the name and the attributes
+ * of the inner class.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see InnerClasses
+ */
+public final class InnerClass implements Cloneable, Node, Serializable {
+
+ private int inner_class_index;
+ private int outer_class_index;
+ private int inner_name_index;
+ private int inner_access_flags;
+
+
+ /**
+ * Initialize from another object.
+ */
+ public InnerClass(InnerClass c) {
+ this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c
+ .getInnerAccessFlags());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ InnerClass(DataInput file) throws IOException {
+ this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
+ .readUnsignedShort());
+ }
+
+
+ /**
+ * @param inner_class_index Class index in constant pool of inner class
+ * @param outer_class_index Class index in constant pool of outer class
+ * @param inner_name_index Name index in constant pool of inner class
+ * @param inner_access_flags Access flags of inner class
+ */
+ public InnerClass(int inner_class_index, int outer_class_index, int inner_name_index,
+ int inner_access_flags) {
+ this.inner_class_index = inner_class_index;
+ this.outer_class_index = outer_class_index;
+ this.inner_name_index = inner_name_index;
+ this.inner_access_flags = inner_access_flags;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitInnerClass(this);
+ }
+
+
+ /**
+ * Dump inner class attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(inner_class_index);
+ file.writeShort(outer_class_index);
+ file.writeShort(inner_name_index);
+ file.writeShort(inner_access_flags);
+ }
+
+
+ /**
+ * @return access flags of inner class.
+ */
+ public final int getInnerAccessFlags() {
+ return inner_access_flags;
+ }
+
+
+ /**
+ * @return class index of inner class.
+ */
+ public final int getInnerClassIndex() {
+ return inner_class_index;
+ }
+
+
+ /**
+ * @return name index of inner class.
+ */
+ public final int getInnerNameIndex() {
+ return inner_name_index;
+ }
+
+
+ /**
+ * @return class index of outer class.
+ */
+ public final int getOuterClassIndex() {
+ return outer_class_index;
+ }
+
+
+ /**
+ * @param inner_access_flags access flags for this inner class
+ */
+ public final void setInnerAccessFlags( int inner_access_flags ) {
+ this.inner_access_flags = inner_access_flags;
+ }
+
+
+ /**
+ * @param inner_class_index index into the constant pool for this class
+ */
+ public final void setInnerClassIndex( int inner_class_index ) {
+ this.inner_class_index = inner_class_index;
+ }
+
+
+ /**
+ * @param inner_name_index index into the constant pool for this class's name
+ */
+ public final void setInnerNameIndex( int inner_name_index ) {
+ this.inner_name_index = inner_name_index;
+ }
+
+
+ /**
+ * @param outer_class_index index into the constant pool for the owning class
+ */
+ public final void setOuterClassIndex( int outer_class_index ) {
+ this.outer_class_index = outer_class_index;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ return "InnerClass(" + inner_class_index + ", " + outer_class_index + ", "
+ + inner_name_index + ", " + inner_access_flags + ")";
+ }
+
+
+ /**
+ * @return Resolved string representation
+ */
+ public final String toString( ConstantPool constant_pool ) {
+ String inner_class_name, outer_class_name, inner_name, access;
+ inner_class_name = constant_pool.getConstantString(inner_class_index,
+ Constants.CONSTANT_Class);
+ inner_class_name = Utility.compactClassName(inner_class_name);
+ if (outer_class_index != 0) {
+ outer_class_name = constant_pool.getConstantString(outer_class_index,
+ Constants.CONSTANT_Class);
+ outer_class_name = Utility.compactClassName(outer_class_name);
+ } else {
+ outer_class_name = "<not a member>";
+ }
+ if (inner_name_index != 0) {
+ inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index,
+ Constants.CONSTANT_Utf8)).getBytes();
+ } else {
+ inner_name = "<anonymous>";
+ }
+ access = Utility.accessToString(inner_access_flags, true);
+ access = access.equals("") ? "" : (access + " ");
+ return "InnerClass:" + access + inner_class_name + "(\"" + outer_class_name + "\", \""
+ + inner_name + "\")";
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public InnerClass copy() {
+ try {
+ return (InnerClass) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and denotes that this class
+ * is an Inner class of another.
+ * to the source file of this class.
+ * It is instantiated from the <em>Attribute.readAttribute()</em> method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class InnerClasses extends Attribute {
+
+ private InnerClass[] inner_classes;
+ private int number_of_classes;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public InnerClasses(InnerClasses c) {
+ this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param inner_classes array of inner classes attributes
+ * @param constant_pool Array of constants
+ */
+ public InnerClasses(int name_index, int length, InnerClass[] inner_classes,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_INNER_CLASSES, name_index, length, constant_pool);
+ setInnerClasses(inner_classes);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ *
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ InnerClasses(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (InnerClass[]) null, constant_pool);
+ number_of_classes = file.readUnsignedShort();
+ inner_classes = new InnerClass[number_of_classes];
+ for (int i = 0; i < number_of_classes; i++) {
+ inner_classes[i] = new InnerClass(file);
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitInnerClasses(this);
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(number_of_classes);
+ for (int i = 0; i < number_of_classes; i++) {
+ inner_classes[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return array of inner class "records"
+ */
+ public final InnerClass[] getInnerClasses() {
+ return inner_classes;
+ }
+
+
+ /**
+ * @param inner_classes the array of inner classes
+ */
+ public final void setInnerClasses( InnerClass[] inner_classes ) {
+ this.inner_classes = inner_classes;
+ number_of_classes = (inner_classes == null) ? 0 : inner_classes.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < number_of_classes; i++) {
+ buf.append(inner_classes[i].toString(constant_pool)).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ InnerClasses c = (InnerClasses) clone();
+ c.inner_classes = new InnerClass[number_of_classes];
+ for (int i = 0; i < number_of_classes; i++) {
+ c.inner_classes[i] = inner_classes[i].copy();
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.generic.Type;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+import org.apache.tomcat.util.bcel.util.ClassQueue;
+import org.apache.tomcat.util.bcel.util.SyntheticRepository;
+
+/**
+ * Represents a Java class, i.e., the data structures, constant pool,
+ * fields, methods and commands contained in a Java .class file.
+ * See <a href="ftp://java.sun.com/docs/specs/">JVM specification</a> for details.
+ * The intent of this class is to represent a parsed or otherwise existing
+ * class file. Those interested in programatically generating classes
+ * should see the <a href="../generic/ClassGen.html">ClassGen</a> class.
+
+ * @version $Id$
+ * @see org.apache.tomcat.util.bcel.generic.ClassGen
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable {
+
+ private String file_name;
+ private String package_name;
+ private String source_file_name = "<Unknown>";
+ private int class_name_index;
+ private int superclass_name_index;
+ private String class_name;
+ private String superclass_name;
+ private int major, minor; // Compiler version
+ private ConstantPool constant_pool; // Constant pool
+ private int[] interfaces; // implemented interfaces
+ private String[] interface_names;
+ private Field[] fields; // Fields, i.e., variables of class
+ private Method[] methods; // methods defined in the class
+ private Attribute[] attributes; // attributes defined in the class
+ private AnnotationEntry[] annotations; // annotations defined on the class
+ private byte source = HEAP; // Generated in memory
+ private boolean isAnonymous = false;
+ private boolean isNested = false;
+ private boolean computedNestedTypeStatus = false;
+ public static final byte HEAP = 1;
+ public static final byte FILE = 2;
+ public static final byte ZIP = 3;
+ static boolean debug = false; // Debugging on/off
+ static char sep = '/'; // directory separator
+
+ // Annotations are collected from certain attributes, don't do it more than necessary!
+ private boolean annotationsOutOfDate = true;
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ JavaClass THIS = (JavaClass) o1;
+ JavaClass THAT = (JavaClass) o2;
+ return THIS.getClassName().equals(THAT.getClassName());
+ }
+
+
+ public int hashCode( Object o ) {
+ JavaClass THIS = (JavaClass) o;
+ return THIS.getClassName().hashCode();
+ }
+ };
+ /**
+ * In cases where we go ahead and create something,
+ * use the default SyntheticRepository, because we
+ * don't know any better.
+ */
+ private transient org.apache.tomcat.util.bcel.util.Repository repository = SyntheticRepository
+ .getInstance();
+
+
+ /**
+ * Constructor gets all contents as arguments.
+ *
+ * @param class_name_index Index into constant pool referencing a
+ * ConstantClass that represents this class.
+ * @param superclass_name_index Index into constant pool referencing a
+ * ConstantClass that represents this class's superclass.
+ * @param file_name File name
+ * @param major Major compiler version
+ * @param minor Minor compiler version
+ * @param access_flags Access rights defined by bit flags
+ * @param constant_pool Array of constants
+ * @param interfaces Implemented interfaces
+ * @param fields Class fields
+ * @param methods Class methods
+ * @param attributes Class attributes
+ * @param source Read from file or generated in memory?
+ */
+ public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major,
+ int minor, int access_flags, ConstantPool constant_pool, int[] interfaces,
+ Field[] fields, Method[] methods, Attribute[] attributes, byte source) {
+ if (interfaces == null) {
+ interfaces = new int[0];
+ }
+ if (attributes == null) {
+ attributes = new Attribute[0];
+ }
+ if (fields == null) {
+ fields = new Field[0];
+ }
+ if (methods == null) {
+ methods = new Method[0];
+ }
+ this.class_name_index = class_name_index;
+ this.superclass_name_index = superclass_name_index;
+ this.file_name = file_name;
+ this.major = major;
+ this.minor = minor;
+ this.access_flags = access_flags;
+ this.constant_pool = constant_pool;
+ this.interfaces = interfaces;
+ this.fields = fields;
+ this.methods = methods;
+ this.attributes = attributes;
+ annotationsOutOfDate = true;
+ this.source = source;
+ // Get source file name if available
+ for (int i = 0; i < attributes.length; i++) {
+ if (attributes[i] instanceof SourceFile) {
+ source_file_name = ((SourceFile) attributes[i]).getSourceFileName();
+ break;
+ }
+ }
+ /* According to the specification the following entries must be of type
+ * `ConstantClass' but we check that anyway via the
+ * `ConstPool.getConstant' method.
+ */
+ class_name = constant_pool.getConstantString(class_name_index, Constants.CONSTANT_Class);
+ class_name = Utility.compactClassName(class_name, false);
+ int index = class_name.lastIndexOf('.');
+ if (index < 0) {
+ package_name = "";
+ } else {
+ package_name = class_name.substring(0, index);
+ }
+ if (superclass_name_index > 0) {
+ // May be zero -> class is java.lang.Object
+ superclass_name = constant_pool.getConstantString(superclass_name_index,
+ Constants.CONSTANT_Class);
+ superclass_name = Utility.compactClassName(superclass_name, false);
+ } else {
+ superclass_name = "java.lang.Object";
+ }
+ interface_names = new String[interfaces.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class);
+ interface_names[i] = Utility.compactClassName(str, false);
+ }
+ }
+
+
+ /**
+ * Constructor gets all contents as arguments.
+ *
+ * @param class_name_index Class name
+ * @param superclass_name_index Superclass name
+ * @param file_name File name
+ * @param major Major compiler version
+ * @param minor Minor compiler version
+ * @param access_flags Access rights defined by bit flags
+ * @param constant_pool Array of constants
+ * @param interfaces Implemented interfaces
+ * @param fields Class fields
+ * @param methods Class methods
+ * @param attributes Class attributes
+ */
+ public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major,
+ int minor, int access_flags, ConstantPool constant_pool, int[] interfaces,
+ Field[] fields, Method[] methods, Attribute[] attributes) {
+ this(class_name_index, superclass_name_index, file_name, major, minor, access_flags,
+ constant_pool, interfaces, fields, methods, attributes, HEAP);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitJavaClass(this);
+ }
+
+
+ /* Print debug information depending on `JavaClass.debug'
+ */
+ static final void Debug( String str ) {
+ if (debug) {
+ System.out.println(str);
+ }
+ }
+
+
+ /**
+ * Dump class to a file.
+ *
+ * @param file Output file
+ * @throws IOException
+ */
+ public void dump( File file ) throws IOException {
+ String parent = file.getParent();
+ if (parent != null) {
+ File dir = new File(parent);
+ dir.mkdirs();
+ }
+ DataOutputStream dos = null;
+ try {
+ dos = new DataOutputStream(new FileOutputStream(file));
+ dump(dos);
+ } finally {
+ if (dos != null) {
+ dos.close();
+ }
+ }
+ }
+
+
+ /**
+ * Dump class to a file named file_name.
+ *
+ * @param _file_name Output file name
+ * @exception IOException
+ */
+ public void dump( String _file_name ) throws IOException {
+ dump(new File(_file_name));
+ }
+
+
+ /**
+ * @return class in binary format
+ */
+ public byte[] getBytes() {
+ ByteArrayOutputStream s = new ByteArrayOutputStream();
+ DataOutputStream ds = new DataOutputStream(s);
+ try {
+ dump(ds);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ ds.close();
+ } catch (IOException e2) {
+ e2.printStackTrace();
+ }
+ }
+ return s.toByteArray();
+ }
+
+
+ /**
+ * Dump Java class to output stream in binary format.
+ *
+ * @param file Output stream
+ * @exception IOException
+ */
+ public void dump( OutputStream file ) throws IOException {
+ dump(new DataOutputStream(file));
+ }
+
+
+ /**
+ * Dump Java class to output stream in binary format.
+ *
+ * @param file Output stream
+ * @exception IOException
+ */
+ public void dump( DataOutputStream file ) throws IOException {
+ file.writeInt(0xcafebabe);
+ file.writeShort(minor);
+ file.writeShort(major);
+ constant_pool.dump(file);
+ file.writeShort(access_flags);
+ file.writeShort(class_name_index);
+ file.writeShort(superclass_name_index);
+ file.writeShort(interfaces.length);
+ for (int i = 0; i < interfaces.length; i++) {
+ file.writeShort(interfaces[i]);
+ }
+ file.writeShort(fields.length);
+ for (int i = 0; i < fields.length; i++) {
+ fields[i].dump(file);
+ }
+ file.writeShort(methods.length);
+ for (int i = 0; i < methods.length; i++) {
+ methods[i].dump(file);
+ }
+ if (attributes != null) {
+ file.writeShort(attributes.length);
+ for (int i = 0; i < attributes.length; i++) {
+ attributes[i].dump(file);
+ }
+ } else {
+ file.writeShort(0);
+ }
+ file.flush();
+ }
+
+
+ /**
+ * @return Attributes of the class.
+ */
+ public Attribute[] getAttributes() {
+ return attributes;
+ }
+
+ public AnnotationEntry[] getAnnotationEntries() {
+ if (annotationsOutOfDate) {
+ // Find attributes that contain annotation data
+ Attribute[] attrs = getAttributes();
+ List accumulatedAnnotations = new ArrayList();
+ for (int i = 0; i < attrs.length; i++) {
+ Attribute attribute = attrs[i];
+ if (attribute instanceof Annotations) {
+ Annotations runtimeAnnotations = (Annotations)attribute;
+ for(int j = 0; j < runtimeAnnotations.getAnnotationEntries().length; j++)
+ accumulatedAnnotations.add(runtimeAnnotations.getAnnotationEntries()[j]);
+ }
+ }
+ annotations = (AnnotationEntry[])accumulatedAnnotations.toArray(new AnnotationEntry[accumulatedAnnotations.size()]);
+ annotationsOutOfDate = false;
+ }
+ return annotations;
+ }
+ /**
+ * @return Class name.
+ */
+ public String getClassName() {
+ return class_name;
+ }
+
+
+ /**
+ * @return Package name.
+ */
+ public String getPackageName() {
+ return package_name;
+ }
+
+
+ /**
+ * @return Class name index.
+ */
+ public int getClassNameIndex() {
+ return class_name_index;
+ }
+
+
+ /**
+ * @return Constant pool.
+ */
+ public ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @return Fields, i.e., variables of the class. Like the JVM spec
+ * mandates for the classfile format, these fields are those specific to
+ * this class, and not those of the superclass or superinterfaces.
+ */
+ public Field[] getFields() {
+ return fields;
+ }
+
+
+ /**
+ * @return File name of class, aka SourceFile attribute value
+ */
+ public String getFileName() {
+ return file_name;
+ }
+
+
+ /**
+ * @return Names of implemented interfaces.
+ */
+ public String[] getInterfaceNames() {
+ return interface_names;
+ }
+
+
+ /**
+ * @return Indices in constant pool of implemented interfaces.
+ */
+ public int[] getInterfaceIndices() {
+ return interfaces;
+ }
+
+
+ /**
+ * @return Major number of class file version.
+ */
+ public int getMajor() {
+ return major;
+ }
+
+
+ /**
+ * @return Methods of the class.
+ */
+ public Method[] getMethods() {
+ return methods;
+ }
+
+
+ /**
+ * @return A org.apache.tomcat.util.bcel.classfile.Method corresponding to
+ * java.lang.reflect.Method if any
+ */
+ public Method getMethod( java.lang.reflect.Method m ) {
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ if (m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers())
+ && Type.getSignature(m).equals(method.getSignature())) {
+ return method;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @return Minor number of class file version.
+ */
+ public int getMinor() {
+ return minor;
+ }
+
+
+ /**
+ * @return sbsolute path to file where this class was read from
+ */
+ public String getSourceFileName() {
+ return source_file_name;
+ }
+
+
+ /**
+ * @return Superclass name.
+ */
+ public String getSuperclassName() {
+ return superclass_name;
+ }
+
+
+ /**
+ * @return Class name index.
+ */
+ public int getSuperclassNameIndex() {
+ return superclass_name_index;
+ }
+
+ static {
+ // Debugging ... on/off
+ debug = Boolean.getBoolean("JavaClass.debug");
+ // Get path separator either / or \ usually
+ String _sep = System.getProperty("file.separator");
+ if (_sep != null) {
+ try {
+ JavaClass.sep = _sep.charAt(0);
+ } catch (StringIndexOutOfBoundsException e) {
+ } // Never reached
+ }
+ }
+
+
+ /**
+ * @param attributes .
+ */
+ public void setAttributes( Attribute[] attributes ) {
+ this.attributes = attributes;
+ }
+
+
+ /**
+ * @param class_name .
+ */
+ public void setClassName( String class_name ) {
+ this.class_name = class_name;
+ }
+
+
+ /**
+ * @param class_name_index .
+ */
+ public void setClassNameIndex( int class_name_index ) {
+ this.class_name_index = class_name_index;
+ }
+
+
+ /**
+ * @param constant_pool .
+ */
+ public void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * @param fields .
+ */
+ public void setFields( Field[] fields ) {
+ this.fields = fields;
+ }
+
+
+ /**
+ * Set File name of class, aka SourceFile attribute value
+ */
+ public void setFileName( String file_name ) {
+ this.file_name = file_name;
+ }
+
+
+ /**
+ * @param interface_names .
+ */
+ public void setInterfaceNames( String[] interface_names ) {
+ this.interface_names = interface_names;
+ }
+
+
+ /**
+ * @param interfaces .
+ */
+ public void setInterfaces( int[] interfaces ) {
+ this.interfaces = interfaces;
+ }
+
+
+ /**
+ * @param major .
+ */
+ public void setMajor( int major ) {
+ this.major = major;
+ }
+
+
+ /**
+ * @param methods .
+ */
+ public void setMethods( Method[] methods ) {
+ this.methods = methods;
+ }
+
+
+ /**
+ * @param minor .
+ */
+ public void setMinor( int minor ) {
+ this.minor = minor;
+ }
+
+
+ /**
+ * Set absolute path to file this class was read from.
+ */
+ public void setSourceFileName( String source_file_name ) {
+ this.source_file_name = source_file_name;
+ }
+
+
+ /**
+ * @param superclass_name .
+ */
+ public void setSuperclassName( String superclass_name ) {
+ this.superclass_name = superclass_name;
+ }
+
+
+ /**
+ * @param superclass_name_index .
+ */
+ public void setSuperclassNameIndex( int superclass_name_index ) {
+ this.superclass_name_index = superclass_name_index;
+ }
+
+
+ /**
+ * @return String representing class contents.
+ */
+ public String toString() {
+ String access = Utility.accessToString(access_flags, true);
+ access = access.equals("") ? "" : (access + " ");
+ StringBuffer buf = new StringBuffer(128);
+ buf.append(access).append(Utility.classOrInterface(access_flags)).append(" ").append(
+ class_name).append(" extends ").append(
+ Utility.compactClassName(superclass_name, false)).append('\n');
+ int size = interfaces.length;
+ if (size > 0) {
+ buf.append("implements\t\t");
+ for (int i = 0; i < size; i++) {
+ buf.append(interface_names[i]);
+ if (i < size - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append('\n');
+ }
+ buf.append("filename\t\t").append(file_name).append('\n');
+ buf.append("compiled from\t\t").append(source_file_name).append('\n');
+ buf.append("compiler version\t").append(major).append(".").append(minor).append('\n');
+ buf.append("access flags\t\t").append(access_flags).append('\n');
+ buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n");
+ buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n");
+ if (attributes.length > 0) {
+ buf.append("\nAttribute(s):\n");
+ for (int i = 0; i < attributes.length; i++) {
+ buf.append(indent(attributes[i]));
+ }
+ }
+ AnnotationEntry[] annotations = getAnnotationEntries();
+ if (annotations!=null && annotations.length>0) {
+ buf.append("\nAnnotation(s):\n");
+ for (int i=0; i<annotations.length; i++)
+ buf.append(indent(annotations[i]));
+ }
+ if (fields.length > 0) {
+ buf.append("\n").append(fields.length).append(" fields:\n");
+ for (int i = 0; i < fields.length; i++) {
+ buf.append("\t").append(fields[i]).append('\n');
+ }
+ }
+ if (methods.length > 0) {
+ buf.append("\n").append(methods.length).append(" methods:\n");
+ for (int i = 0; i < methods.length; i++) {
+ buf.append("\t").append(methods[i]).append('\n');
+ }
+ }
+ return buf.toString();
+ }
+
+
+ private static final String indent( Object obj ) {
+ StringTokenizer tok = new StringTokenizer(obj.toString(), "\n");
+ StringBuffer buf = new StringBuffer();
+ while (tok.hasMoreTokens()) {
+ buf.append("\t").append(tok.nextToken()).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this class
+ */
+ public JavaClass copy() {
+ JavaClass c = null;
+ try {
+ c = (JavaClass) clone();
+ c.constant_pool = constant_pool.copy();
+ c.interfaces = (int[]) interfaces.clone();
+ c.interface_names = (String[]) interface_names.clone();
+ c.fields = new Field[fields.length];
+ for (int i = 0; i < fields.length; i++) {
+ c.fields[i] = fields[i].copy(c.constant_pool);
+ }
+ c.methods = new Method[methods.length];
+ for (int i = 0; i < methods.length; i++) {
+ c.methods[i] = methods[i].copy(c.constant_pool);
+ }
+ c.attributes = new Attribute[attributes.length];
+ for (int i = 0; i < attributes.length; i++) {
+ c.attributes[i] = attributes[i].copy(c.constant_pool);
+ }
+ } catch (CloneNotSupportedException e) {
+ }
+ return c;
+ }
+
+
+ public final boolean isSuper() {
+ return (access_flags & Constants.ACC_SUPER) != 0;
+ }
+
+
+ public final boolean isClass() {
+ return (access_flags & Constants.ACC_INTERFACE) == 0;
+ }
+
+ public final boolean isAnonymous() {
+ computeNestedTypeStatus();
+ return this.isAnonymous;
+ }
+
+ public final boolean isNested() {
+ computeNestedTypeStatus();
+ return this.isNested;
+ }
+
+ private final void computeNestedTypeStatus() {
+ if (computedNestedTypeStatus) return;
+ for (int i = 0; i < this.attributes.length; i++) {
+ if (this.attributes[i] instanceof InnerClasses) {
+ InnerClass[] innerClasses = ((InnerClasses) this.attributes[i]).getInnerClasses();
+ for (int j = 0; j < innerClasses.length; j++) {
+ boolean innerClassAttributeRefersToMe = false;
+ String inner_class_name = constant_pool.getConstantString(innerClasses[j].getInnerClassIndex(),
+ Constants.CONSTANT_Class);
+ inner_class_name = Utility.compactClassName(inner_class_name);
+ if (inner_class_name.equals(getClassName())) {
+ innerClassAttributeRefersToMe = true;
+ }
+ if (innerClassAttributeRefersToMe) {
+ this.isNested = true;
+ if (innerClasses[j].getInnerNameIndex() == 0) {
+ this.isAnonymous = true;
+ }
+ }
+ }
+ }
+ }
+ this.computedNestedTypeStatus = true;
+ }
+
+
+ /** @return returns either HEAP (generated), FILE, or ZIP
+ */
+ public final byte getSource() {
+ return source;
+ }
+
+
+ /********************* New repository functionality *********************/
+ /**
+ * Gets the ClassRepository which holds its definition. By default
+ * this is the same as SyntheticRepository.getInstance();
+ */
+ public org.apache.tomcat.util.bcel.util.Repository getRepository() {
+ return repository;
+ }
+
+
+ /**
+ * Sets the ClassRepository which loaded the JavaClass.
+ * Should be called immediately after parsing is done.
+ */
+ public void setRepository( org.apache.tomcat.util.bcel.util.Repository repository ) {
+ this.repository = repository;
+ }
+
+
+ /** Equivalent to runtime "instanceof" operator.
+ *
+ * @return true if this JavaClass is derived from the super class
+ * @throws ClassNotFoundException if superclasses or superinterfaces
+ * of this object can't be found
+ */
+ public final boolean instanceOf( JavaClass super_class ) throws ClassNotFoundException {
+ if (this.equals(super_class)) {
+ return true;
+ }
+ JavaClass[] super_classes = getSuperClasses();
+ for (int i = 0; i < super_classes.length; i++) {
+ if (super_classes[i].equals(super_class)) {
+ return true;
+ }
+ }
+ if (super_class.isInterface()) {
+ return implementationOf(super_class);
+ }
+ return false;
+ }
+
+
+ /**
+ * @return true, if this class is an implementation of interface inter
+ * @throws ClassNotFoundException if superclasses or superinterfaces
+ * of this class can't be found
+ */
+ public boolean implementationOf( JavaClass inter ) throws ClassNotFoundException {
+ if (!inter.isInterface()) {
+ throw new IllegalArgumentException(inter.getClassName() + " is no interface");
+ }
+ if (this.equals(inter)) {
+ return true;
+ }
+ JavaClass[] super_interfaces = getAllInterfaces();
+ for (int i = 0; i < super_interfaces.length; i++) {
+ if (super_interfaces[i].equals(inter)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * @return the superclass for this JavaClass object, or null if this
+ * is java.lang.Object
+ * @throws ClassNotFoundException if the superclass can't be found
+ */
+ public JavaClass getSuperClass() throws ClassNotFoundException {
+ if ("java.lang.Object".equals(getClassName())) {
+ return null;
+ }
+ return repository.loadClass(getSuperclassName());
+ }
+
+
+ /**
+ * @return list of super classes of this class in ascending order, i.e.,
+ * java.lang.Object is always the last element
+ * @throws ClassNotFoundException if any of the superclasses can't be found
+ */
+ public JavaClass[] getSuperClasses() throws ClassNotFoundException {
+ JavaClass clazz = this;
+ List allSuperClasses = new ArrayList();
+ for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
+ allSuperClasses.add(clazz);
+ }
+ return (JavaClass[]) allSuperClasses.toArray(new JavaClass[allSuperClasses.size()]);
+ }
+
+
+ /**
+ * Get interfaces directly implemented by this JavaClass.
+ */
+ public JavaClass[] getInterfaces() throws ClassNotFoundException {
+ String[] _interfaces = getInterfaceNames();
+ JavaClass[] classes = new JavaClass[_interfaces.length];
+ for (int i = 0; i < _interfaces.length; i++) {
+ classes[i] = repository.loadClass(_interfaces[i]);
+ }
+ return classes;
+ }
+
+
+ /**
+ * Get all interfaces implemented by this JavaClass (transitively).
+ */
+ public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
+ ClassQueue queue = new ClassQueue();
+ Set allInterfaces = new TreeSet();
+ queue.enqueue(this);
+ while (!queue.empty()) {
+ JavaClass clazz = queue.dequeue();
+ JavaClass souper = clazz.getSuperClass();
+ JavaClass[] _interfaces = clazz.getInterfaces();
+ if (clazz.isInterface()) {
+ allInterfaces.add(clazz);
+ } else {
+ if (souper != null) {
+ queue.enqueue(souper);
+ }
+ }
+ for (int i = 0; i < _interfaces.length; i++) {
+ queue.enqueue(_interfaces[i]);
+ }
+ }
+ return (JavaClass[]) allInterfaces.toArray(new JavaClass[allInterfaces.size()]);
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two JavaClass objects are said to be equal when
+ * their class names are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return the natural ordering of two JavaClasses.
+ * This ordering is based on the class name
+ */
+ public int compareTo( Object obj ) {
+ return getClassName().compareTo(((JavaClass) obj).getClassName());
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the class name.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * This class represents a (PC offset, line number) pair, i.e., a line number in
+ * the source that corresponds to a relative address in the byte code. This
+ * is used for debugging purposes.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see LineNumberTable
+ */
+public final class LineNumber implements Cloneable, Node, Serializable {
+
+ private int start_pc; // Program Counter (PC) corresponds to line
+ private int line_number; // number in source file
+
+
+ /**
+ * Initialize from another object.
+ */
+ public LineNumber(LineNumber c) {
+ this(c.getStartPC(), c.getLineNumber());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ LineNumber(DataInput file) throws IOException {
+ this(file.readUnsignedShort(), file.readUnsignedShort());
+ }
+
+
+ /**
+ * @param start_pc Program Counter (PC) corresponds to
+ * @param line_number line number in source file
+ */
+ public LineNumber(int start_pc, int line_number) {
+ this.start_pc = start_pc;
+ this.line_number = line_number;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLineNumber(this);
+ }
+
+
+ /**
+ * Dump line number/pc pair to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(start_pc);
+ file.writeShort(line_number);
+ }
+
+
+ /**
+ * @return Corresponding source line
+ */
+ public final int getLineNumber() {
+ return line_number;
+ }
+
+
+ /**
+ * @return PC in code
+ */
+ public final int getStartPC() {
+ return start_pc;
+ }
+
+
+ /**
+ * @param line_number the source line number
+ */
+ public final void setLineNumber( int line_number ) {
+ this.line_number = line_number;
+ }
+
+
+ /**
+ * @param start_pc the pc for this line number
+ */
+ public final void setStartPC( int start_pc ) {
+ this.start_pc = start_pc;
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return "LineNumber(" + start_pc + ", " + line_number + ")";
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public LineNumber copy() {
+ try {
+ return (LineNumber) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a table of line numbers for debugging
+ * purposes. This attribute is used by the <em>Code</em> attribute. It
+ * contains pairs of PCs and line numbers.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ * @see LineNumber
+ */
+public final class LineNumberTable extends Attribute {
+
+ private int line_number_table_length;
+ private LineNumber[] line_number_table; // Table of line/numbers pairs
+
+
+ /*
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public LineNumberTable(LineNumberTable c) {
+ this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool());
+ }
+
+
+ /*
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param line_number_table Table of line/numbers pairs
+ * @param constant_pool Array of constants
+ */
+ public LineNumberTable(int name_index, int length, LineNumber[] line_number_table,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool);
+ setLineNumberTable(line_number_table);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ LineNumberTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (LineNumber[]) null, constant_pool);
+ line_number_table_length = (file.readUnsignedShort());
+ line_number_table = new LineNumber[line_number_table_length];
+ for (int i = 0; i < line_number_table_length; i++) {
+ line_number_table[i] = new LineNumber(file);
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLineNumberTable(this);
+ }
+
+
+ /**
+ * Dump line number table attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(line_number_table_length);
+ for (int i = 0; i < line_number_table_length; i++) {
+ line_number_table[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Array of (pc offset, line number) pairs.
+ */
+ public final LineNumber[] getLineNumberTable() {
+ return line_number_table;
+ }
+
+
+ /**
+ * @param line_number_table the line number entries for this table
+ */
+ public final void setLineNumberTable( LineNumber[] line_number_table ) {
+ this.line_number_table = line_number_table;
+ line_number_table_length = (line_number_table == null) ? 0 : line_number_table.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+ StringBuffer line = new StringBuffer();
+ String newLine = System.getProperty("line.separator", "\n");
+ for (int i = 0; i < line_number_table_length; i++) {
+ line.append(line_number_table[i].toString());
+ if (i < line_number_table_length - 1) {
+ line.append(", ");
+ }
+ if (line.length() > 72) {
+ line.append(newLine);
+ buf.append(line.toString());
+ line.setLength(0);
+ }
+ }
+ buf.append(line);
+ return buf.toString();
+ }
+
+
+ /**
+ * Map byte code positions to source code lines.
+ *
+ * @param pos byte code offset
+ * @return corresponding line in source code
+ */
+ public int getSourceLine( int pos ) {
+ int l = 0, r = line_number_table_length - 1;
+ if (r < 0) {
+ return -1;
+ }
+ int min_index = -1, min = -1;
+ /* Do a binary search since the array is ordered.
+ */
+ do {
+ int i = (l + r) / 2;
+ int j = line_number_table[i].getStartPC();
+ if (j == pos) {
+ return line_number_table[i].getLineNumber();
+ } else if (pos < j) {
+ r = i - 1;
+ } else {
+ l = i + 1;
+ }
+ /* If exact match can't be found (which is the most common case)
+ * return the line number that corresponds to the greatest index less
+ * than pos.
+ */
+ if (j < pos && j > min) {
+ min = j;
+ min_index = i;
+ }
+ } while (l <= r);
+ /* It's possible that we did not find any valid entry for the bytecode
+ * offset we were looking for.
+ */
+ if (min_index < 0) {
+ return -1;
+ }
+ return line_number_table[min_index].getLineNumber();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ LineNumberTable c = (LineNumberTable) clone();
+ c.line_number_table = new LineNumber[line_number_table_length];
+ for (int i = 0; i < line_number_table_length; i++) {
+ c.line_number_table[i] = line_number_table[i].copy();
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+
+
+ public final int getTableLength() {
+ return line_number_table_length;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a local variable within a method. It contains its
+ * scope, name, signature and index on the method's frame.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see LocalVariableTable
+ */
+public final class LocalVariable implements Constants, Cloneable, Node, Serializable {
+
+ private int start_pc; // Range in which the variable is valid
+ private int length;
+ private int name_index; // Index in constant pool of variable name
+ private int signature_index; // Index of variable signature
+ private int index; /* Variable is `index'th local variable on
+ * this method's frame.
+ */
+ private ConstantPool constant_pool;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public LocalVariable(LocalVariable c) {
+ this(c.getStartPC(), c.getLength(), c.getNameIndex(), c.getSignatureIndex(), c.getIndex(),
+ c.getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ LocalVariable(DataInput file, ConstantPool constant_pool) throws IOException {
+ this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
+ .readUnsignedShort(), file.readUnsignedShort(), constant_pool);
+ }
+
+
+ /**
+ * @param start_pc Range in which the variable
+ * @param length ... is valid
+ * @param name_index Index in constant pool of variable name
+ * @param signature_index Index of variable's signature
+ * @param index Variable is `index'th local variable on the method's frame
+ * @param constant_pool Array of constants
+ */
+ public LocalVariable(int start_pc, int length, int name_index, int signature_index, int index,
+ ConstantPool constant_pool) {
+ this.start_pc = start_pc;
+ this.length = length;
+ this.name_index = name_index;
+ this.signature_index = signature_index;
+ this.index = index;
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLocalVariable(this);
+ }
+
+
+ /**
+ * Dump local variable to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(start_pc);
+ file.writeShort(length);
+ file.writeShort(name_index);
+ file.writeShort(signature_index);
+ file.writeShort(index);
+ }
+
+
+ /**
+ * @return Constant pool used by this object.
+ */
+ public final ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @return Variable is valid within getStartPC() .. getStartPC()+getLength()
+ */
+ public final int getLength() {
+ return length;
+ }
+
+
+ /**
+ * @return Variable name.
+ */
+ public final String getName() {
+ ConstantUtf8 c;
+ c = (ConstantUtf8) constant_pool.getConstant(name_index, CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return Index in constant pool of variable name.
+ */
+ public final int getNameIndex() {
+ return name_index;
+ }
+
+
+ /**
+ * @return Signature.
+ */
+ public final String getSignature() {
+ ConstantUtf8 c;
+ c = (ConstantUtf8) constant_pool.getConstant(signature_index, CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return Index in constant pool of variable signature.
+ */
+ public final int getSignatureIndex() {
+ return signature_index;
+ }
+
+
+ /**
+ * @return index of register where variable is stored
+ */
+ public final int getIndex() {
+ return index;
+ }
+
+
+ /**
+ * @return Start of range where he variable is valid
+ */
+ public final int getStartPC() {
+ return start_pc;
+ }
+
+
+ /**
+ * @param constant_pool Constant pool to be used for this object.
+ */
+ public final void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * @param length the length of this local variable
+ */
+ public final void setLength( int length ) {
+ this.length = length;
+ }
+
+
+ /**
+ * @param name_index the index into the constant pool for the name of this variable
+ */
+ public final void setNameIndex( int name_index ) {
+ this.name_index = name_index;
+ }
+
+
+ /**
+ * @param signature_index the index into the constant pool for the signature of this variable
+ */
+ public final void setSignatureIndex( int signature_index ) {
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * @param index the index in the local variable table of this variable
+ */
+ public final void setIndex( int index ) {
+ this.index = index;
+ }
+
+
+ /**
+ * @param start_pc Specify range where the local variable is valid.
+ */
+ public final void setStartPC( int start_pc ) {
+ this.start_pc = start_pc;
+ }
+
+
+ /**
+ * @return string representation.
+ */
+ public final String toString() {
+ String name = getName(), signature = Utility.signatureToString(getSignature());
+ return "LocalVariable(start_pc = " + start_pc + ", length = " + length + ", index = "
+ + index + ":" + signature + " " + name + ")";
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public LocalVariable copy() {
+ try {
+ return (LocalVariable) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents colection of local variables in a
+ * method. This attribute is contained in the <em>Code</em> attribute.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ * @see LocalVariable
+ */
+public class LocalVariableTable extends Attribute {
+
+ private int local_variable_table_length; // Table of local
+ private LocalVariable[] local_variable_table; // variables
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public LocalVariableTable(LocalVariableTable c) {
+ this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to `LocalVariableTable'
+ * @param length Content length in bytes
+ * @param local_variable_table Table of local variables
+ * @param constant_pool Array of constants
+ */
+ public LocalVariableTable(int name_index, int length, LocalVariable[] local_variable_table,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool);
+ setLocalVariableTable(local_variable_table);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (LocalVariable[]) null, constant_pool);
+ local_variable_table_length = (file.readUnsignedShort());
+ local_variable_table = new LocalVariable[local_variable_table_length];
+ for (int i = 0; i < local_variable_table_length; i++) {
+ local_variable_table[i] = new LocalVariable(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLocalVariableTable(this);
+ }
+
+
+ /**
+ * Dump local variable table attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(local_variable_table_length);
+ for (int i = 0; i < local_variable_table_length; i++) {
+ local_variable_table[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Array of local variables of method.
+ */
+ public final LocalVariable[] getLocalVariableTable() {
+ return local_variable_table;
+ }
+
+
+ /**
+ * @return first matching variable using index
+ *
+ * @param index the variable slot
+ *
+ * @return the first LocalVariable that matches the slot or null if not found
+ *
+ * @deprecated since 5.2 because multiple variables can share the
+ * same slot, use getLocalVariable(int index, int pc) instead.
+ */
+ public final LocalVariable getLocalVariable( int index ) {
+ for (int i = 0; i < local_variable_table_length; i++) {
+ if (local_variable_table[i].getIndex() == index) {
+ return local_variable_table[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @return matching variable using index when variable is used at supplied pc
+ *
+ * @param index the variable slot
+ * @param pc the current pc that this variable is alive
+ *
+ * @return the LocalVariable that matches or null if not found
+ */
+ public final LocalVariable getLocalVariable( int index, int pc ) {
+ for (int i = 0; i < local_variable_table_length; i++) {
+ if (local_variable_table[i].getIndex() == index) {
+ int start_pc = local_variable_table[i].getStartPC();
+ int end_pc = start_pc + local_variable_table[i].getLength();
+ if ((pc >= start_pc) && (pc <= end_pc)) {
+ return local_variable_table[i];
+ }
+ }
+ }
+ return null;
+ }
+
+
+ public final void setLocalVariableTable( LocalVariable[] local_variable_table ) {
+ this.local_variable_table = local_variable_table;
+ local_variable_table_length = (local_variable_table == null)
+ ? 0
+ : local_variable_table.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < local_variable_table_length; i++) {
+ buf.append(local_variable_table[i].toString());
+ if (i < local_variable_table_length - 1) {
+ buf.append('\n');
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ LocalVariableTable c = (LocalVariableTable) clone();
+ c.local_variable_table = new LocalVariable[local_variable_table_length];
+ for (int i = 0; i < local_variable_table_length; i++) {
+ c.local_variable_table[i] = local_variable_table[i].copy();
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+
+
+ public final int getTableLength() {
+ return local_variable_table_length;
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation
+ *
+ * All rights reserved.
+ * This program and the accompanying materials are made available
+ * under the terms of the Common Public License v1.0
+ * which accompanies this distribution and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * Heavily based on LocalVariableTable
+ * ******************************************************************/
+package org.apache.tomcat.util.bcel.classfile;
+
+
+import org.apache.tomcat.util.bcel.Constants;
+import java.io.*;
+
+// The new table is used when generic types are about...
+
+//LocalVariableTable_attribute {
+// u2 attribute_name_index;
+// u4 attribute_length;
+// u2 local_variable_table_length;
+// { u2 start_pc;
+// u2 length;
+// u2 name_index;
+// u2 descriptor_index;
+// u2 index;
+// } local_variable_table[local_variable_table_length];
+// }
+
+//LocalVariableTypeTable_attribute {
+// u2 attribute_name_index;
+// u4 attribute_length;
+// u2 local_variable_type_table_length;
+// {
+// u2 start_pc;
+// u2 length;
+// u2 name_index;
+// u2 signature_index;
+// u2 index;
+// } local_variable_type_table[local_variable_type_table_length];
+// }
+// J5TODO: Needs some testing !
+public class LocalVariableTypeTable extends Attribute {
+ private int local_variable_type_table_length; // Table of local
+ private LocalVariable[] local_variable_type_table; // variables
+
+ public LocalVariableTypeTable(LocalVariableTypeTable c) {
+ this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(),
+ c.getConstantPool());
+ }
+
+ public LocalVariableTypeTable(int name_index, int length,
+ LocalVariable[] local_variable_table,
+ ConstantPool constant_pool)
+ {
+ super(Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool);
+ setLocalVariableTable(local_variable_table);
+ }
+
+ LocalVariableTypeTable(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException {
+ this(nameIdx, len, (LocalVariable[])null, cpool);
+
+ local_variable_type_table_length = (dis.readUnsignedShort());
+ local_variable_type_table = new LocalVariable[local_variable_type_table_length];
+
+ for(int i=0; i < local_variable_type_table_length; i++)
+ local_variable_type_table[i] = new LocalVariable(dis, cpool);
+ }
+
+ public void accept(Visitor v) {
+ v.visitLocalVariableTypeTable(this);
+ }
+
+ public final void dump(DataOutputStream file) throws IOException
+ {
+ super.dump(file);
+ file.writeShort(local_variable_type_table_length);
+ for(int i=0; i < local_variable_type_table_length; i++)
+ local_variable_type_table[i].dump(file);
+ }
+
+ public final LocalVariable[] getLocalVariableTypeTable() {
+ return local_variable_type_table;
+ }
+
+ public final LocalVariable getLocalVariable(int index) {
+ for(int i=0; i < local_variable_type_table_length; i++)
+ if(local_variable_type_table[i].getIndex() == index)
+ return local_variable_type_table[i];
+
+ return null;
+ }
+
+ public final void setLocalVariableTable(LocalVariable[] local_variable_table)
+ {
+ this.local_variable_type_table = local_variable_table;
+ local_variable_type_table_length = (local_variable_table == null)? 0 :
+ local_variable_table.length;
+ }
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer();
+
+ for(int i=0; i < local_variable_type_table_length; i++) {
+ buf.append(local_variable_type_table[i].toString());
+
+ if(i < local_variable_type_table_length - 1) buf.append('\n');
+ }
+
+ return buf.toString();
+ }
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy(ConstantPool constant_pool) {
+ LocalVariableTypeTable c = (LocalVariableTypeTable)clone();
+
+ c.local_variable_type_table = new LocalVariable[local_variable_type_table_length];
+ for(int i=0; i < local_variable_type_table_length; i++)
+ c.local_variable_type_table[i] = local_variable_type_table[i].copy();
+
+ c.constant_pool = constant_pool;
+ return c;
+ }
+
+ public final int getTableLength() { return local_variable_type_table_length; }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.generic.Type;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * This class represents the method info structure, i.e., the representation
+ * for a method in the class. See JVM specification for details.
+ * A method has access flags, a name, a signature and a number of attributes.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class Method extends FieldOrMethod {
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ Method THIS = (Method) o1;
+ Method THAT = (Method) o2;
+ return THIS.getName().equals(THAT.getName())
+ && THIS.getSignature().equals(THAT.getSignature());
+ }
+
+
+ public int hashCode( Object o ) {
+ Method THIS = (Method) o;
+ return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ }
+ };
+
+
+ /**
+ * Empty constructor, all attributes have to be defined via `setXXX'
+ * methods. Use at your own risk.
+ */
+ public Method() {
+ }
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public Method(Method c) {
+ super(c);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ Method(DataInputStream file, ConstantPool constant_pool) throws IOException,
+ ClassFormatException {
+ super(file, constant_pool);
+ }
+
+
+ /**
+ * @param access_flags Access rights of method
+ * @param name_index Points to field name in constant pool
+ * @param signature_index Points to encoded signature
+ * @param attributes Collection of attributes
+ * @param constant_pool Array of constants
+ */
+ public Method(int access_flags, int name_index, int signature_index, Attribute[] attributes,
+ ConstantPool constant_pool) {
+ super(access_flags, name_index, signature_index, attributes, constant_pool);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitMethod(this);
+ }
+
+
+ /**
+ * @return Code attribute of method, if any
+ */
+ public final Code getCode() {
+ for (int i = 0; i < attributes_count; i++) {
+ if (attributes[i] instanceof Code) {
+ return (Code) attributes[i];
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * @return ExceptionTable attribute of method, if any, i.e., list all
+ * exceptions the method may throw not exception handlers!
+ */
+ public final ExceptionTable getExceptionTable() {
+ for (int i = 0; i < attributes_count; i++) {
+ if (attributes[i] instanceof ExceptionTable) {
+ return (ExceptionTable) attributes[i];
+ }
+ }
+ return null;
+ }
+
+
+ /** @return LocalVariableTable of code attribute if any, i.e. the call is forwarded
+ * to the Code atribute.
+ */
+ public final LocalVariableTable getLocalVariableTable() {
+ Code code = getCode();
+ if (code == null) {
+ return null;
+ }
+ return code.getLocalVariableTable();
+ }
+
+
+ /** @return LineNumberTable of code attribute if any, i.e. the call is forwarded
+ * to the Code atribute.
+ */
+ public final LineNumberTable getLineNumberTable() {
+ Code code = getCode();
+ if (code == null) {
+ return null;
+ }
+ return code.getLineNumberTable();
+ }
+
+
+ /**
+ * Return string representation close to declaration format,
+ * `public static void main(String[] args) throws IOException', e.g.
+ *
+ * @return String representation of the method.
+ */
+ public final String toString() {
+ ConstantUtf8 c;
+ String name, signature, access; // Short cuts to constant pool
+ StringBuffer buf;
+ access = Utility.accessToString(access_flags);
+ // Get name and signature from constant pool
+ c = (ConstantUtf8) constant_pool.getConstant(signature_index, Constants.CONSTANT_Utf8);
+ signature = c.getBytes();
+ c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8);
+ name = c.getBytes();
+ signature = Utility.methodSignatureToString(signature, name, access, true,
+ getLocalVariableTable());
+ buf = new StringBuffer(signature);
+ for (int i = 0; i < attributes_count; i++) {
+ Attribute a = attributes[i];
+ if (!((a instanceof Code) || (a instanceof ExceptionTable))) {
+ buf.append(" [").append(a.toString()).append("]");
+ }
+ }
+ ExceptionTable e = getExceptionTable();
+ if (e != null) {
+ String str = e.toString();
+ if (!str.equals("")) {
+ buf.append("\n\t\tthrows ").append(str);
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this method
+ */
+ public final Method copy( ConstantPool _constant_pool ) {
+ return (Method) copy_(_constant_pool);
+ }
+
+
+ /**
+ * @return return type of method
+ */
+ public Type getReturnType() {
+ return Type.getReturnType(getSignature());
+ }
+
+
+ /**
+ * @return array of method argument types
+ */
+ public Type[] getArgumentTypes() {
+ return Type.getArgumentTypes(getSignature());
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two method objects are said to be equal when
+ * their names and signatures are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the method's name XOR signature.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * Denote class to have an accept method();
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface Node {
+
+ public void accept( Visitor obj );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and represents a reference
+ * to a PMG attribute.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class PMGClass extends Attribute {
+
+ private int pmg_class_index, pmg_index;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public PMGClass(PMGClass c) {
+ this(c.getNameIndex(), c.getLength(), c.getPMGIndex(), c.getPMGClassIndex(), c
+ .getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ PMGClass(int name_index, int length, DataInput file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), constant_pool);
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param pmg_index index in constant pool for source file name
+ * @param pmg_class_index Index in constant pool to CONSTANT_Utf8
+ * @param constant_pool Array of constants
+ */
+ public PMGClass(int name_index, int length, int pmg_index, int pmg_class_index,
+ ConstantPool constant_pool) {
+ super(Constants.ATTR_PMG, name_index, length, constant_pool);
+ this.pmg_index = pmg_index;
+ this.pmg_class_index = pmg_class_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ System.err.println("Visiting non-standard PMGClass object");
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(pmg_index);
+ file.writeShort(pmg_class_index);
+ }
+
+
+ /**
+ * @return Index in constant pool of source file name.
+ */
+ public final int getPMGClassIndex() {
+ return pmg_class_index;
+ }
+
+
+ /**
+ * @param pmg_class_index
+ */
+ public final void setPMGClassIndex( int pmg_class_index ) {
+ this.pmg_class_index = pmg_class_index;
+ }
+
+
+ /**
+ * @return Index in constant pool of source file name.
+ */
+ public final int getPMGIndex() {
+ return pmg_index;
+ }
+
+
+ /**
+ * @param pmg_index
+ */
+ public final void setPMGIndex( int pmg_index ) {
+ this.pmg_index = pmg_index;
+ }
+
+
+ /**
+ * @return PMG name.
+ */
+ public final String getPMGName() {
+ ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(pmg_index,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return PMG class name.
+ */
+ public final String getPMGClassName() {
+ ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(pmg_class_index,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return "PMGClass(" + getPMGName() + ", " + getPMGClassName() + ")";
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ return (PMGClass) clone();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents one parameter annotation in the parameter annotation table
+ *
+ * @version $Id: ParameterAnnotationEntry
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class ParameterAnnotationEntry implements Node, Constants {
+
+ private int annotation_table_length;
+ private AnnotationEntry[] annotation_table;
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ ParameterAnnotationEntry(DataInputStream file, ConstantPool constant_pool) throws IOException {
+ annotation_table_length = (file.readUnsignedShort());
+ annotation_table = new AnnotationEntry[annotation_table_length];
+ for (int i = 0; i < annotation_table_length; i++) {
+// TODO isRuntimeVisible
+ annotation_table[i] = AnnotationEntry.read(file, constant_pool, false);
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ // v.visitParameterAnnotationEntry(this);
+ }
+
+
+ /**
+ * @return the number of annotation entries in this parameter annotation
+ */
+ public final int getNumAnnotations() {
+ return annotation_table_length;
+ }
+
+
+ /**
+ * returns the array of annotation entries in this annotation
+ */
+ public AnnotationEntry[] getAnnotationEntries() {
+ return annotation_table;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * base class for parameter annotations
+ *
+ * @version $Id: ParameterAnnotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public abstract class ParameterAnnotations extends Attribute {
+
+ private int num_parameters;
+ private ParameterAnnotationEntry[] parameter_annotation_table; // Table of parameter annotations
+
+
+ /**
+ * @param parameter_annotation_type the subclass type of the parameter annotation
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ */
+ ParameterAnnotations(byte parameter_annotation_type, int name_index, int length,
+ DataInputStream file, ConstantPool constant_pool) throws IOException {
+ this(parameter_annotation_type, name_index, length, (ParameterAnnotationEntry[]) null,
+ constant_pool);
+ num_parameters = (file.readUnsignedByte());
+ parameter_annotation_table = new ParameterAnnotationEntry[num_parameters];
+ for (int i = 0; i < num_parameters; i++) {
+ parameter_annotation_table[i] = new ParameterAnnotationEntry(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * @param parameter_annotation_type the subclass type of the parameter annotation
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param parameter_annotation_table the actual parameter annotations
+ * @param constant_pool Array of constants
+ */
+ public ParameterAnnotations(byte parameter_annotation_type, int name_index, int length,
+ ParameterAnnotationEntry[] parameter_annotation_table, ConstantPool constant_pool) {
+ super(parameter_annotation_type, name_index, length, constant_pool);
+ setParameterAnnotationTable(parameter_annotation_table);
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ // v.visitParameterAnnotation(this);
+ }
+
+
+ /**
+ * @param parameter_annotation_table the entries to set in this parameter annotation
+ */
+ public final void setParameterAnnotationTable(
+ ParameterAnnotationEntry[] parameter_annotation_table ) {
+ this.parameter_annotation_table = parameter_annotation_table;
+ num_parameters = (parameter_annotation_table == null)
+ ? 0
+ : parameter_annotation_table.length;
+ }
+
+
+ /**
+ * @return the parameter annotation entry table
+ */
+ public final ParameterAnnotationEntry[] getParameterAnnotationTable() {
+ return parameter_annotation_table;
+ }
+
+
+ /**
+ * returns the array of parameter annotation entries in this parameter annotation
+ */
+ public ParameterAnnotationEntry[] getParameterAnnotationEntries() {
+ return parameter_annotation_table;
+ }
+
+
+ /**
+ * @return the number of parameter annotation entries in this parameter annotation
+ */
+ public final int getNumParameterAnnotation() {
+ return num_parameters;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents an annotation that is represented in the class file but is not
+ * provided to the JVM.
+ *
+ * @version $Id: RuntimeInvisibleAnnotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class RuntimeInvisibleAnnotations extends Annotations
+{
+ /**
+ * @param name_index
+ * Index pointing to the name <em>Code</em>
+ * @param length
+ * Content length in bytes
+ * @param file
+ * Input stream
+ * @param constant_pool
+ * Array of constants
+ */
+ RuntimeInvisibleAnnotations(int name_index, int length,
+ DataInputStream file, ConstantPool constant_pool)
+ throws IOException
+ {
+ super(Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, name_index, length,
+ file, constant_pool, false);
+ }
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy(ConstantPool constant_pool)
+ {
+ Annotations c = (Annotations) clone();
+ return c;
+ }
+
+ public final void dump(DataOutputStream dos) throws IOException
+ {
+ super.dump(dos);
+ writeAnnotations(dos);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents a parameter annotation that is represented in the class file
+ * but is not provided to the JVM.
+ *
+ * @version $Id: RuntimeInvisibleParameterAnnotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
+
+ /**
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ */
+ RuntimeInvisibleParameterAnnotations(int name_index, int length, DataInputStream file,
+ ConstantPool constant_pool) throws IOException {
+ super(Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file,
+ constant_pool);
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool constant_pool ) {
+ Annotations c = (Annotations) clone();
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents an annotation that is represented in the class file and is
+ * provided to the JVM.
+ *
+ * @version $Id: RuntimeVisibleAnnotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class RuntimeVisibleAnnotations extends Annotations
+{
+ /**
+ * @param name_index
+ * Index pointing to the name <em>Code</em>
+ * @param length
+ * Content length in bytes
+ * @param file
+ * Input stream
+ * @param constant_pool
+ * Array of constants
+ */
+ public RuntimeVisibleAnnotations(int name_index, int length,
+ DataInputStream file, ConstantPool constant_pool)
+ throws IOException
+ {
+ super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length,
+ file, constant_pool, true);
+ }
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy(ConstantPool constant_pool)
+ {
+ Annotations c = (Annotations) clone();
+ return c;
+ }
+
+ public final void dump(DataOutputStream dos) throws IOException
+ {
+ super.dump(dos);
+ writeAnnotations(dos);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * represents a parameter annotation that is represented in the class file
+ * and is provided to the JVM.
+ *
+ * @version $Id: RuntimeVisibleParameterAnnotations
+ * @author <A HREF="mailto:dbrosius@qis.net">D. Brosius</A>
+ * @since 5.3
+ */
+public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
+
+ /**
+ * @param name_index Index pointing to the name <em>Code</em>
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ */
+ RuntimeVisibleParameterAnnotations(int name_index, int length, DataInputStream file,
+ ConstantPool constant_pool) throws IOException {
+ super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file,
+ constant_pool);
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool constant_pool ) {
+ Annotations c = (Annotations) clone();
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and represents a reference
+ * to a GJ attribute.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class Signature extends Attribute {
+
+ private int signature_index;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public Signature(Signature c) {
+ this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ Signature(int name_index, int length, DataInput file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, file.readUnsignedShort(), constant_pool);
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param signature_index Index in constant pool to CONSTANT_Utf8
+ * @param constant_pool Array of constants
+ */
+ public Signature(int name_index, int length, int signature_index, ConstantPool constant_pool) {
+ super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool);
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ //System.err.println("Visiting non-standard Signature object");
+ v.visitSignature(this);
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(signature_index);
+ }
+
+
+ /**
+ * @return Index in constant pool of source file name.
+ */
+ public final int getSignatureIndex() {
+ return signature_index;
+ }
+
+
+ /**
+ * @param signature_index the index info the constant pool of this signature
+ */
+ public final void setSignatureIndex( int signature_index ) {
+ this.signature_index = signature_index;
+ }
+
+
+ /**
+ * @return GJ signature.
+ */
+ public final String getSignature() {
+ ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(signature_index,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ /**
+ * Extends ByteArrayInputStream to make 'unreading' chars possible.
+ */
+ private static final class MyByteArrayInputStream extends ByteArrayInputStream {
+
+ MyByteArrayInputStream(String data) {
+ super(data.getBytes());
+ }
+
+
+ final int mark() {
+ return pos;
+ }
+
+
+ final String getData() {
+ return new String(buf);
+ }
+
+
+ final void reset( int p ) {
+ pos = p;
+ }
+
+
+ final void unread() {
+ if (pos > 0) {
+ pos--;
+ }
+ }
+ }
+
+
+ private static boolean identStart( int ch ) {
+ return ch == 'T' || ch == 'L';
+ }
+
+
+ private static final void matchIdent( MyByteArrayInputStream in, StringBuffer buf ) {
+ int ch;
+ if ((ch = in.read()) == -1) {
+ throw new RuntimeException("Illegal signature: " + in.getData()
+ + " no ident, reaching EOF");
+ }
+ //System.out.println("return from ident:" + (char)ch);
+ if (!identStart(ch)) {
+ StringBuffer buf2 = new StringBuffer();
+ int count = 1;
+ while (Character.isJavaIdentifierPart((char) ch)) {
+ buf2.append((char) ch);
+ count++;
+ ch = in.read();
+ }
+ if (ch == ':') { // Ok, formal parameter
+ in.skip("Ljava/lang/Object".length());
+ buf.append(buf2);
+ ch = in.read();
+ in.unread();
+ //System.out.println("so far:" + buf2 + ":next:" +(char)ch);
+ } else {
+ for (int i = 0; i < count; i++) {
+ in.unread();
+ }
+ }
+ return;
+ }
+ StringBuffer buf2 = new StringBuffer();
+ ch = in.read();
+ do {
+ buf2.append((char) ch);
+ ch = in.read();
+ //System.out.println("within ident:"+ (char)ch);
+ } while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/')));
+ buf.append(buf2.toString().replace('/', '.'));
+ //System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
+ if (ch != -1) {
+ in.unread();
+ }
+ }
+
+
+ private static final void matchGJIdent( MyByteArrayInputStream in, StringBuffer buf ) {
+ int ch;
+ matchIdent(in, buf);
+ ch = in.read();
+ if ((ch == '<') || ch == '(') { // Parameterized or method
+ //System.out.println("Enter <");
+ buf.append((char) ch);
+ matchGJIdent(in, buf);
+ while (((ch = in.read()) != '>') && (ch != ')')) { // List of parameters
+ if (ch == -1) {
+ throw new RuntimeException("Illegal signature: " + in.getData()
+ + " reaching EOF");
+ }
+ //System.out.println("Still no >");
+ buf.append(", ");
+ in.unread();
+ matchGJIdent(in, buf); // Recursive call
+ }
+ //System.out.println("Exit >");
+ buf.append((char) ch);
+ } else {
+ in.unread();
+ }
+ ch = in.read();
+ if (identStart(ch)) {
+ in.unread();
+ matchGJIdent(in, buf);
+ } else if (ch == ')') {
+ in.unread();
+ return;
+ } else if (ch != ';') {
+ throw new RuntimeException("Illegal signature: " + in.getData() + " read " + (char) ch);
+ }
+ }
+
+
+ public static String translate( String s ) {
+ //System.out.println("Sig:" + s);
+ StringBuffer buf = new StringBuffer();
+ matchGJIdent(new MyByteArrayInputStream(s), buf);
+ return buf.toString();
+ }
+
+
+ public static final boolean isFormalParameterList( String s ) {
+ return s.startsWith("<") && (s.indexOf(':') > 0);
+ }
+
+
+ public static final boolean isActualParameterList( String s ) {
+ return s.startsWith("L") && s.endsWith(">;");
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ String s = getSignature();
+ return "Signature(" + s + ")";
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ return (Signature) clone();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+public class SimpleElementValue extends ElementValue
+{
+ private int index;
+
+ public SimpleElementValue(int type, int index, ConstantPool cpool)
+ {
+ super(type, cpool);
+ this.index = index;
+ }
+
+ /**
+ * @return Value entry index in the cpool
+ */
+ public int getIndex()
+ {
+ return index;
+ }
+
+ public void setIndex(int index)
+ {
+ this.index = index;
+ }
+
+ public String getValueString()
+ {
+ if (type != STRING)
+ throw new RuntimeException(
+ "Dont call getValueString() on a non STRING ElementValue");
+ ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+ public int getValueInt()
+ {
+ if (type != PRIMITIVE_INT)
+ throw new RuntimeException(
+ "Dont call getValueString() on a non STRING ElementValue");
+ ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return c.getBytes();
+ }
+
+ public byte getValueByte()
+ {
+ if (type != PRIMITIVE_BYTE)
+ throw new RuntimeException(
+ "Dont call getValueByte() on a non BYTE ElementValue");
+ ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return (byte) c.getBytes();
+ }
+
+ public char getValueChar()
+ {
+ if (type != PRIMITIVE_CHAR)
+ throw new RuntimeException(
+ "Dont call getValueChar() on a non CHAR ElementValue");
+ ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return (char) c.getBytes();
+ }
+
+ public long getValueLong()
+ {
+ if (type != PRIMITIVE_LONG)
+ throw new RuntimeException(
+ "Dont call getValueLong() on a non LONG ElementValue");
+ ConstantLong j = (ConstantLong) cpool.getConstant(getIndex());
+ return j.getBytes();
+ }
+
+ public float getValueFloat()
+ {
+ if (type != PRIMITIVE_FLOAT)
+ throw new RuntimeException(
+ "Dont call getValueFloat() on a non FLOAT ElementValue");
+ ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex());
+ return f.getBytes();
+ }
+
+ public double getValueDouble()
+ {
+ if (type != PRIMITIVE_DOUBLE)
+ throw new RuntimeException(
+ "Dont call getValueDouble() on a non DOUBLE ElementValue");
+ ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex());
+ return d.getBytes();
+ }
+
+ public boolean getValueBoolean()
+ {
+ if (type != PRIMITIVE_BOOLEAN)
+ throw new RuntimeException(
+ "Dont call getValueBoolean() on a non BOOLEAN ElementValue");
+ ConstantInteger bo = (ConstantInteger) cpool.getConstant(getIndex());
+ return (bo.getBytes() != 0);
+ }
+
+ public short getValueShort()
+ {
+ if (type != PRIMITIVE_SHORT)
+ throw new RuntimeException(
+ "Dont call getValueShort() on a non SHORT ElementValue");
+ ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex());
+ return (short) s.getBytes();
+ }
+
+ public String toString()
+ {
+ return stringifyValue();
+ }
+
+ // Whatever kind of value it is, return it as a string
+ public String stringifyValue()
+ {
+ switch (type)
+ {
+ case PRIMITIVE_INT:
+ ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return Integer.toString(c.getBytes());
+ case PRIMITIVE_LONG:
+ ConstantLong j = (ConstantLong) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Long);
+ return Long.toString(j.getBytes());
+ case PRIMITIVE_DOUBLE:
+ ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Double);
+ return Double.toString(d.getBytes());
+ case PRIMITIVE_FLOAT:
+ ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Float);
+ return Float.toString(f.getBytes());
+ case PRIMITIVE_SHORT:
+ ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return Integer.toString(s.getBytes());
+ case PRIMITIVE_BYTE:
+ ConstantInteger b = (ConstantInteger) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Integer);
+ return Integer.toString(b.getBytes());
+ case PRIMITIVE_CHAR:
+ ConstantInteger ch = (ConstantInteger) cpool.getConstant(
+ getIndex(), Constants.CONSTANT_Integer);
+ return String.valueOf((char)ch.getBytes());
+ case PRIMITIVE_BOOLEAN:
+ ConstantInteger bo = (ConstantInteger) cpool.getConstant(
+ getIndex(), Constants.CONSTANT_Integer);
+ if (bo.getBytes() == 0)
+ return "false";
+ if (bo.getBytes() != 0)
+ return "true";
+ case STRING:
+ ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(getIndex(),
+ Constants.CONSTANT_Utf8);
+ return cu8.getBytes();
+ default:
+ throw new RuntimeException(
+ "SimpleElementValue class does not know how to stringify type "
+ + type);
+ }
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 kind of value
+ switch (type)
+ {
+ case PRIMITIVE_INT:
+ case PRIMITIVE_BYTE:
+ case PRIMITIVE_CHAR:
+ case PRIMITIVE_FLOAT:
+ case PRIMITIVE_LONG:
+ case PRIMITIVE_BOOLEAN:
+ case PRIMITIVE_SHORT:
+ case PRIMITIVE_DOUBLE:
+ case STRING:
+ dos.writeShort(getIndex());
+ break;
+ default:
+ throw new RuntimeException(
+ "SimpleElementValue doesnt know how to write out type "
+ + type);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and represents a reference
+ * to the source file of this class. At most one SourceFile attribute
+ * should appear per classfile. The intention of this class is that it is
+ * instantiated from the <em>Attribute.readAttribute()</em> method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class SourceFile extends Attribute {
+
+ private int sourcefile_index;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public SourceFile(SourceFile c) {
+ this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), c.getConstantPool());
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ SourceFile(int name_index, int length, DataInput file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, file.readUnsignedShort(), constant_pool);
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8, which
+ * should represent the string "SourceFile".
+ * @param length Content length in bytes, the value should be 2.
+ * @param constant_pool The constant pool that this attribute is
+ * associated with.
+ * @param sourcefile_index Index in constant pool to CONSTANT_Utf8. This
+ * string will be interpreted as the name of the file from which this
+ * class was compiled. It will not be interpreted as indicating the name
+ * of the directory contqining the file or an absolute path; this
+ * information has to be supplied the consumer of this attribute - in
+ * many cases, the JVM.
+ */
+ public SourceFile(int name_index, int length, int sourcefile_index, ConstantPool constant_pool) {
+ super(Constants.ATTR_SOURCE_FILE, name_index, length, constant_pool);
+ this.sourcefile_index = sourcefile_index;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitSourceFile(this);
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(sourcefile_index);
+ }
+
+
+ /**
+ * @return Index in constant pool of source file name.
+ */
+ public final int getSourceFileIndex() {
+ return sourcefile_index;
+ }
+
+
+ /**
+ * @param sourcefile_index
+ */
+ public final void setSourceFileIndex( int sourcefile_index ) {
+ this.sourcefile_index = sourcefile_index;
+ }
+
+
+ /**
+ * @return Source file name.
+ */
+ public final String getSourceFileName() {
+ ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(sourcefile_index,
+ Constants.CONSTANT_Utf8);
+ return c.getBytes();
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return "SourceFile(" + getSourceFileName() + ")";
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ return (SourceFile) clone();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a stack map attribute used for
+ * preverification of Java classes for the <a
+ * href="http://java.sun.com/j2me/"> Java 2 Micro Edition</a>
+ * (J2ME). This attribute is used by the <a
+ * href="http://java.sun.com/products/cldc/">KVM</a> and contained
+ * within the Code attribute of a method. See CLDC specification
+ * �5.3.1.2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ * @see StackMapEntry
+ * @see StackMapType
+ */
+public final class StackMap extends Attribute implements Node {
+
+ private int map_length;
+ private StackMapEntry[] map; // Table of stack map entries
+
+
+ /*
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param map Table of stack map entries
+ * @param constant_pool Array of constants
+ */
+ public StackMap(int name_index, int length, StackMapEntry[] map, ConstantPool constant_pool) {
+ super(Constants.ATTR_STACK_MAP, name_index, length, constant_pool);
+ setStackMap(map);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ StackMap(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (StackMapEntry[]) null, constant_pool);
+ map_length = file.readUnsignedShort();
+ map = new StackMapEntry[map_length];
+ for (int i = 0; i < map_length; i++) {
+ map[i] = new StackMapEntry(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * Dump line number table attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(map_length);
+ for (int i = 0; i < map_length; i++) {
+ map[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Array of stack map entries
+ */
+ public final StackMapEntry[] getStackMap() {
+ return map;
+ }
+
+
+ /**
+ * @param map Array of stack map entries
+ */
+ public final void setStackMap( StackMapEntry[] map ) {
+ this.map = map;
+ map_length = (map == null) ? 0 : map.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer("StackMap(");
+ for (int i = 0; i < map_length; i++) {
+ buf.append(map[i].toString());
+ if (i < map_length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ StackMap c = (StackMap) clone();
+ c.map = new StackMapEntry[map_length];
+ for (int i = 0; i < map_length; i++) {
+ c.map[i] = map[i].copy();
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackMap(this);
+ }
+
+
+ public final int getMapLength() {
+ return map_length;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * This class represents a stack map entry recording the types of
+ * local variables and the the of stack items at a given byte code offset.
+ * See CLDC specification �5.3.1.2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see StackMap
+ * @see StackMapType
+ */
+public final class StackMapEntry implements Cloneable {
+
+ private int byte_code_offset;
+ private int number_of_locals;
+ private StackMapType[] types_of_locals;
+ private int number_of_stack_items;
+ private StackMapType[] types_of_stack_items;
+ private ConstantPool constant_pool;
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException {
+ this(file.readShort(), file.readShort(), null, -1, null, constant_pool);
+ types_of_locals = new StackMapType[number_of_locals];
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i] = new StackMapType(file, constant_pool);
+ }
+ number_of_stack_items = file.readShort();
+ types_of_stack_items = new StackMapType[number_of_stack_items];
+ for (int i = 0; i < number_of_stack_items; i++) {
+ types_of_stack_items[i] = new StackMapType(file, constant_pool);
+ }
+ }
+
+
+ public StackMapEntry(int byte_code_offset, int number_of_locals,
+ StackMapType[] types_of_locals, int number_of_stack_items,
+ StackMapType[] types_of_stack_items, ConstantPool constant_pool) {
+ this.byte_code_offset = byte_code_offset;
+ this.number_of_locals = number_of_locals;
+ this.types_of_locals = types_of_locals;
+ this.number_of_stack_items = number_of_stack_items;
+ this.types_of_stack_items = types_of_stack_items;
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * Dump stack map entry
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeShort(byte_code_offset);
+ file.writeShort(number_of_locals);
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i].dump(file);
+ }
+ file.writeShort(number_of_stack_items);
+ for (int i = 0; i < number_of_stack_items; i++) {
+ types_of_stack_items[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer(64);
+ buf.append("(offset=").append(byte_code_offset);
+ if (number_of_locals > 0) {
+ buf.append(", locals={");
+ for (int i = 0; i < number_of_locals; i++) {
+ buf.append(types_of_locals[i]);
+ if (i < number_of_locals - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+ }
+ if (number_of_stack_items > 0) {
+ buf.append(", stack items={");
+ for (int i = 0; i < number_of_stack_items; i++) {
+ buf.append(types_of_stack_items[i]);
+ if (i < number_of_stack_items - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+
+ public void setByteCodeOffset( int b ) {
+ byte_code_offset = b;
+ }
+
+
+ public int getByteCodeOffset() {
+ return byte_code_offset;
+ }
+
+
+ public void setNumberOfLocals( int n ) {
+ number_of_locals = n;
+ }
+
+
+ public int getNumberOfLocals() {
+ return number_of_locals;
+ }
+
+
+ public void setTypesOfLocals( StackMapType[] t ) {
+ types_of_locals = t;
+ }
+
+
+ public StackMapType[] getTypesOfLocals() {
+ return types_of_locals;
+ }
+
+
+ public void setNumberOfStackItems( int n ) {
+ number_of_stack_items = n;
+ }
+
+
+ public int getNumberOfStackItems() {
+ return number_of_stack_items;
+ }
+
+
+ public void setTypesOfStackItems( StackMapType[] t ) {
+ types_of_stack_items = t;
+ }
+
+
+ public StackMapType[] getTypesOfStackItems() {
+ return types_of_stack_items;
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public StackMapEntry copy() {
+ try {
+ return (StackMapEntry) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackMapEntry(this);
+ }
+
+
+ /**
+ * @return Constant pool used by this object.
+ */
+ public final ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @param constant_pool Constant pool to be used for this object.
+ */
+ public final void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a stack map attribute used for
+ * preverification of Java classes for the <a
+ * href="http://java.sun.com/j2me/"> Java 2 Micro Edition</a>
+ * (J2ME). This attribute is used by the <a
+ * href="http://java.sun.com/products/cldc/">KVM</a> and contained
+ * within the Code attribute of a method. See CLDC specification
+ * ��?5.3.1.2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Code
+ * @see StackMapEntry
+ * @see StackMapType
+ */
+public final class StackMapTable extends Attribute implements Node {
+
+ private int map_length;
+ private StackMapTableEntry[] map; // Table of stack map entries
+
+
+ /*
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param map Table of stack map entries
+ * @param constant_pool Array of constants
+ */
+ public StackMapTable(int name_index, int length, StackMapTableEntry[] map, ConstantPool constant_pool) {
+ super(Constants.ATTR_STACK_MAP_TABLE, name_index, length, constant_pool);
+ setStackMapTable(map);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index of name
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ StackMapTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (StackMapTableEntry[]) null, constant_pool);
+ map_length = file.readUnsignedShort();
+ map = new StackMapTableEntry[map_length];
+ for (int i = 0; i < map_length; i++) {
+ map[i] = new StackMapTableEntry(file, constant_pool);
+ }
+ }
+
+
+ /**
+ * Dump line number table attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ file.writeShort(map_length);
+ for (int i = 0; i < map_length; i++) {
+ map[i].dump(file);
+ }
+ }
+
+
+ /**
+ * @return Array of stack map entries
+ */
+ public final StackMapTableEntry[] getStackMapTable() {
+ return map;
+ }
+
+
+ /**
+ * @param map Array of stack map entries
+ */
+ public final void setStackMapTable( StackMapTableEntry[] map ) {
+ this.map = map;
+ map_length = (map == null) ? 0 : map.length;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer("StackMapTable(");
+ for (int i = 0; i < map_length; i++) {
+ buf.append(map[i].toString());
+ if (i < map_length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(')');
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ StackMapTable c = (StackMapTable) clone();
+ c.map = new StackMapTableEntry[map_length];
+ for (int i = 0; i < map_length; i++) {
+ c.map[i] = map[i].copy();
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackMapTable(this);
+ }
+
+
+ public final int getMapLength() {
+ return map_length;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a stack map entry recording the types of
+ * local variables and the the of stack items at a given byte code offset.
+ * See CLDC specification ��?5.3.1.2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see StackMap
+ * @see StackMapType
+ */
+public final class StackMapTableEntry implements Cloneable {
+
+ private int frame_type;
+ private int byte_code_offset_delta;
+ private int number_of_locals;
+ private StackMapType[] types_of_locals;
+ private int number_of_stack_items;
+ private StackMapType[] types_of_stack_items;
+ private ConstantPool constant_pool;
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ StackMapTableEntry(DataInputStream file, ConstantPool constant_pool) throws IOException {
+ this(file.read(), -1, -1, null, -1, null, constant_pool);
+
+ if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) {
+ byte_code_offset_delta = frame_type - Constants.SAME_FRAME;
+ } else if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
+ byte_code_offset_delta = frame_type - Constants.SAME_LOCALS_1_STACK_ITEM_FRAME;
+ number_of_stack_items = 1;
+ types_of_stack_items = new StackMapType[1];
+ types_of_stack_items[0] = new StackMapType(file, constant_pool);
+ } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
+ byte_code_offset_delta = file.readShort();
+ number_of_stack_items = 1;
+ types_of_stack_items = new StackMapType[1];
+ types_of_stack_items[0] = new StackMapType(file, constant_pool);
+ } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) {
+ byte_code_offset_delta = file.readShort();
+ } else if (frame_type == Constants.SAME_FRAME_EXTENDED) {
+ byte_code_offset_delta = file.readShort();
+ } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) {
+ byte_code_offset_delta = file.readShort();
+ number_of_locals = frame_type - 251;
+ types_of_locals = new StackMapType[number_of_locals];
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i] = new StackMapType(file, constant_pool);
+ }
+ } else if (frame_type == Constants.FULL_FRAME) {
+ byte_code_offset_delta = file.readShort();
+ number_of_locals = file.readShort();
+ types_of_locals = new StackMapType[number_of_locals];
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i] = new StackMapType(file, constant_pool);
+ }
+ number_of_stack_items = file.readShort();
+ types_of_stack_items = new StackMapType[number_of_stack_items];
+ for (int i = 0; i < number_of_stack_items; i++) {
+ types_of_stack_items[i] = new StackMapType(file, constant_pool);
+ }
+ } else {
+ /* Can't happen */
+ throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frame_type);
+ }
+ }
+
+
+ public StackMapTableEntry(int tag, int byte_code_offset_delta, int number_of_locals,
+ StackMapType[] types_of_locals, int number_of_stack_items,
+ StackMapType[] types_of_stack_items, ConstantPool constant_pool) {
+ this.frame_type = tag;
+ this.byte_code_offset_delta = byte_code_offset_delta;
+ this.number_of_locals = number_of_locals;
+ this.types_of_locals = types_of_locals;
+ this.number_of_stack_items = number_of_stack_items;
+ this.types_of_stack_items = types_of_stack_items;
+ this.constant_pool = constant_pool;
+ }
+
+
+ /**
+ * Dump stack map entry
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.write(frame_type);
+ if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
+ types_of_stack_items[0].dump(file);
+ } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
+ file.write(byte_code_offset_delta);
+ types_of_stack_items[0].dump(file);
+ } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) {
+ file.write(byte_code_offset_delta);
+ } else if (frame_type == Constants.SAME_FRAME_EXTENDED) {
+ file.write(byte_code_offset_delta);
+ } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) {
+ file.write(byte_code_offset_delta);
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i].dump(file);
+ }
+ } else if (frame_type == Constants.FULL_FRAME) {
+ file.writeShort(byte_code_offset_delta);
+ file.writeShort(number_of_locals);
+ for (int i = 0; i < number_of_locals; i++) {
+ types_of_locals[i].dump(file);
+ }
+ file.writeShort(number_of_stack_items);
+ for (int i = 0; i < number_of_stack_items; i++) {
+ types_of_stack_items[i].dump(file);
+ }
+ } else {
+ /* Can't happen */
+ throw new ClassFormatException ("Invalid Stack map table tag: " + frame_type);
+ }
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer(64);
+ buf.append("(");
+ if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) {
+ buf.append("SAME");
+ } else if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
+ buf.append("SAME_LOCALS_1_STACK");
+ } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
+ buf.append("SAME_LOCALS_1_STACK_EXTENDED");
+ } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) {
+ buf.append("CHOP "+(251-frame_type));
+ } else if (frame_type == Constants.SAME_FRAME_EXTENDED) {
+ buf.append("SAME_EXTENDED");
+ } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) {
+ buf.append("APPEND "+(frame_type-251));
+ } else if (frame_type == Constants.FULL_FRAME) {
+ buf.append("FULL");
+ } else {
+ buf.append("UNKNOWN");
+ }
+ buf.append(", offset delta=").append(byte_code_offset_delta);
+ if (number_of_locals > 0) {
+ buf.append(", locals={");
+ for (int i = 0; i < number_of_locals; i++) {
+ buf.append(types_of_locals[i]);
+ if (i < number_of_locals - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+ }
+ if (number_of_stack_items > 0) {
+ buf.append(", stack items={");
+ for (int i = 0; i < number_of_stack_items; i++) {
+ buf.append(types_of_stack_items[i]);
+ if (i < number_of_stack_items - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("}");
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+
+ public void setByteCodeOffsetDelta( int b ) {
+ byte_code_offset_delta = b;
+ }
+
+
+ public int getByteCodeOffsetDelta() {
+ return byte_code_offset_delta;
+ }
+
+
+ public void setNumberOfLocals( int n ) {
+ number_of_locals = n;
+ }
+
+
+ public int getNumberOfLocals() {
+ return number_of_locals;
+ }
+
+
+ public void setTypesOfLocals( StackMapType[] t ) {
+ types_of_locals = t;
+ }
+
+
+ public StackMapType[] getTypesOfLocals() {
+ return types_of_locals;
+ }
+
+
+ public void setNumberOfStackItems( int n ) {
+ number_of_stack_items = n;
+ }
+
+
+ public int getNumberOfStackItems() {
+ return number_of_stack_items;
+ }
+
+
+ public void setTypesOfStackItems( StackMapType[] t ) {
+ types_of_stack_items = t;
+ }
+
+
+ public StackMapType[] getTypesOfStackItems() {
+ return types_of_stack_items;
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public StackMapTableEntry copy() {
+ try {
+ return (StackMapTableEntry) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackMapTableEntry(this);
+ }
+
+
+ /**
+ * @return Constant pool used by this object.
+ */
+ public final ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @param constant_pool Constant pool to be used for this object.
+ */
+ public final void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents the type of a local variable or item on stack
+ * used in the StackMap entries.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see StackMapEntry
+ * @see StackMap
+ * @see Constants
+ */
+public final class StackMapType implements Cloneable {
+
+ private byte type;
+ private int index = -1; // Index to CONSTANT_Class or offset
+ private ConstantPool constant_pool;
+
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @throws IOException
+ */
+ StackMapType(DataInput file, ConstantPool constant_pool) throws IOException {
+ this(file.readByte(), -1, constant_pool);
+ if (hasIndex()) {
+ setIndex(file.readShort());
+ }
+ setConstantPool(constant_pool);
+ }
+
+
+ /**
+ * @param type type tag as defined in the Constants interface
+ * @param index index to constant pool, or byte code offset
+ */
+ public StackMapType(byte type, int index, ConstantPool constant_pool) {
+ setType(type);
+ setIndex(index);
+ setConstantPool(constant_pool);
+ }
+
+
+ public void setType( byte t ) {
+ if ((t < Constants.ITEM_Bogus) || (t > Constants.ITEM_NewObject)) {
+ throw new RuntimeException("Illegal type for StackMapType: " + t);
+ }
+ type = t;
+ }
+
+
+ public byte getType() {
+ return type;
+ }
+
+
+ public void setIndex( int t ) {
+ index = t;
+ }
+
+
+ /** @return index to constant pool if type == ITEM_Object, or offset
+ * in byte code, if type == ITEM_NewObject, and -1 otherwise
+ */
+ public int getIndex() {
+ return index;
+ }
+
+
+ /**
+ * Dump type entries to file.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ file.writeByte(type);
+ if (hasIndex()) {
+ file.writeShort(getIndex());
+ }
+ }
+
+
+ /** @return true, if type is either ITEM_Object or ITEM_NewObject
+ */
+ public final boolean hasIndex() {
+ return ((type == Constants.ITEM_Object) || (type == Constants.ITEM_NewObject));
+ }
+
+
+ private String printIndex() {
+ if (type == Constants.ITEM_Object) {
+ if (index < 0) {
+ return ", class=<unknown>";
+ }
+ return ", class=" + constant_pool.constantToString(index, Constants.CONSTANT_Class);
+ } else if (type == Constants.ITEM_NewObject) {
+ return ", offset=" + index;
+ } else {
+ return "";
+ }
+ }
+
+
+ /**
+ * @return String representation
+ */
+ public final String toString() {
+ return "(type=" + Constants.ITEM_NAMES[type] + printIndex() + ")";
+ }
+
+
+ /**
+ * @return deep copy of this object
+ */
+ public StackMapType copy() {
+ try {
+ return (StackMapType) clone();
+ } catch (CloneNotSupportedException e) {
+ }
+ return null;
+ }
+
+
+ /**
+ * @return Constant pool used by this object.
+ */
+ public final ConstantPool getConstantPool() {
+ return constant_pool;
+ }
+
+
+ /**
+ * @param constant_pool Constant pool to be used for this object.
+ */
+ public final void setConstantPool( ConstantPool constant_pool ) {
+ this.constant_pool = constant_pool;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class is derived from <em>Attribute</em> and declares this class as
+ * `synthetic', i.e., it needs special handling. The JVM specification
+ * states "A class member that does not appear in the source code must be
+ * marked using a Synthetic attribute." It may appear in the ClassFile
+ * attribute table, a field_info table or a method_info table. This class
+ * is intended to be instantiated from the
+ * <em>Attribute.readAttribute()</em> method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Attribute
+ */
+public final class Synthetic extends Attribute {
+
+ private byte[] bytes;
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use copy() for a physical copy.
+ */
+ public Synthetic(Synthetic c) {
+ this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
+ }
+
+
+ /**
+ * @param name_index Index in constant pool to CONSTANT_Utf8, which
+ * should represent the string "Synthetic".
+ * @param length Content length in bytes - should be zero.
+ * @param bytes Attribute contents
+ * @param constant_pool The constant pool this attribute is associated
+ * with.
+ */
+ public Synthetic(int name_index, int length, byte[] bytes, ConstantPool constant_pool) {
+ super(Constants.ATTR_SYNTHETIC, name_index, length, constant_pool);
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool to CONSTANT_Utf8
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ Synthetic(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (byte[]) null, constant_pool);
+ if (length > 0) {
+ bytes = new byte[length];
+ file.readFully(bytes);
+ System.err.println("Synthetic attribute with length > 0");
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitSynthetic(this);
+ }
+
+
+ /**
+ * Dump source file attribute to file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ if (length > 0) {
+ file.write(bytes, 0, length);
+ }
+ }
+
+
+ /**
+ * @return data bytes.
+ */
+ public final byte[] getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @param bytes
+ */
+ public final void setBytes( byte[] bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ StringBuffer buf = new StringBuffer("Synthetic");
+ if (length > 0) {
+ buf.append(" ").append(Utility.toHexString(bytes));
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ Synthetic c = (Synthetic) clone();
+ if (bytes != null) {
+ c.bytes = new byte[bytes.length];
+ System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This class represents a reference to an unknown (i.e.,
+ * application-specific) attribute of a class. It is instantiated from the
+ * <em>Attribute.readAttribute()</em> method. Applications that need to
+ * read in application-specific attributes should create an <a
+ * href="./AttributeReader.html">AttributeReader</a> implementation and
+ * attach it via <a
+ * href="./Attribute.html#addAttributeReader(java.lang.String,
+ * org.apache.tomcat.util.bcel.classfile.AttributeReader)">Attribute.addAttributeReader</a>.
+
+ *
+ * @version $Id$
+ * @see org.apache.tomcat.util.bcel.classfile.Attribute
+ * @see org.apache.tomcat.util.bcel.classfile.AttributeReader
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class Unknown extends Attribute {
+
+ private byte[] bytes;
+ private String name;
+ private static Map unknown_attributes = new HashMap();
+
+
+ /** @return array of unknown attributes, but just one for each kind.
+ */
+ static Unknown[] getUnknownAttributes() {
+ Unknown[] unknowns = new Unknown[unknown_attributes.size()];
+ Iterator entries = unknown_attributes.values().iterator();
+ for (int i = 0; entries.hasNext(); i++) {
+ unknowns[i] = (Unknown) entries.next();
+ }
+ unknown_attributes.clear();
+ return unknowns;
+ }
+
+
+ /**
+ * Initialize from another object. Note that both objects use the same
+ * references (shallow copy). Use clone() for a physical copy.
+ */
+ public Unknown(Unknown c) {
+ this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool());
+ }
+
+
+ /**
+ * Create a non-standard attribute.
+ *
+ * @param name_index Index in constant pool
+ * @param length Content length in bytes
+ * @param bytes Attribute contents
+ * @param constant_pool Array of constants
+ */
+ public Unknown(int name_index, int length, byte[] bytes, ConstantPool constant_pool) {
+ super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool);
+ this.bytes = bytes;
+ name = ((ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8))
+ .getBytes();
+ unknown_attributes.put(name, this);
+ }
+
+
+ /**
+ * Construct object from file stream.
+ * @param name_index Index in constant pool
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @throws IOException
+ */
+ Unknown(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
+ throws IOException {
+ this(name_index, length, (byte[]) null, constant_pool);
+ if (length > 0) {
+ bytes = new byte[length];
+ file.readFully(bytes);
+ }
+ }
+
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitely
+ * defined by the contents of a Java class. I.e., the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitUnknown(this);
+ }
+
+
+ /**
+ * Dump unknown bytes to file stream.
+ *
+ * @param file Output file stream
+ * @throws IOException
+ */
+ public final void dump( DataOutputStream file ) throws IOException {
+ super.dump(file);
+ if (length > 0) {
+ file.write(bytes, 0, length);
+ }
+ }
+
+
+ /**
+ * @return data bytes.
+ */
+ public final byte[] getBytes() {
+ return bytes;
+ }
+
+
+ /**
+ * @return name of attribute.
+ */
+ public final String getName() {
+ return name;
+ }
+
+
+ /**
+ * @param bytes the bytes to set
+ */
+ public final void setBytes( byte[] bytes ) {
+ this.bytes = bytes;
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public final String toString() {
+ if (length == 0 || bytes == null) {
+ return "(Unknown attribute " + name + ")";
+ }
+ String hex;
+ if (length > 10) {
+ byte[] tmp = new byte[10];
+ System.arraycopy(bytes, 0, tmp, 0, 10);
+ hex = Utility.toHexString(tmp) + "... (truncated)";
+ } else {
+ hex = Utility.toHexString(bytes);
+ }
+ return "(Unknown attribute " + name + ": " + hex + ")";
+ }
+
+
+ /**
+ * @return deep copy of this attribute
+ */
+ public Attribute copy( ConstantPool _constant_pool ) {
+ Unknown c = (Unknown) clone();
+ if (bytes != null) {
+ c.bytes = new byte[bytes.length];
+ System.arraycopy(bytes, 0, c.bytes, 0, bytes.length);
+ }
+ c.constant_pool = _constant_pool;
+ return c;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.CharArrayWriter;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FilterReader;
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.generic.AnnotationEntryGen;
+import org.apache.tomcat.util.bcel.generic.ConstantPoolGen;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Utility functions that do not really belong to any class in particular.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class Utility {
+
+ private static int unwrap( ThreadLocal tl ) {
+ return ((Integer) tl.get()).intValue();
+ }
+
+
+ private static void wrap( ThreadLocal tl, int value ) {
+ tl.set(new Integer(value));
+ }
+
+ private static ThreadLocal consumed_chars = new ThreadLocal() {
+
+ protected Object initialValue() {
+ return new Integer(0);
+ }
+ };/* How many chars have been consumed
+ * during parsing in signatureToString().
+ * Read by methodSignatureToString().
+ * Set by side effect,but only internally.
+ */
+ private static boolean wide = false; /* The `WIDE' instruction is used in the
+ * byte code to allow 16-bit wide indices
+ * for local variables. This opcode
+ * precedes an `ILOAD', e.g.. The opcode
+ * immediately following takes an extra
+ * byte which is combined with the
+ * following byte to form a
+ * 16-bit value.
+ */
+
+
+ /**
+ * Convert bit field of flags into string such as `static final'.
+ *
+ * @param access_flags Access flags
+ * @return String representation of flags
+ */
+ public static final String accessToString( int access_flags ) {
+ return accessToString(access_flags, false);
+ }
+
+
+ /**
+ * Convert bit field of flags into string such as `static final'.
+ *
+ * Special case: Classes compiled with new compilers and with the
+ * `ACC_SUPER' flag would be said to be "synchronized". This is
+ * because SUN used the same value for the flags `ACC_SUPER' and
+ * `ACC_SYNCHRONIZED'.
+ *
+ * @param access_flags Access flags
+ * @param for_class access flags are for class qualifiers ?
+ * @return String representation of flags
+ */
+ public static final String accessToString( int access_flags, boolean for_class ) {
+ StringBuffer buf = new StringBuffer();
+ int p = 0;
+ for (int i = 0; p < Constants.MAX_ACC_FLAG; i++) { // Loop through known flags
+ p = pow2(i);
+ if ((access_flags & p) != 0) {
+ /* Special case: Classes compiled with new compilers and with the
+ * `ACC_SUPER' flag would be said to be "synchronized". This is
+ * because SUN used the same value for the flags `ACC_SUPER' and
+ * `ACC_SYNCHRONIZED'.
+ */
+ if (for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE))) {
+ continue;
+ }
+ buf.append(Constants.ACCESS_NAMES[i]).append(" ");
+ }
+ }
+ return buf.toString().trim();
+ }
+
+
+ /**
+ * @return "class" or "interface", depending on the ACC_INTERFACE flag
+ */
+ public static final String classOrInterface( int access_flags ) {
+ return ((access_flags & Constants.ACC_INTERFACE) != 0) ? "interface" : "class";
+ }
+
+
+ /**
+ * Disassemble a byte array of JVM byte codes starting from code line
+ * `index' and return the disassembled string representation. Decode only
+ * `num' opcodes (including their operands), use -1 if you want to
+ * decompile everything.
+ *
+ * @param code byte code array
+ * @param constant_pool Array of constants
+ * @param index offset in `code' array
+ * <EM>(number of opcodes, not bytes!)</EM>
+ * @param length number of opcodes to decompile, -1 for all
+ * @param verbose be verbose, e.g. print constant pool index
+ * @return String representation of byte codes
+ */
+ public static final String codeToString( byte[] code, ConstantPool constant_pool, int index,
+ int length, boolean verbose ) {
+ StringBuffer buf = new StringBuffer(code.length * 20); // Should be sufficient
+ ByteSequence stream = new ByteSequence(code);
+ try {
+ for (int i = 0; i < index; i++) {
+ codeToString(stream, constant_pool, verbose);
+ }
+ for (int i = 0; stream.available() > 0; i++) {
+ if ((length < 0) || (i < length)) {
+ String indices = fillup(stream.getIndex() + ":", 6, true, ' ');
+ buf.append(indices).append(codeToString(stream, constant_pool, verbose))
+ .append('\n');
+ }
+ }
+ } catch (IOException e) {
+ System.out.println(buf.toString());
+ e.printStackTrace();
+ throw new ClassFormatException("Byte code error: " + e, e);
+ }
+ return buf.toString();
+ }
+
+
+ public static final String codeToString( byte[] code, ConstantPool constant_pool, int index,
+ int length ) {
+ return codeToString(code, constant_pool, index, length, true);
+ }
+
+
+ /**
+ * Disassemble a stream of byte codes and return the
+ * string representation.
+ *
+ * @param bytes stream of bytes
+ * @param constant_pool Array of constants
+ * @param verbose be verbose, e.g. print constant pool index
+ * @return String representation of byte code
+ */
+ public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool,
+ boolean verbose ) throws IOException {
+ short opcode = (short) bytes.readUnsignedByte();
+ int default_offset = 0, low, high, npairs;
+ int index, vindex, constant;
+ int[] match, jump_table;
+ int no_pad_bytes = 0, offset;
+ StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]);
+ /* Special case: Skip (0-3) padding bytes, i.e., the
+ * following bytes are 4-byte-aligned
+ */
+ if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) {
+ int remainder = bytes.getIndex() % 4;
+ no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
+ for (int i = 0; i < no_pad_bytes; i++) {
+ byte b;
+ if ((b = bytes.readByte()) != 0) {
+ System.err.println("Warning: Padding byte != 0 in "
+ + Constants.OPCODE_NAMES[opcode] + ":" + b);
+ }
+ }
+ // Both cases have a field default_offset in common
+ default_offset = bytes.readInt();
+ }
+ switch (opcode) {
+ /* Table switch has variable length arguments.
+ */
+ case Constants.TABLESWITCH:
+ low = bytes.readInt();
+ high = bytes.readInt();
+ offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
+ default_offset += offset;
+ buf.append("\tdefault = ").append(default_offset).append(", low = ").append(low)
+ .append(", high = ").append(high).append("(");
+ jump_table = new int[high - low + 1];
+ for (int i = 0; i < jump_table.length; i++) {
+ jump_table[i] = offset + bytes.readInt();
+ buf.append(jump_table[i]);
+ if (i < jump_table.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ break;
+ /* Lookup switch has variable length arguments.
+ */
+ case Constants.LOOKUPSWITCH: {
+ npairs = bytes.readInt();
+ offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
+ match = new int[npairs];
+ jump_table = new int[npairs];
+ default_offset += offset;
+ buf.append("\tdefault = ").append(default_offset).append(", npairs = ").append(
+ npairs).append(" (");
+ for (int i = 0; i < npairs; i++) {
+ match[i] = bytes.readInt();
+ jump_table[i] = offset + bytes.readInt();
+ buf.append("(").append(match[i]).append(", ").append(jump_table[i]).append(")");
+ if (i < npairs - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ }
+ break;
+ /* Two address bytes + offset from start of byte stream form the
+ * jump target
+ */
+ case Constants.GOTO:
+ case Constants.IFEQ:
+ case Constants.IFGE:
+ case Constants.IFGT:
+ case Constants.IFLE:
+ case Constants.IFLT:
+ case Constants.JSR:
+ case Constants.IFNE:
+ case Constants.IFNONNULL:
+ case Constants.IFNULL:
+ case Constants.IF_ACMPEQ:
+ case Constants.IF_ACMPNE:
+ case Constants.IF_ICMPEQ:
+ case Constants.IF_ICMPGE:
+ case Constants.IF_ICMPGT:
+ case Constants.IF_ICMPLE:
+ case Constants.IF_ICMPLT:
+ case Constants.IF_ICMPNE:
+ buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readShort());
+ break;
+ /* 32-bit wide jumps
+ */
+ case Constants.GOTO_W:
+ case Constants.JSR_W:
+ buf.append("\t\t#").append(((bytes.getIndex() - 1) + bytes.readInt()));
+ break;
+ /* Index byte references local variable (register)
+ */
+ case Constants.ALOAD:
+ case Constants.ASTORE:
+ case Constants.DLOAD:
+ case Constants.DSTORE:
+ case Constants.FLOAD:
+ case Constants.FSTORE:
+ case Constants.ILOAD:
+ case Constants.ISTORE:
+ case Constants.LLOAD:
+ case Constants.LSTORE:
+ case Constants.RET:
+ if (wide) {
+ vindex = bytes.readUnsignedShort();
+ wide = false; // Clear flag
+ } else {
+ vindex = bytes.readUnsignedByte();
+ }
+ buf.append("\t\t%").append(vindex);
+ break;
+ /*
+ * Remember wide byte which is used to form a 16-bit address in the
+ * following instruction. Relies on that the method is called again with
+ * the following opcode.
+ */
+ case Constants.WIDE:
+ wide = true;
+ buf.append("\t(wide)");
+ break;
+ /* Array of basic type.
+ */
+ case Constants.NEWARRAY:
+ buf.append("\t\t<").append(Constants.TYPE_NAMES[bytes.readByte()]).append(">");
+ break;
+ /* Access object/class fields.
+ */
+ case Constants.GETFIELD:
+ case Constants.GETSTATIC:
+ case Constants.PUTFIELD:
+ case Constants.PUTSTATIC:
+ index = bytes.readUnsignedShort();
+ buf.append("\t\t").append(
+ constant_pool.constantToString(index, Constants.CONSTANT_Fieldref)).append(
+ (verbose ? " (" + index + ")" : ""));
+ break;
+ /* Operands are references to classes in constant pool
+ */
+ case Constants.NEW:
+ case Constants.CHECKCAST:
+ buf.append("\t");
+ /* FALL THRU */
+ case Constants.INSTANCEOF:
+ index = bytes.readUnsignedShort();
+ buf.append("\t<").append(
+ constant_pool.constantToString(index, Constants.CONSTANT_Class))
+ .append(">").append((verbose ? " (" + index + ")" : ""));
+ break;
+ /* Operands are references to methods in constant pool
+ */
+ case Constants.INVOKESPECIAL:
+ case Constants.INVOKESTATIC:
+ case Constants.INVOKEVIRTUAL:
+ index = bytes.readUnsignedShort();
+ buf.append("\t").append(
+ constant_pool.constantToString(index, Constants.CONSTANT_Methodref))
+ .append((verbose ? " (" + index + ")" : ""));
+ break;
+ case Constants.INVOKEINTERFACE:
+ index = bytes.readUnsignedShort();
+ int nargs = bytes.readUnsignedByte(); // historical, redundant
+ buf.append("\t").append(
+ constant_pool
+ .constantToString(index, Constants.CONSTANT_InterfaceMethodref))
+ .append(verbose ? " (" + index + ")\t" : "").append(nargs).append("\t")
+ .append(bytes.readUnsignedByte()); // Last byte is a reserved space
+ break;
+ /* Operands are references to items in constant pool
+ */
+ case Constants.LDC_W:
+ case Constants.LDC2_W:
+ index = bytes.readUnsignedShort();
+ buf.append("\t\t").append(
+ constant_pool.constantToString(index, constant_pool.getConstant(index)
+ .getTag())).append((verbose ? " (" + index + ")" : ""));
+ break;
+ case Constants.LDC:
+ index = bytes.readUnsignedByte();
+ buf.append("\t\t").append(
+ constant_pool.constantToString(index, constant_pool.getConstant(index)
+ .getTag())).append((verbose ? " (" + index + ")" : ""));
+ break;
+ /* Array of references.
+ */
+ case Constants.ANEWARRAY:
+ index = bytes.readUnsignedShort();
+ buf.append("\t\t<").append(
+ compactClassName(constant_pool.getConstantString(index,
+ Constants.CONSTANT_Class), false)).append(">").append(
+ (verbose ? " (" + index + ")" : ""));
+ break;
+ /* Multidimensional array of references.
+ */
+ case Constants.MULTIANEWARRAY: {
+ index = bytes.readUnsignedShort();
+ int dimensions = bytes.readUnsignedByte();
+ buf.append("\t<").append(
+ compactClassName(constant_pool.getConstantString(index,
+ Constants.CONSTANT_Class), false)).append(">\t").append(dimensions)
+ .append((verbose ? " (" + index + ")" : ""));
+ }
+ break;
+ /* Increment local variable.
+ */
+ case Constants.IINC:
+ if (wide) {
+ vindex = bytes.readUnsignedShort();
+ constant = bytes.readShort();
+ wide = false;
+ } else {
+ vindex = bytes.readUnsignedByte();
+ constant = bytes.readByte();
+ }
+ buf.append("\t\t%").append(vindex).append("\t").append(constant);
+ break;
+ default:
+ if (Constants.NO_OF_OPERANDS[opcode] > 0) {
+ for (int i = 0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) {
+ buf.append("\t\t");
+ switch (Constants.TYPE_OF_OPERANDS[opcode][i]) {
+ case Constants.T_BYTE:
+ buf.append(bytes.readByte());
+ break;
+ case Constants.T_SHORT:
+ buf.append(bytes.readShort());
+ break;
+ case Constants.T_INT:
+ buf.append(bytes.readInt());
+ break;
+ default: // Never reached
+ System.err.println("Unreachable default case reached!");
+ System.exit(-1);
+ }
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+
+ public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool )
+ throws IOException {
+ return codeToString(bytes, constant_pool, true);
+ }
+
+
+ /**
+ * Shorten long class names, <em>java/lang/String</em> becomes
+ * <em>String</em>.
+ *
+ * @param str The long class name
+ * @return Compacted class name
+ */
+ public static final String compactClassName( String str ) {
+ return compactClassName(str, true);
+ }
+
+
+ /**
+ * Shorten long class name <em>str</em>, i.e., chop off the <em>prefix</em>,
+ * if the
+ * class name starts with this string and the flag <em>chopit</em> is true.
+ * Slashes <em>/</em> are converted to dots <em>.</em>.
+ *
+ * @param str The long class name
+ * @param prefix The prefix the get rid off
+ * @param chopit Flag that determines whether chopping is executed or not
+ * @return Compacted class name
+ */
+ public static final String compactClassName( String str, String prefix, boolean chopit ) {
+ int len = prefix.length();
+ str = str.replace('/', '.'); // Is `/' on all systems, even DOS
+ if (chopit) {
+ // If string starts with `prefix' and contains no further dots
+ if (str.startsWith(prefix) && (str.substring(len).indexOf('.') == -1)) {
+ str = str.substring(len);
+ }
+ }
+ return str;
+ }
+
+
+ /**
+ * Shorten long class names, <em>java/lang/String</em> becomes
+ * <em>java.lang.String</em>,
+ * e.g.. If <em>chopit</em> is <em>true</em> the prefix <em>java.lang</em>
+ * is also removed.
+ *
+ * @param str The long class name
+ * @param chopit Flag that determines whether chopping is executed or not
+ * @return Compacted class name
+ */
+ public static final String compactClassName( String str, boolean chopit ) {
+ return compactClassName(str, "java.lang.", chopit);
+ }
+
+
+ /**
+ * @return `flag' with bit `i' set to 1
+ */
+ public static final int setBit( int flag, int i ) {
+ return flag | pow2(i);
+ }
+
+
+ /**
+ * @return `flag' with bit `i' set to 0
+ */
+ public static final int clearBit( int flag, int i ) {
+ int bit = pow2(i);
+ return (flag & bit) == 0 ? flag : flag ^ bit;
+ }
+
+
+ /**
+ * @return true, if bit `i' in `flag' is set
+ */
+ public static final boolean isSet( int flag, int i ) {
+ return (flag & pow2(i)) != 0;
+ }
+
+
+ /**
+ * Converts string containing the method return and argument types
+ * to a byte code method signature.
+ *
+ * @param ret Return type of method
+ * @param argv Types of method arguments
+ * @return Byte code representation of method signature
+ */
+ public final static String methodTypeToSignature( String ret, String[] argv )
+ throws ClassFormatException {
+ StringBuffer buf = new StringBuffer("(");
+ String str;
+ if (argv != null) {
+ for (int i = 0; i < argv.length; i++) {
+ str = getSignature(argv[i]);
+ if (str.endsWith("V")) {
+ throw new ClassFormatException("Invalid type: " + argv[i]);
+ }
+ buf.append(str);
+ }
+ }
+ str = getSignature(ret);
+ buf.append(")").append(str);
+ return buf.toString();
+ }
+
+
+ /**
+ * @param signature Method signature
+ * @return Array of argument types
+ * @throws ClassFormatException
+ */
+ public static final String[] methodSignatureArgumentTypes( String signature )
+ throws ClassFormatException {
+ return methodSignatureArgumentTypes(signature, true);
+ }
+
+
+ /**
+ * @param signature Method signature
+ * @param chopit Shorten class names ?
+ * @return Array of argument types
+ * @throws ClassFormatException
+ */
+ public static final String[] methodSignatureArgumentTypes( String signature, boolean chopit )
+ throws ClassFormatException {
+ List vec = new ArrayList();
+ int index;
+ try { // Read all declarations between for `(' and `)'
+ if (signature.charAt(0) != '(') {
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ index = 1; // current string position
+ while (signature.charAt(index) != ')') {
+ vec.add(signatureToString(signature.substring(index), chopit));
+ //corrected concurrent private static field acess
+ index += unwrap(consumed_chars); // update position
+ }
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ return (String[]) vec.toArray(new String[vec.size()]);
+ }
+
+
+ /**
+ * @param signature Method signature
+ * @return return type of method
+ * @throws ClassFormatException
+ */
+ public static final String methodSignatureReturnType( String signature )
+ throws ClassFormatException {
+ return methodSignatureReturnType(signature, true);
+ }
+
+
+ /**
+ * @param signature Method signature
+ * @param chopit Shorten class names ?
+ * @return return type of method
+ * @throws ClassFormatException
+ */
+ public static final String methodSignatureReturnType( String signature, boolean chopit )
+ throws ClassFormatException {
+ int index;
+ String type;
+ try {
+ // Read return type after `)'
+ index = signature.lastIndexOf(')') + 1;
+ type = signatureToString(signature.substring(index), chopit);
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ return type;
+ }
+
+
+ /**
+ * Converts method signature to string with all class names compacted.
+ *
+ * @param signature to convert
+ * @param name of method
+ * @param access flags of method
+ * @return Human readable signature
+ */
+ public static final String methodSignatureToString( String signature, String name, String access ) {
+ return methodSignatureToString(signature, name, access, true);
+ }
+
+
+ public static final String methodSignatureToString( String signature, String name,
+ String access, boolean chopit ) {
+ return methodSignatureToString(signature, name, access, chopit, null);
+ }
+
+
+ /**
+ * A returntype signature represents the return value from a method.
+ * It is a series of bytes in the following grammar:
+ *
+ * <return_signature> ::= <field_type> | V
+ *
+ * The character V indicates that the method returns no value. Otherwise, the
+ * signature indicates the type of the return value.
+ * An argument signature represents an argument passed to a method:
+ *
+ * <argument_signature> ::= <field_type>
+ *
+ * A method signature represents the arguments that the method expects, and
+ * the value that it returns.
+ * <method_signature> ::= (<arguments_signature>) <return_signature>
+ * <arguments_signature>::= <argument_signature>*
+ *
+ * This method converts such a string into a Java type declaration like
+ * `void main(String[])' and throws a `ClassFormatException' when the parsed
+ * type is invalid.
+ *
+ * @param signature Method signature
+ * @param name Method name
+ * @param access Method access rights
+ * @return Java type declaration
+ * @throws ClassFormatException
+ */
+ public static final String methodSignatureToString( String signature, String name,
+ String access, boolean chopit, LocalVariableTable vars ) throws ClassFormatException {
+ StringBuffer buf = new StringBuffer("(");
+ String type;
+ int index;
+ int var_index = (access.indexOf("static") >= 0) ? 0 : 1;
+ try { // Read all declarations between for `(' and `)'
+ if (signature.charAt(0) != '(') {
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ index = 1; // current string position
+ while (signature.charAt(index) != ')') {
+ String param_type = signatureToString(signature.substring(index), chopit);
+ buf.append(param_type);
+ if (vars != null) {
+ LocalVariable l = vars.getLocalVariable(var_index);
+ if (l != null) {
+ buf.append(" ").append(l.getName());
+ }
+ } else {
+ buf.append(" arg").append(var_index);
+ }
+ if ("double".equals(param_type) || "long".equals(param_type)) {
+ var_index += 2;
+ } else {
+ var_index++;
+ }
+ buf.append(", ");
+ //corrected concurrent private static field acess
+ index += unwrap(consumed_chars); // update position
+ }
+ index++; // update position
+ // Read return type after `)'
+ type = signatureToString(signature.substring(index), chopit);
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ if (buf.length() > 1) {
+ buf.setLength(buf.length() - 2);
+ }
+ buf.append(")");
+ return access + ((access.length() > 0) ? " " : "") + // May be an empty string
+ type + " " + name + buf.toString();
+ }
+
+
+ // Guess what this does
+ private static final int pow2( int n ) {
+ return 1 << n;
+ }
+
+
+ /**
+ * Replace all occurrences of <em>old</em> in <em>str</em> with <em>new</em>.
+ *
+ * @param str String to permute
+ * @param old String to be replaced
+ * @param new_ Replacement string
+ * @return new String object
+ */
+ public static final String replace( String str, String old, String new_ ) {
+ int index, old_index;
+ try {
+ if ((index = str.indexOf(old)) != -1) { // `old' found in str
+ StringBuffer buf = new StringBuffer();
+ old_index = 0; // String start offset
+ // While we have something to replace
+ while ((index = str.indexOf(old, old_index)) != -1) {
+ buf.append(str.substring(old_index, index)); // append prefix
+ buf.append(new_); // append replacement
+ old_index = index + old.length(); // Skip `old'.length chars
+ }
+ buf.append(str.substring(old_index)); // append rest of string
+ str = buf.toString();
+ }
+ } catch (StringIndexOutOfBoundsException e) { // Should not occur
+ System.err.println(e);
+ }
+ return str;
+ }
+
+
+ /**
+ * Converts signature to string with all class names compacted.
+ *
+ * @param signature to convert
+ * @return Human readable signature
+ */
+ public static final String signatureToString( String signature ) {
+ return signatureToString(signature, true);
+ }
+
+
+ /**
+ * The field signature represents the value of an argument to a function or
+ * the value of a variable. It is a series of bytes generated by the
+ * following grammar:
+ *
+ * <PRE>
+ * <field_signature> ::= <field_type>
+ * <field_type> ::= <base_type>|<object_type>|<array_type>
+ * <base_type> ::= B|C|D|F|I|J|S|Z
+ * <object_type> ::= L<fullclassname>;
+ * <array_type> ::= [<field_type>
+ *
+ * The meaning of the base types is as follows:
+ * B byte signed byte
+ * C char character
+ * D double double precision IEEE float
+ * F float single precision IEEE float
+ * I int integer
+ * J long long integer
+ * L<fullclassname>; ... an object of the given class
+ * S short signed short
+ * Z boolean true or false
+ * [<field sig> ... array
+ * </PRE>
+ *
+ * This method converts this string into a Java type declaration such as
+ * `String[]' and throws a `ClassFormatException' when the parsed type is
+ * invalid.
+ *
+ * @param signature Class signature
+ * @param chopit Flag that determines whether chopping is executed or not
+ * @return Java type declaration
+ * @throws ClassFormatException
+ */
+ public static final String signatureToString( String signature, boolean chopit ) {
+ //corrected concurrent private static field acess
+ wrap(consumed_chars, 1); // This is the default, read just one char like `B'
+ try {
+ switch (signature.charAt(0)) {
+ case 'B':
+ return "byte";
+ case 'C':
+ return "char";
+ case 'D':
+ return "double";
+ case 'F':
+ return "float";
+ case 'I':
+ return "int";
+ case 'J':
+ return "long";
+ case 'L': { // Full class name
+ int index = signature.indexOf(';'); // Look for closing `;'
+ if (index < 0) {
+ throw new ClassFormatException("Invalid signature: " + signature);
+ }
+ //corrected concurrent private static field acess
+ wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed
+ return compactClassName(signature.substring(1, index), chopit);
+ }
+ case 'S':
+ return "short";
+ case 'Z':
+ return "boolean";
+ case '[': { // Array declaration
+ int n;
+ StringBuffer brackets;
+ String type;
+ int consumed_chars; // Shadows global var
+ brackets = new StringBuffer(); // Accumulate []'s
+ // Count opening brackets and look for optional size argument
+ for (n = 0; signature.charAt(n) == '['; n++) {
+ brackets.append("[]");
+ }
+ consumed_chars = n; // Remember value
+ // The rest of the string denotes a `<field_type>'
+ type = signatureToString(signature.substring(n), chopit);
+ //corrected concurrent private static field acess
+ //Utility.consumed_chars += consumed_chars; is replaced by:
+ int _temp = unwrap(Utility.consumed_chars) + consumed_chars;
+ wrap(Utility.consumed_chars, _temp);
+ return type + brackets.toString();
+ }
+ case 'V':
+ return "void";
+ default:
+ throw new ClassFormatException("Invalid signature: `" + signature + "'");
+ }
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid signature: " + signature, e);
+ }
+ }
+
+
+ /** Parse Java type such as "char", or "java.lang.String[]" and return the
+ * signature in byte code format, e.g. "C" or "[Ljava/lang/String;" respectively.
+ *
+ * @param type Java type
+ * @return byte code signature
+ */
+ public static String getSignature( String type ) {
+ StringBuffer buf = new StringBuffer();
+ char[] chars = type.toCharArray();
+ boolean char_found = false, delim = false;
+ int index = -1;
+ loop: for (int i = 0; i < chars.length; i++) {
+ switch (chars[i]) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\f':
+ if (char_found) {
+ delim = true;
+ }
+ break;
+ case '[':
+ if (!char_found) {
+ throw new RuntimeException("Illegal type: " + type);
+ }
+ index = i;
+ break loop;
+ default:
+ char_found = true;
+ if (!delim) {
+ buf.append(chars[i]);
+ }
+ }
+ }
+ int brackets = 0;
+ if (index > 0) {
+ brackets = countBrackets(type.substring(index));
+ }
+ type = buf.toString();
+ buf.setLength(0);
+ for (int i = 0; i < brackets; i++) {
+ buf.append('[');
+ }
+ boolean found = false;
+ for (int i = Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) {
+ if (Constants.TYPE_NAMES[i].equals(type)) {
+ found = true;
+ buf.append(Constants.SHORT_TYPE_NAMES[i]);
+ }
+ }
+ if (!found) {
+ buf.append('L').append(type.replace('.', '/')).append(';');
+ }
+ return buf.toString();
+ }
+
+
+ private static int countBrackets( String brackets ) {
+ char[] chars = brackets.toCharArray();
+ int count = 0;
+ boolean open = false;
+ for (int i = 0; i < chars.length; i++) {
+ switch (chars[i]) {
+ case '[':
+ if (open) {
+ throw new RuntimeException("Illegally nested brackets:" + brackets);
+ }
+ open = true;
+ break;
+ case ']':
+ if (!open) {
+ throw new RuntimeException("Illegally nested brackets:" + brackets);
+ }
+ open = false;
+ count++;
+ break;
+ default:
+ // Don't care
+ }
+ }
+ if (open) {
+ throw new RuntimeException("Illegally nested brackets:" + brackets);
+ }
+ return count;
+ }
+
+
+ /**
+ * Return type of method signature as a byte value as defined in <em>Constants</em>
+ *
+ * @param signature in format described above
+ * @return type of method signature
+ * @see Constants
+ */
+ public static final byte typeOfMethodSignature( String signature ) throws ClassFormatException {
+ int index;
+ try {
+ if (signature.charAt(0) != '(') {
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ index = signature.lastIndexOf(')') + 1;
+ return typeOfSignature(signature.substring(index));
+ } catch (StringIndexOutOfBoundsException e) {
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ }
+
+
+ /**
+ * Return type of signature as a byte value as defined in <em>Constants</em>
+ *
+ * @param signature in format described above
+ * @return type of signature
+ * @see Constants
+ */
+ public static final byte typeOfSignature( String signature ) throws ClassFormatException {
+ try {
+ switch (signature.charAt(0)) {
+ case 'B':
+ return Constants.T_BYTE;
+ case 'C':
+ return Constants.T_CHAR;
+ case 'D':
+ return Constants.T_DOUBLE;
+ case 'F':
+ return Constants.T_FLOAT;
+ case 'I':
+ return Constants.T_INT;
+ case 'J':
+ return Constants.T_LONG;
+ case 'L':
+ return Constants.T_REFERENCE;
+ case '[':
+ return Constants.T_ARRAY;
+ case 'V':
+ return Constants.T_VOID;
+ case 'Z':
+ return Constants.T_BOOLEAN;
+ case 'S':
+ return Constants.T_SHORT;
+ default:
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ } catch (StringIndexOutOfBoundsException e) {
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ }
+
+
+ /** Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload"
+ */
+ public static short searchOpcode( String name ) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ for (short i = 0; i < Constants.OPCODE_NAMES.length; i++) {
+ if (Constants.OPCODE_NAMES[i].equals(name)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Convert (signed) byte to (unsigned) short value, i.e., all negative
+ * values become positive.
+ */
+ private static final short byteToShort( byte b ) {
+ return (b < 0) ? (short) (256 + b) : (short) b;
+ }
+
+
+ /** Convert bytes into hexidecimal string
+ *
+ * @return bytes as hexidecimal string, e.g. 00 FA 12 ...
+ */
+ public static final String toHexString( byte[] bytes ) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < bytes.length; i++) {
+ short b = byteToShort(bytes[i]);
+ String hex = Integer.toString(b, 0x10);
+ if (b < 0x10) {
+ buf.append('0');
+ }
+ buf.append(hex);
+ if (i < bytes.length - 1) {
+ buf.append(' ');
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Return a string for an integer justified left or right and filled up with
+ * `fill' characters if necessary.
+ *
+ * @param i integer to format
+ * @param length length of desired string
+ * @param left_justify format left or right
+ * @param fill fill character
+ * @return formatted int
+ */
+ public static final String format( int i, int length, boolean left_justify, char fill ) {
+ return fillup(Integer.toString(i), length, left_justify, fill);
+ }
+
+
+ /**
+ * Fillup char with up to length characters with char `fill' and justify it left or right.
+ *
+ * @param str string to format
+ * @param length length of desired string
+ * @param left_justify format left or right
+ * @param fill fill character
+ * @return formatted string
+ */
+ public static final String fillup( String str, int length, boolean left_justify, char fill ) {
+ int len = length - str.length();
+ char[] buf = new char[(len < 0) ? 0 : len];
+ for (int j = 0; j < buf.length; j++) {
+ buf[j] = fill;
+ }
+ if (left_justify) {
+ return str + new String(buf);
+ }
+ return new String(buf) + str;
+ }
+
+
+ static final boolean equals( byte[] a, byte[] b ) {
+ int size;
+ if ((size = a.length) != b.length) {
+ return false;
+ }
+ for (int i = 0; i < size; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public static final void printArray( PrintStream out, Object[] obj ) {
+ out.println(printArray(obj, true));
+ }
+
+
+ public static final void printArray( PrintWriter out, Object[] obj ) {
+ out.println(printArray(obj, true));
+ }
+
+
+ public static final String printArray( Object[] obj ) {
+ return printArray(obj, true);
+ }
+
+
+ public static final String printArray( Object[] obj, boolean braces ) {
+ return printArray(obj, braces, false);
+ }
+
+
+ public static final String printArray( Object[] obj, boolean braces, boolean quote ) {
+ if (obj == null) {
+ return null;
+ }
+ StringBuffer buf = new StringBuffer();
+ if (braces) {
+ buf.append('{');
+ }
+ for (int i = 0; i < obj.length; i++) {
+ if (obj[i] != null) {
+ buf.append((quote ? "\"" : "")).append(obj[i].toString()).append(
+ (quote ? "\"" : ""));
+ } else {
+ buf.append("null");
+ }
+ if (i < obj.length - 1) {
+ buf.append(", ");
+ }
+ }
+ if (braces) {
+ buf.append('}');
+ }
+ return buf.toString();
+ }
+
+
+ /** @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _)
+ */
+ public static boolean isJavaIdentifierPart( char ch ) {
+ return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))
+ || ((ch >= '0') && (ch <= '9')) || (ch == '_');
+ }
+
+
+ /** Encode byte array it into Java identifier string, i.e., a string
+ * that only contains the following characters: (a, ... z, A, ... Z,
+ * 0, ... 9, _, $). The encoding algorithm itself is not too
+ * clever: if the current byte's ASCII value already is a valid Java
+ * identifier part, leave it as it is. Otherwise it writes the
+ * escape character($) followed by <p><ul><li> the ASCII value as a
+ * hexadecimal string, if the value is not in the range
+ * 200..247</li> <li>a Java identifier char not used in a lowercase
+ * hexadecimal string, if the value is in the range
+ * 200..247</li><ul></p>
+ *
+ * <p>This operation inflates the original byte array by roughly 40-50%</p>
+ *
+ * @param bytes the byte array to convert
+ * @param compress use gzip to minimize string
+ */
+ public static String encode( byte[] bytes, boolean compress ) throws IOException {
+ if (compress) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ GZIPOutputStream gos = new GZIPOutputStream(baos);
+ gos.write(bytes, 0, bytes.length);
+ gos.close();
+ baos.close();
+ bytes = baos.toByteArray();
+ }
+ CharArrayWriter caw = new CharArrayWriter();
+ JavaWriter jw = new JavaWriter(caw);
+ for (int i = 0; i < bytes.length; i++) {
+ int in = bytes[i] & 0x000000ff; // Normalize to unsigned
+ jw.write(in);
+ }
+ return caw.toString();
+ }
+
+
+ /** Decode a string back to a byte array.
+ *
+ * @param s the string to convert
+ * @param uncompress use gzip to uncompress the stream of bytes
+ */
+ public static byte[] decode( String s, boolean uncompress ) throws IOException {
+ char[] chars = s.toCharArray();
+ CharArrayReader car = new CharArrayReader(chars);
+ JavaReader jr = new JavaReader(car);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ int ch;
+ while ((ch = jr.read()) >= 0) {
+ bos.write(ch);
+ }
+ bos.close();
+ car.close();
+ jr.close();
+ byte[] bytes = bos.toByteArray();
+ if (uncompress) {
+ GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes));
+ byte[] tmp = new byte[bytes.length * 3]; // Rough estimate
+ int count = 0;
+ int b;
+ while ((b = gis.read()) >= 0) {
+ tmp[count++] = (byte) b;
+ }
+ bytes = new byte[count];
+ System.arraycopy(tmp, 0, bytes, 0, count);
+ }
+ return bytes;
+ }
+
+ // A-Z, g-z, _, $
+ private static final int FREE_CHARS = 48;
+ static int[] CHAR_MAP = new int[FREE_CHARS];
+ static int[] MAP_CHAR = new int[256]; // Reverse map
+ private static final char ESCAPE_CHAR = '$';
+ static {
+ int j = 0;
+ for (int i = 'A'; i <= 'Z'; i++) {
+ CHAR_MAP[j] = i;
+ MAP_CHAR[i] = j;
+ j++;
+ }
+ for (int i = 'g'; i <= 'z'; i++) {
+ CHAR_MAP[j] = i;
+ MAP_CHAR[i] = j;
+ j++;
+ }
+ CHAR_MAP[j] = '$';
+ MAP_CHAR['$'] = j;
+ j++;
+ CHAR_MAP[j] = '_';
+ MAP_CHAR['_'] = j;
+ }
+
+ /** Decode characters into bytes.
+ * Used by <a href="Utility.html#decode(java.lang.String, boolean)">decode()</a>
+ */
+ private static class JavaReader extends FilterReader {
+
+ public JavaReader(Reader in) {
+ super(in);
+ }
+
+
+ public int read() throws IOException {
+ int b = in.read();
+ if (b != ESCAPE_CHAR) {
+ return b;
+ }
+ int i = in.read();
+ if (i < 0) {
+ return -1;
+ }
+ if (((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { // Normal escape
+ int j = in.read();
+ if (j < 0) {
+ return -1;
+ }
+ char[] tmp = {
+ (char) i, (char) j
+ };
+ int s = Integer.parseInt(new String(tmp), 16);
+ return s;
+ }
+ return MAP_CHAR[i];
+ }
+
+
+ public int read( char[] cbuf, int off, int len ) throws IOException {
+ for (int i = 0; i < len; i++) {
+ cbuf[off + i] = (char) read();
+ }
+ return len;
+ }
+ }
+
+ /** Encode bytes into valid java identifier characters.
+ * Used by <a href="Utility.html#encode(byte[], boolean)">encode()</a>
+ */
+ private static class JavaWriter extends FilterWriter {
+
+ public JavaWriter(Writer out) {
+ super(out);
+ }
+
+
+ public void write( int b ) throws IOException {
+ if (isJavaIdentifierPart((char) b) && (b != ESCAPE_CHAR)) {
+ out.write(b);
+ } else {
+ out.write(ESCAPE_CHAR); // Escape character
+ // Special escape
+ if (b >= 0 && b < FREE_CHARS) {
+ out.write(CHAR_MAP[b]);
+ } else { // Normal escape
+ char[] tmp = Integer.toHexString(b).toCharArray();
+ if (tmp.length == 1) {
+ out.write('0');
+ out.write(tmp[0]);
+ } else {
+ out.write(tmp[0]);
+ out.write(tmp[1]);
+ }
+ }
+ }
+ }
+
+
+ public void write( char[] cbuf, int off, int len ) throws IOException {
+ for (int i = 0; i < len; i++) {
+ write(cbuf[off + i]);
+ }
+ }
+
+
+ public void write( String str, int off, int len ) throws IOException {
+ write(str.toCharArray(), off, len);
+ }
+ }
+
+
+ /**
+ * Escape all occurences of newline chars '\n', quotes \", etc.
+ */
+ public static final String convertString( String label ) {
+ char[] ch = label.toCharArray();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < ch.length; i++) {
+ switch (ch[i]) {
+ case '\n':
+ buf.append("\\n");
+ break;
+ case '\r':
+ buf.append("\\r");
+ break;
+ case '\"':
+ buf.append("\\\"");
+ break;
+ case '\'':
+ buf.append("\\'");
+ break;
+ case '\\':
+ buf.append("\\\\");
+ break;
+ default:
+ buf.append(ch[i]);
+ break;
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Converts a list of AnnotationGen objects into a set of attributes
+ * that can be attached to the class file.
+ *
+ * @param cp The constant pool gen where we can create the necessary name refs
+ * @param vec A list of AnnotationGen objects
+ */
+ public static Attribute[] getAnnotationAttributes(ConstantPoolGen cp,List vec) {
+
+ if (vec.isEmpty()) return new Attribute[0];
+
+ try {
+ int countVisible = 0;
+ int countInvisible = 0;
+
+ // put the annotations in the right output stream
+ for (int i=0; i<vec.size(); i++) {
+ AnnotationEntryGen a = (AnnotationEntryGen)vec.get(i);
+ if (a.isRuntimeVisible()) countVisible++;
+ else countInvisible++;
+ }
+
+ ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
+ ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
+ DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
+ DataOutputStream riaDos = new DataOutputStream(riaBytes);
+
+ rvaDos.writeShort(countVisible);
+ riaDos.writeShort(countInvisible);
+
+ // put the annotations in the right output stream
+ for (int i=0; i<vec.size(); i++) {
+ AnnotationEntryGen a = (AnnotationEntryGen)vec.get(i);
+ if (a.isRuntimeVisible()) a.dump(rvaDos);
+ else a.dump(riaDos);
+ }
+
+ rvaDos.close();
+ riaDos.close();
+
+ byte[] rvaData = rvaBytes.toByteArray();
+ byte[] riaData = riaBytes.toByteArray();
+
+ int rvaIndex = -1;
+ int riaIndex = -1;
+
+ if (rvaData.length>2) rvaIndex = cp.addUtf8("RuntimeVisibleAnnotations");
+ if (riaData.length>2) riaIndex = cp.addUtf8("RuntimeInvisibleAnnotations");
+
+ List newAttributes = new ArrayList();
+ if (rvaData.length>2) {
+
+ newAttributes.add(
+ new RuntimeVisibleAnnotations(rvaIndex,rvaData.length,new DataInputStream(new ByteArrayInputStream(rvaData)),cp.getConstantPool()));
+ }
+ if (riaData.length>2) {
+ newAttributes.add(
+ new RuntimeInvisibleAnnotations(riaIndex,riaData.length,new DataInputStream(new ByteArrayInputStream(riaData)),cp.getConstantPool()));
+ }
+
+ return (Attribute[])newAttributes.toArray(new Attribute[newAttributes.size()]);
+ } catch (IOException e) {
+ System.err.println("IOException whilst processing annotations");
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ /**
+ * Annotations against a class are stored in one of four attribute kinds:
+ * - RuntimeVisibleParameterAnnotations
+ * - RuntimeInvisibleParameterAnnotations
+ */
+ public static Attribute[] getParameterAnnotationAttributes(
+ ConstantPoolGen cp,
+ List[] /*Array of lists, array size depends on #params */vec)
+ {
+ int visCount[] = new int[vec.length];
+ int totalVisCount = 0;
+ int invisCount[] = new int[vec.length];
+ int totalInvisCount = 0;
+ try
+ {
+ for (int i = 0; i < vec.length; i++)
+ {
+ List l = vec[i];
+ if (l != null)
+ {
+ for (Iterator iter = l.iterator(); iter.hasNext();)
+ {
+ AnnotationEntryGen element = (AnnotationEntryGen) iter.next();
+ if (element.isRuntimeVisible())
+ {
+ visCount[i]++;
+ totalVisCount++;
+ }
+ else
+ {
+ invisCount[i]++;
+ totalInvisCount++;
+ }
+ }
+ }
+ }
+ // Lets do the visible ones
+ ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream();
+ DataOutputStream rvaDos = new DataOutputStream(rvaBytes);
+ rvaDos.writeByte(vec.length); // First goes number of parameters
+ for (int i = 0; i < vec.length; i++)
+ {
+ rvaDos.writeShort(visCount[i]);
+ if (visCount[i] > 0)
+ {
+ List l = vec[i];
+ for (Iterator iter = l.iterator(); iter.hasNext();)
+ {
+ AnnotationEntryGen element = (AnnotationEntryGen) iter.next();
+ if (element.isRuntimeVisible())
+ element.dump(rvaDos);
+ }
+ }
+ }
+ rvaDos.close();
+ // Lets do the invisible ones
+ ByteArrayOutputStream riaBytes = new ByteArrayOutputStream();
+ DataOutputStream riaDos = new DataOutputStream(riaBytes);
+ riaDos.writeByte(vec.length); // First goes number of parameters
+ for (int i = 0; i < vec.length; i++)
+ {
+ riaDos.writeShort(invisCount[i]);
+ if (invisCount[i] > 0)
+ {
+ List l = vec[i];
+ for (Iterator iter = l.iterator(); iter.hasNext();)
+ {
+ AnnotationEntryGen element = (AnnotationEntryGen) iter.next();
+ if (!element.isRuntimeVisible())
+ element.dump(riaDos);
+ }
+ }
+ }
+ riaDos.close();
+ byte[] rvaData = rvaBytes.toByteArray();
+ byte[] riaData = riaBytes.toByteArray();
+ int rvaIndex = -1;
+ int riaIndex = -1;
+ if (totalVisCount > 0)
+ rvaIndex = cp.addUtf8("RuntimeVisibleParameterAnnotations");
+ if (totalInvisCount > 0)
+ riaIndex = cp.addUtf8("RuntimeInvisibleParameterAnnotations");
+ List newAttributes = new ArrayList();
+ if (totalVisCount > 0)
+ {
+ newAttributes
+ .add(new RuntimeVisibleParameterAnnotations(rvaIndex,
+ rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool()));
+ }
+ if (totalInvisCount > 0)
+ {
+ newAttributes
+ .add(new RuntimeInvisibleParameterAnnotations(riaIndex,
+ riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool()));
+ }
+ return (Attribute[]) newAttributes.toArray(new Attribute[newAttributes.size()]);
+ }
+ catch (IOException e)
+ {
+ System.err
+ .println("IOException whilst processing parameter annotations");
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.classfile;
+
+/**
+ * Interface to make use of the Visitor pattern programming style. I.e. a class
+ * that implements this interface can traverse the contents of a Java class just
+ * by calling the `accept' method which all classes have.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface Visitor
+{
+ public void visitCode(Code obj);
+
+ public void visitCodeException(CodeException obj);
+
+ public void visitConstantClass(ConstantClass obj);
+
+ public void visitConstantDouble(ConstantDouble obj);
+
+ public void visitConstantFieldref(ConstantFieldref obj);
+
+ public void visitConstantFloat(ConstantFloat obj);
+
+ public void visitConstantInteger(ConstantInteger obj);
+
+ public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj);
+
+ public void visitConstantLong(ConstantLong obj);
+
+ public void visitConstantMethodref(ConstantMethodref obj);
+
+ public void visitConstantNameAndType(ConstantNameAndType obj);
+
+ public void visitConstantPool(ConstantPool obj);
+
+ public void visitConstantString(ConstantString obj);
+
+ public void visitConstantUtf8(ConstantUtf8 obj);
+
+ public void visitConstantValue(ConstantValue obj);
+
+ public void visitDeprecated(Deprecated obj);
+
+ public void visitExceptionTable(ExceptionTable obj);
+
+ public void visitField(Field obj);
+
+ public void visitInnerClass(InnerClass obj);
+
+ public void visitInnerClasses(InnerClasses obj);
+
+ public void visitJavaClass(JavaClass obj);
+
+ public void visitLineNumber(LineNumber obj);
+
+ public void visitLineNumberTable(LineNumberTable obj);
+
+ public void visitLocalVariable(LocalVariable obj);
+
+ public void visitLocalVariableTable(LocalVariableTable obj);
+
+ public void visitMethod(Method obj);
+
+ public void visitSignature(Signature obj);
+
+ public void visitSourceFile(SourceFile obj);
+
+ public void visitSynthetic(Synthetic obj);
+
+ public void visitUnknown(Unknown obj);
+
+ public void visitStackMap(StackMap obj);
+
+ public void visitStackMapEntry(StackMapEntry obj);
+
+ public void visitStackMapTable(StackMapTable obj);
+
+ public void visitStackMapTableEntry(StackMapTableEntry obj);
+
+ public void visitAnnotation(Annotations obj);
+
+ public void visitParameterAnnotation(ParameterAnnotations obj);
+
+ public void visitAnnotationEntry(AnnotationEntry obj);
+
+ public void visitAnnotationDefault(AnnotationDefault obj);
+
+ public void visitLocalVariableTypeTable(LocalVariableTypeTable obj);
+
+ public void visitEnclosingMethod(EnclosingMethod obj);
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+$Id$
+-->
+</head>
+<body bgcolor="white">
+<p>
+This package contains the classes that describe the structure of a
+Java class file and a class file parser.
+</p>
+</body>
+</html>
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * AALOAD - Load reference from array
+ * <PRE>Stack: ..., arrayref, index -> value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class AALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load reference from array
+ */
+ public AALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.AALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitAALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * AASTORE - Store into reference array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class AASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store into reference array
+ */
+ public AASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.AASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitAASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ACONST_NULL - Push null reference
+ * <PRE>Stack: ... -> ..., null</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ACONST_NULL extends Instruction implements PushInstruction, TypedInstruction {
+
+ /**
+ * Push null reference
+ */
+ public ACONST_NULL() {
+ super(org.apache.tomcat.util.bcel.Constants.ACONST_NULL, (short) 1);
+ }
+
+
+ /** @return Type.NULL
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.NULL;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitACONST_NULL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ALOAD - Load reference from local variable
+ * <PRE>Stack: ... -> ..., objectref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ALOAD extends LoadInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.ALOAD, org.apache.tomcat.util.bcel.Constants.ALOAD_0);
+ }
+
+
+ /** Load reference from local variable
+ * @param n index of local variable
+ */
+ public ALOAD(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.ALOAD, org.apache.tomcat.util.bcel.Constants.ALOAD_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * ANEWARRAY - Create new array of references
+ * <PRE>Stack: ..., count -> ..., arrayref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction,
+ ExceptionThrower, StackConsumer, StackProducer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ANEWARRAY() {
+ }
+
+
+ public ANEWARRAY(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.ANEWARRAY, index);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[1 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLoadClass(this);
+ v.visitAllocationInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitANEWARRAY(this);
+ }
+
+
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ Type t = getType(cpg);
+ if (t instanceof ArrayType) {
+ t = ((ArrayType) t).getBasicType();
+ }
+ return (t instanceof ObjectType) ? (ObjectType) t : null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ARETURN - Return reference from method
+ * <PRE>Stack: ..., objectref -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ARETURN extends ReturnInstruction {
+
+ /**
+ * Return reference from method
+ */
+ public ARETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.ARETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitARETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ARRAYLENGTH - Get length of array
+ * <PRE>Stack: ..., arrayref -> ..., length</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer {
+
+ /** Get length of array
+ */
+ public ARRAYLENGTH() {
+ super(org.apache.tomcat.util.bcel.Constants.ARRAYLENGTH, (short) 1);
+ }
+
+
+ /** @return exceptions this instruction may cause
+ */
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitARRAYLENGTH(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ASTORE - Store reference into local variable
+ * <PRE>Stack ..., objectref -> ... </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ASTORE extends StoreInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.ASTORE, org.apache.tomcat.util.bcel.Constants.ASTORE_0);
+ }
+
+
+ /** Store reference into local variable
+ * @param n index of local variable
+ */
+ public ASTORE(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.ASTORE, org.apache.tomcat.util.bcel.Constants.ASTORE_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ATHROW - Throw exception
+ * <PRE>Stack: ..., objectref -> objectref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower {
+
+ /**
+ * Throw exception
+ */
+ public ATHROW() {
+ super(org.apache.tomcat.util.bcel.Constants.ATHROW, (short) 1);
+ }
+
+
+ /** @return exceptions this instruction may cause
+ */
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.THROWABLE
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitUnconditionalBranch(this);
+ v.visitExceptionThrower(this);
+ v.visitATHROW(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote family of instructions that allocates space in the heap.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface AllocationInstruction {
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+
+public class AnnotationElementValueGen extends ElementValueGen
+{
+ // For annotation element values, this is the annotation
+ private AnnotationEntryGen a;
+
+ public AnnotationElementValueGen(AnnotationEntryGen a, ConstantPoolGen cpool)
+ {
+ super(ANNOTATION, cpool);
+ this.a = a;
+ }
+
+ public AnnotationElementValueGen(int type, AnnotationEntryGen annotation,
+ ConstantPoolGen cpool)
+ {
+ super(type, cpool);
+ if (type != ANNOTATION)
+ throw new RuntimeException(
+ "Only element values of type annotation can be built with this ctor - type specified: " + type);
+ this.a = annotation;
+ }
+
+ public AnnotationElementValueGen(AnnotationElementValue value,
+ ConstantPoolGen cpool, boolean copyPoolEntries)
+ {
+ super(ANNOTATION, cpool);
+ a = new AnnotationEntryGen(value.getAnnotationEntry(), cpool, copyPoolEntries);
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ANNOTATION == '@')
+ a.dump(dos);
+ }
+
+ public String stringifyValue()
+ {
+ throw new RuntimeException("Not implemented yet");
+ }
+
+ /**
+ * Return immutable variant of this AnnotationElementValueGen
+ */
+ public ElementValue getElementValue()
+ {
+ return new AnnotationElementValue(this.type, a.getAnnotation(), cpGen
+ .getConstantPool());
+ }
+
+ public AnnotationEntryGen getAnnotation()
+ {
+ return a;
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ElementValuePair;
+
+
+public class AnnotationEntryGen
+{
+ private int typeIndex;
+
+ private List /* ElementNameValuePairGen */evs;
+
+ private ConstantPoolGen cpool;
+
+ private boolean isRuntimeVisible = false;
+
+ /**
+ * Here we are taking a fixed annotation of type Annotation and building a
+ * modifiable AnnotationGen object. If the pool passed in is for a different
+ * class file, then copyPoolEntries should have been passed as true as that
+ * will force us to do a deep copy of the annotation and move the cpool
+ * entries across. We need to copy the type and the element name value pairs
+ * and the visibility.
+ */
+ public AnnotationEntryGen(AnnotationEntry a, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ this.cpool = cpool;
+ if (copyPoolEntries)
+ {
+ typeIndex = cpool.addUtf8(a.getAnnotationType());
+ }
+ else
+ {
+ typeIndex = a.getAnnotationTypeIndex();
+ }
+ isRuntimeVisible = a.isRuntimeVisible();
+ evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries);
+ }
+
+ private List copyValues(ElementValuePair[] in, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ List out = new ArrayList();
+ int l = in.length;
+ for (int i = 0; i < l; i++)
+ {
+ ElementValuePair nvp = (ElementValuePair) in[i];
+ out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries));
+ }
+ return out;
+ }
+
+ private AnnotationEntryGen(ConstantPoolGen cpool)
+ {
+ this.cpool = cpool;
+ }
+
+ /**
+ * Retrieve an immutable version of this AnnotationGen
+ */
+ public AnnotationEntry getAnnotation()
+ {
+ AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(),
+ isRuntimeVisible);
+ for (Iterator iter = evs.iterator(); iter.hasNext();)
+ {
+ ElementValuePairGen element = (ElementValuePairGen) iter
+ .next();
+ a.addElementNameValuePair(element.getElementNameValuePair());
+ }
+ return a;
+ }
+
+ public AnnotationEntryGen(ObjectType type,
+ List /* ElementNameValuePairGen */elements, boolean vis,
+ ConstantPoolGen cpool)
+ {
+ this.cpool = cpool;
+ this.typeIndex = cpool.addUtf8(type.getSignature());
+ evs = elements;
+ isRuntimeVisible = vis;
+ }
+
+ public static AnnotationEntryGen read(DataInputStream dis,
+ ConstantPoolGen cpool, boolean b) throws IOException
+ {
+ AnnotationEntryGen a = new AnnotationEntryGen(cpool);
+ a.typeIndex = dis.readUnsignedShort();
+ int elemValuePairCount = dis.readUnsignedShort();
+ for (int i = 0; i < elemValuePairCount; i++)
+ {
+ int nidx = dis.readUnsignedShort();
+ a.addElementNameValuePair(new ElementValuePairGen(nidx,
+ ElementValueGen.readElementValue(dis, cpool), cpool));
+ }
+ a.isRuntimeVisible(b);
+ return a;
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeShort(typeIndex); // u2 index of type name in cpool
+ dos.writeShort(evs.size()); // u2 element_value pair count
+ for (int i = 0; i < evs.size(); i++)
+ {
+ ElementValuePairGen envp = (ElementValuePairGen) evs.get(i);
+ envp.dump(dos);
+ }
+ }
+
+ public void addElementNameValuePair(ElementValuePairGen evp)
+ {
+ if (evs == null)
+ evs = new ArrayList();
+ evs.add(evp);
+ }
+
+ public int getTypeIndex()
+ {
+ return typeIndex;
+ }
+
+ public final String getTypeSignature()
+ {
+ // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex);
+ ConstantUtf8 utf8 = (ConstantUtf8) cpool
+ .getConstant(typeIndex/* c.getNameIndex() */);
+ return utf8.getBytes();
+ }
+
+ public final String getTypeName()
+ {
+ return getTypeSignature();// BCELBUG: Should I use this instead?
+ // Utility.signatureToString(getTypeSignature());
+ }
+
+ /**
+ * Returns list of ElementNameValuePair objects
+ */
+ public List getValues()
+ {
+ return evs;
+ }
+
+ public String toString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("AnnotationGen:[" + getTypeName() + " #" + evs.size() + " {");
+ for (int i = 0; i < evs.size(); i++)
+ {
+ s.append(evs.get(i));
+ if (i + 1 < evs.size())
+ s.append(",");
+ }
+ s.append("}]");
+ return s.toString();
+ }
+
+ public String toShortString()
+ {
+ StringBuffer s = new StringBuffer();
+ s.append("@" + getTypeName() + "(");
+ for (int i = 0; i < evs.size(); i++)
+ {
+ s.append(evs.get(i));
+ if (i + 1 < evs.size())
+ s.append(",");
+ }
+ s.append(")");
+ return s.toString();
+ }
+
+ private void isRuntimeVisible(boolean b)
+ {
+ isRuntimeVisible = b;
+ }
+
+ public boolean isRuntimeVisible()
+ {
+ return isRuntimeVisible;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Super class for the family of arithmetic instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class ArithmeticInstruction extends Instruction implements TypedInstruction,
+ StackProducer, StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ArithmeticInstruction() {
+ }
+
+
+ /**
+ * @param opcode of instruction
+ */
+ protected ArithmeticInstruction(short opcode) {
+ super(opcode, (short) 1);
+ }
+
+
+ /** @return type associated with the instruction
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ switch (opcode) {
+ case Constants.DADD:
+ case Constants.DDIV:
+ case Constants.DMUL:
+ case Constants.DNEG:
+ case Constants.DREM:
+ case Constants.DSUB:
+ return Type.DOUBLE;
+ case Constants.FADD:
+ case Constants.FDIV:
+ case Constants.FMUL:
+ case Constants.FNEG:
+ case Constants.FREM:
+ case Constants.FSUB:
+ return Type.FLOAT;
+ case Constants.IADD:
+ case Constants.IAND:
+ case Constants.IDIV:
+ case Constants.IMUL:
+ case Constants.INEG:
+ case Constants.IOR:
+ case Constants.IREM:
+ case Constants.ISHL:
+ case Constants.ISHR:
+ case Constants.ISUB:
+ case Constants.IUSHR:
+ case Constants.IXOR:
+ return Type.INT;
+ case Constants.LADD:
+ case Constants.LAND:
+ case Constants.LDIV:
+ case Constants.LMUL:
+ case Constants.LNEG:
+ case Constants.LOR:
+ case Constants.LREM:
+ case Constants.LSHL:
+ case Constants.LSHR:
+ case Constants.LSUB:
+ case Constants.LUSHR:
+ case Constants.LXOR:
+ return Type.LONG;
+ default: // Never reached
+ throw new ClassGenException("Unknown type " + opcode);
+ }
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.tomcat.util.bcel.classfile.ArrayElementValue;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+
+public class ArrayElementValueGen extends ElementValueGen
+{
+ // J5TODO: Should we make this an array or a list? A list would be easier to
+ // modify ...
+ private List /* ElementValueGen */evalues;
+
+ public ArrayElementValueGen(ConstantPoolGen cp)
+ {
+ super(ARRAY, cp);
+ evalues = new ArrayList();
+ }
+
+ public ArrayElementValueGen(int type, ElementValue[] datums,
+ ConstantPoolGen cpool)
+ {
+ super(type, cpool);
+ if (type != ARRAY)
+ throw new RuntimeException(
+ "Only element values of type array can be built with this ctor - type specified: " + type);
+ this.evalues = new ArrayList();
+ for (int i = 0; i < datums.length; i++)
+ {
+ evalues.add(datums[i]);
+ }
+ }
+
+ /**
+ * Return immutable variant of this ArrayElementValueGen
+ */
+ public ElementValue getElementValue()
+ {
+ ElementValue[] immutableData = new ElementValue[evalues.size()];
+ int i = 0;
+ for (Iterator iter = evalues.iterator(); iter.hasNext();)
+ {
+ ElementValueGen element = (ElementValueGen) iter.next();
+ immutableData[i++] = element.getElementValue();
+ }
+ return new ArrayElementValue(type, immutableData, cpGen
+ .getConstantPool());
+ }
+
+ /**
+ * @param value
+ * @param cpool
+ */
+ public ArrayElementValueGen(ArrayElementValue value, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ super(ARRAY, cpool);
+ evalues = new ArrayList();
+ ElementValue[] in = value.getElementValuesArray();
+ for (int i = 0; i < in.length; i++)
+ {
+ evalues.add(ElementValueGen.copy(in[i], cpool, copyPoolEntries));
+ }
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ARRAY == '[')
+ dos.writeShort(evalues.size());
+ for (Iterator iter = evalues.iterator(); iter.hasNext();)
+ {
+ ElementValueGen element = (ElementValueGen) iter.next();
+ element.dump(dos);
+ }
+ }
+
+ public String stringifyValue()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[");
+ for (Iterator iter = evalues.iterator(); iter.hasNext();)
+ {
+ ElementValueGen element = (ElementValueGen) iter.next();
+ sb.append(element.stringifyValue());
+ if (iter.hasNext())
+ sb.append(",");
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ public List getElementValues()
+ {
+ return evalues;
+ }
+
+ public int getElementValuesSize()
+ {
+ return evalues.size();
+ }
+
+ public void addElement(ElementValueGen gen)
+ {
+ evalues.add(gen);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Super class for instructions dealing with array access such as IALOAD.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class ArrayInstruction extends Instruction implements ExceptionThrower,
+ TypedInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ArrayInstruction() {
+ }
+
+
+ /**
+ * @param opcode of instruction
+ */
+ protected ArrayInstruction(short opcode) {
+ super(opcode, (short) 1);
+ }
+
+
+ public Class[] getExceptions() {
+ return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION;
+ }
+
+
+ /** @return type associated with the instruction
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ switch (opcode) {
+ case org.apache.tomcat.util.bcel.Constants.IALOAD:
+ case org.apache.tomcat.util.bcel.Constants.IASTORE:
+ return Type.INT;
+ case org.apache.tomcat.util.bcel.Constants.CALOAD:
+ case org.apache.tomcat.util.bcel.Constants.CASTORE:
+ return Type.CHAR;
+ case org.apache.tomcat.util.bcel.Constants.BALOAD:
+ case org.apache.tomcat.util.bcel.Constants.BASTORE:
+ return Type.BYTE;
+ case org.apache.tomcat.util.bcel.Constants.SALOAD:
+ case org.apache.tomcat.util.bcel.Constants.SASTORE:
+ return Type.SHORT;
+ case org.apache.tomcat.util.bcel.Constants.LALOAD:
+ case org.apache.tomcat.util.bcel.Constants.LASTORE:
+ return Type.LONG;
+ case org.apache.tomcat.util.bcel.Constants.DALOAD:
+ case org.apache.tomcat.util.bcel.Constants.DASTORE:
+ return Type.DOUBLE;
+ case org.apache.tomcat.util.bcel.Constants.FALOAD:
+ case org.apache.tomcat.util.bcel.Constants.FASTORE:
+ return Type.FLOAT;
+ case org.apache.tomcat.util.bcel.Constants.AALOAD:
+ case org.apache.tomcat.util.bcel.Constants.AASTORE:
+ return Type.OBJECT;
+ default:
+ throw new ClassGenException("Oops: unknown case in switch" + opcode);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Denotes array type, such as int[][]
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ArrayType extends ReferenceType {
+
+ private int dimensions;
+ private Type basic_type;
+
+
+ /**
+ * Convenience constructor for array type, e.g. int[]
+ *
+ * @param type array type, e.g. T_INT
+ */
+ public ArrayType(byte type, int dimensions) {
+ this(BasicType.getType(type), dimensions);
+ }
+
+
+ /**
+ * Convenience constructor for reference array type, e.g. Object[]
+ *
+ * @param class_name complete name of class (java.lang.String, e.g.)
+ */
+ public ArrayType(String class_name, int dimensions) {
+ this(new ObjectType(class_name), dimensions);
+ }
+
+
+ /**
+ * Constructor for array of given type
+ *
+ * @param type type of array (may be an array itself)
+ */
+ public ArrayType(Type type, int dimensions) {
+ super(Constants.T_ARRAY, "<dummy>");
+ if ((dimensions < 1) || (dimensions > Constants.MAX_BYTE)) {
+ throw new ClassGenException("Invalid number of dimensions: " + dimensions);
+ }
+ switch (type.getType()) {
+ case Constants.T_ARRAY:
+ ArrayType array = (ArrayType) type;
+ this.dimensions = dimensions + array.dimensions;
+ basic_type = array.basic_type;
+ break;
+ case Constants.T_VOID:
+ throw new ClassGenException("Invalid type: void[]");
+ default: // Basic type or reference
+ this.dimensions = dimensions;
+ basic_type = type;
+ break;
+ }
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < this.dimensions; i++) {
+ buf.append('[');
+ }
+ buf.append(basic_type.getSignature());
+ signature = buf.toString();
+ }
+
+
+ /**
+ * @return basic type of array, i.e., for int[][][] the basic type is int
+ */
+ public Type getBasicType() {
+ return basic_type;
+ }
+
+
+ /**
+ * @return element type of array, i.e., for int[][][] the element type is int[][]
+ */
+ public Type getElementType() {
+ if (dimensions == 1) {
+ return basic_type;
+ }
+ return new ArrayType(basic_type, dimensions - 1);
+ }
+
+
+ /** @return number of dimensions of array
+ */
+ public int getDimensions() {
+ return dimensions;
+ }
+
+
+ /** @return a hash code value for the object.
+ */
+ public int hashCode() {
+ return basic_type.hashCode() ^ dimensions;
+ }
+
+
+ /** @return true if both type objects refer to the same array type.
+ */
+ public boolean equals( Object _type ) {
+ if (_type instanceof ArrayType) {
+ ArrayType array = (ArrayType) _type;
+ return (array.dimensions == dimensions) && array.basic_type.equals(basic_type);
+ }
+ return false;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * BALOAD - Load byte or boolean from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class BALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load byte or boolean from array
+ */
+ public BALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.BALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitBALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * BASTORE - Store into byte or boolean array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class BASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store byte or boolean into array
+ */
+ public BASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.BASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitBASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * BIPUSH - Push byte on stack
+ *
+ * <PRE>Stack: ... -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class BIPUSH extends Instruction implements ConstantPushInstruction {
+
+ private byte b;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ BIPUSH() {
+ }
+
+
+ /** Push byte on stack
+ */
+ public BIPUSH(byte b) {
+ super(org.apache.tomcat.util.bcel.Constants.BIPUSH, (short) 2);
+ this.b = b;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ super.dump(out);
+ out.writeByte(b);
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + b;
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ length = 2;
+ b = bytes.readByte();
+ }
+
+
+ public Number getValue() {
+ return new Integer(b);
+ }
+
+
+ /** @return Type.BYTE
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.BYTE;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitBIPUSH(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * BREAKPOINT, JVM dependent, ignored by default
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class BREAKPOINT extends Instruction {
+
+ public BREAKPOINT() {
+ super(org.apache.tomcat.util.bcel.Constants.BREAKPOINT, (short) 1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitBREAKPOINT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Denotes basic type such as int.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class BasicType extends Type {
+
+ /**
+ * Constructor for basic types such as int, long, `void'
+ *
+ * @param type one of T_INT, T_BOOLEAN, ..., T_VOID
+ * @see org.apache.tomcat.util.bcel.Constants
+ */
+ BasicType(byte type) {
+ super(type, Constants.SHORT_TYPE_NAMES[type]);
+ if ((type < Constants.T_BOOLEAN) || (type > Constants.T_VOID)) {
+ throw new ClassGenException("Invalid type: " + type);
+ }
+ }
+
+
+ public static final BasicType getType( byte type ) {
+ switch (type) {
+ case Constants.T_VOID:
+ return VOID;
+ case Constants.T_BOOLEAN:
+ return BOOLEAN;
+ case Constants.T_BYTE:
+ return BYTE;
+ case Constants.T_SHORT:
+ return SHORT;
+ case Constants.T_CHAR:
+ return CHAR;
+ case Constants.T_INT:
+ return INT;
+ case Constants.T_LONG:
+ return LONG;
+ case Constants.T_DOUBLE:
+ return DOUBLE;
+ case Constants.T_FLOAT:
+ return FLOAT;
+ default:
+ throw new ClassGenException("Invalid type: " + type);
+ }
+ }
+
+
+ /** @return a hash code value for the object.
+ */
+ public int hashCode() {
+ return type;
+ }
+
+
+ /** @return true if both type objects refer to the same type
+ */
+ public boolean equals( Object _type ) {
+ return (_type instanceof BasicType) ? ((BasicType) _type).type == this.type : false;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * BranchHandle is returned by specialized InstructionList.append() whenever a
+ * BranchInstruction is appended. This is useful when the target of this
+ * instruction is not known at time of creation and must be set later
+ * via setTarget().
+ *
+ * @see InstructionHandle
+ * @see Instruction
+ * @see InstructionList
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class BranchHandle extends InstructionHandle {
+
+ private BranchInstruction bi; // An alias in fact, but saves lots of casts
+
+
+ private BranchHandle(BranchInstruction i) {
+ super(i);
+ bi = i;
+ }
+
+ /** Factory methods.
+ */
+ private static BranchHandle bh_list = null; // List of reusable handles
+
+
+ static final BranchHandle getBranchHandle( BranchInstruction i ) {
+ if (bh_list == null) {
+ return new BranchHandle(i);
+ }
+ BranchHandle bh = bh_list;
+ bh_list = (BranchHandle) bh.next;
+ bh.setInstruction(i);
+ return bh;
+ }
+
+
+ /** Handle adds itself to the list of resuable handles.
+ */
+ protected void addHandle() {
+ next = bh_list;
+ bh_list = this;
+ }
+
+
+ /* Override InstructionHandle methods: delegate to branch instruction.
+ * Through this overriding all access to the private i_position field should
+ * be prevented.
+ */
+ public int getPosition() {
+ return bi.position;
+ }
+
+
+ void setPosition( int pos ) {
+ i_position = bi.position = pos;
+ }
+
+
+ protected int updatePosition( int offset, int max_offset ) {
+ int x = bi.updatePosition(offset, max_offset);
+ i_position = bi.position;
+ return x;
+ }
+
+
+ /**
+ * Pass new target to instruction.
+ */
+ public void setTarget( InstructionHandle ih ) {
+ bi.setTarget(ih);
+ }
+
+
+ /**
+ * Update target of instruction.
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ bi.updateTarget(old_ih, new_ih);
+ }
+
+
+ /**
+ * @return target of instruction.
+ */
+ public InstructionHandle getTarget() {
+ return bi.getTarget();
+ }
+
+
+ /**
+ * Set new contents. Old instruction is disposed and may not be used anymore.
+ */
+ public void setInstruction( Instruction i ) {
+ super.setInstruction(i);
+ if (!(i instanceof BranchInstruction)) {
+ throw new ClassGenException("Assigning " + i
+ + " to branch handle which is not a branch instruction");
+ }
+ bi = (BranchInstruction) i;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Abstract super class for branching instructions like GOTO, IFEQ, etc..
+ * Branch instructions may have a variable length, namely GOTO, JSR,
+ * LOOKUPSWITCH and TABLESWITCH.
+ *
+ * @see InstructionList
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
+
+ protected int index; // Branch target relative to this instruction
+ protected InstructionHandle target; // Target object in instruction list
+ protected int position; // Byte code offset
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ BranchInstruction() {
+ }
+
+
+ /** Common super constructor
+ * @param opcode Instruction opcode
+ * @param target instruction to branch to
+ */
+ protected BranchInstruction(short opcode, InstructionHandle target) {
+ super(opcode, (short) 3);
+ setTarget(target);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ index = getTargetOffset();
+ if (Math.abs(index) >= 32767) {
+ throw new ClassGenException("Branch target offset too large for short: " + index);
+ }
+ out.writeShort(index); // May be negative, i.e., point backwards
+ }
+
+
+ /**
+ * @param _target branch target
+ * @return the offset to `target' relative to this instruction
+ */
+ protected int getTargetOffset( InstructionHandle _target ) {
+ if (_target == null) {
+ throw new ClassGenException("Target of " + super.toString(true)
+ + " is invalid null handle");
+ }
+ int t = _target.getPosition();
+ if (t < 0) {
+ throw new ClassGenException("Invalid branch target position offset for "
+ + super.toString(true) + ":" + t + ":" + _target);
+ }
+ return t - position;
+ }
+
+
+ /**
+ * @return the offset to this instruction's target
+ */
+ protected int getTargetOffset() {
+ return getTargetOffset(target);
+ }
+
+
+ /**
+ * Called by InstructionList.setPositions when setting the position for every
+ * instruction. In the presence of variable length instructions `setPositions'
+ * performs multiple passes over the instruction list to calculate the
+ * correct (byte) positions and offsets by calling this function.
+ *
+ * @param offset additional offset caused by preceding (variable length) instructions
+ * @param max_offset the maximum offset that may be caused by these instructions
+ * @return additional offset caused by possible change of this instruction's length
+ */
+ protected int updatePosition( int offset, int max_offset ) {
+ position += offset;
+ return 0;
+ }
+
+
+ /**
+ * Long output format:
+ *
+ * <position in byte code>
+ * <name of opcode> "["<opcode number>"]"
+ * "("<length of instruction>")"
+ * "<"<target instruction>">" "@"<branch target offset>
+ *
+ * @param verbose long/short format switch
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ String s = super.toString(verbose);
+ String t = "null";
+ if (verbose) {
+ if (target != null) {
+ if (target.getInstruction() == this) {
+ t = "<points to itself>";
+ } else if (target.getInstruction() == null) {
+ t = "<null instruction!!!?>";
+ } else {
+ t = target.getInstruction().toString(false); // Avoid circles
+ }
+ }
+ } else {
+ if (target != null) {
+ index = getTargetOffset();
+ t = "" + (index + position);
+ }
+ }
+ return s + " -> " + t;
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file. Conversion to a InstructionHandle
+ * is done in InstructionList(byte[]).
+ *
+ * @param bytes input stream
+ * @param wide wide prefix?
+ * @see InstructionList
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ length = 3;
+ index = bytes.readShort();
+ }
+
+
+ /**
+ * @return target offset in byte code
+ */
+ public final int getIndex() {
+ return index;
+ }
+
+
+ /**
+ * @return target of branch instruction
+ */
+ public InstructionHandle getTarget() {
+ return target;
+ }
+
+
+ /**
+ * Set branch target
+ * @param target branch target
+ */
+ public void setTarget( InstructionHandle target ) {
+ notifyTarget(this.target, target, this);
+ this.target = target;
+ }
+
+
+ /**
+ * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen
+ */
+ static final void notifyTarget( InstructionHandle old_ih, InstructionHandle new_ih,
+ InstructionTargeter t ) {
+ if (old_ih != null) {
+ old_ih.removeTargeter(t);
+ }
+ if (new_ih != null) {
+ new_ih.addTargeter(t);
+ }
+ }
+
+
+ /**
+ * @param old_ih old target
+ * @param new_ih new target
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ if (target == old_ih) {
+ setTarget(new_ih);
+ } else {
+ throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
+ }
+ }
+
+
+ /**
+ * @return true, if ih is target of this instruction
+ */
+ public boolean containsTarget( InstructionHandle ih ) {
+ return (target == ih);
+ }
+
+
+ /**
+ * Inform target that it's not targeted anymore.
+ */
+ void dispose() {
+ setTarget(null);
+ index = -1;
+ position = -1;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * CALOAD - Load char from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class CALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load char from array
+ */
+ public CALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.CALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitCALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * CASTORE - Store into char array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class CASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store char into array
+ */
+ public CASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.CASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitCASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * CHECKCAST - Check whether object is of given type
+ * <PRE>Stack: ..., objectref -> ..., objectref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class CHECKCAST extends CPInstruction implements LoadClass, ExceptionThrower, StackProducer,
+ StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ CHECKCAST() {
+ }
+
+
+ /** Check whether object is of given type
+ * @param index index to class in constant pool
+ */
+ public CHECKCAST(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.CHECKCAST, index);
+ }
+
+
+ /** @return exceptions this instruction may cause
+ */
+ public Class[] getExceptions() {
+ Class[] cs = new Class[1 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.CLASS_CAST_EXCEPTION;
+ return cs;
+ }
+
+
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ Type t = getType(cpg);
+ if (t instanceof ArrayType) {
+ t = ((ArrayType) t).getBasicType();
+ }
+ return (t instanceof ObjectType) ? (ObjectType) t : null;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLoadClass(this);
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitCHECKCAST(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.classfile.ConstantClass;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Abstract super class for instructions that use an index into the
+ * constant pool such as LDC, INVOKEVIRTUAL, etc.
+ *
+ * @see ConstantPoolGen
+ * @see LDC
+ * @see INVOKEVIRTUAL
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class CPInstruction extends Instruction implements TypedInstruction,
+ IndexedInstruction {
+
+ protected int index; // index to constant pool
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ CPInstruction() {
+ }
+
+
+ /**
+ * @param index to constant pool
+ */
+ protected CPInstruction(short opcode, int index) {
+ super(opcode, (short) 3);
+ setIndex(index);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ out.writeShort(index);
+ }
+
+
+ /**
+ * Long output format:
+ *
+ * <name of opcode> "["<opcode number>"]"
+ * "("<length of instruction>")" "<"< constant pool index>">"
+ *
+ * @param verbose long/short format switch
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + index;
+ }
+
+
+ /**
+ * @return mnemonic for instruction with symbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ Constant c = cp.getConstant(index);
+ String str = cp.constantToString(c);
+ if (c instanceof ConstantClass) {
+ str = str.replace('.', '/');
+ }
+ return org.apache.tomcat.util.bcel.Constants.OPCODE_NAMES[opcode] + " " + str;
+ }
+
+
+ /**
+ * Read needed data (i.e., index) from file.
+ * @param bytes input stream
+ * @param wide wide prefix?
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ setIndex(bytes.readUnsignedShort());
+ length = 3;
+ }
+
+
+ /**
+ * @return index in constant pool referred by this instruction.
+ */
+ public final int getIndex() {
+ return index;
+ }
+
+
+ /**
+ * Set the index to constant pool.
+ * @param index in constant pool.
+ */
+ public void setIndex( int index ) {
+ if (index < 0) {
+ throw new ClassGenException("Negative index value: " + index);
+ }
+ this.index = index;
+ }
+
+
+ /** @return type related with this instruction.
+ */
+ public Type getType( ConstantPoolGen cpg ) {
+ ConstantPool cp = cpg.getConstantPool();
+ String name = cp.getConstantString(index, org.apache.tomcat.util.bcel.Constants.CONSTANT_Class);
+ if (!name.startsWith("[")) {
+ name = "L" + name + ";";
+ }
+ return Type.getType(name);
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ClassElementValue;
+import org.apache.tomcat.util.bcel.generic.ConstantPoolGen;
+import org.apache.tomcat.util.bcel.generic.ObjectType;
+import org.apache.tomcat.util.bcel.generic.ElementValueGen;
+
+public class ClassElementValueGen extends ElementValueGen
+{
+ // For primitive types and string type, this points to the value entry in
+ // the cpool
+ // For 'class' this points to the class entry in the cpool
+ private int idx;
+
+ protected ClassElementValueGen(int typeIdx, ConstantPoolGen cpool)
+ {
+ super(ElementValueGen.CLASS, cpool);
+ this.idx = typeIdx;
+ }
+
+ public ClassElementValueGen(ObjectType t, ConstantPoolGen cpool)
+ {
+ super(ElementValueGen.CLASS, cpool);
+ // this.idx = cpool.addClass(t);
+ idx = cpool.addUtf8(t.getSignature());
+ }
+
+ /**
+ * Return immutable variant of this ClassElementValueGen
+ */
+ public ElementValue getElementValue()
+ {
+ return new ClassElementValue(type, idx, cpGen.getConstantPool());
+ }
+
+ public ClassElementValueGen(ClassElementValue value, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ super(CLASS, cpool);
+ if (copyPoolEntries)
+ {
+ // idx = cpool.addClass(value.getClassString());
+ idx = cpool.addUtf8(value.getClassString());
+ }
+ else
+ {
+ idx = value.getIndex();
+ }
+ }
+
+ public int getIndex()
+ {
+ return idx;
+ }
+
+ public String getClassString()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx);
+ return cu8.getBytes();
+ // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx);
+ // ConstantUtf8 utf8 =
+ // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex());
+ // return utf8.getBytes();
+ }
+
+ public String stringifyValue()
+ {
+ return getClassString();
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 kind of value
+ dos.writeShort(idx);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.AccessFlags;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.Annotations;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.Field;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.RuntimeInvisibleAnnotations;
+import org.apache.tomcat.util.bcel.classfile.RuntimeVisibleAnnotations;
+import org.apache.tomcat.util.bcel.classfile.SourceFile;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * Template class for building up a java class. May be initialized with an
+ * existing java class (file).
+ *
+ * @see JavaClass
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ClassGen extends AccessFlags implements Cloneable {
+
+ /* Corresponds to the fields found in a JavaClass object.
+ */
+ private String class_name, super_class_name, file_name;
+ private int class_name_index = -1, superclass_name_index = -1;
+ private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1;
+ private ConstantPoolGen cp; // Template for building up constant pool
+ // ArrayLists instead of arrays to gather fields, methods, etc.
+ private List field_vec = new ArrayList();
+ private List method_vec = new ArrayList();
+ private List attribute_vec = new ArrayList();
+ private List interface_vec = new ArrayList();
+ private List annotation_vec = new ArrayList();
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ ClassGen THIS = (ClassGen) o1;
+ ClassGen THAT = (ClassGen) o2;
+ return THIS.getClassName().equals(THAT.getClassName());
+ }
+
+
+ public int hashCode( Object o ) {
+ ClassGen THIS = (ClassGen) o;
+ return THIS.getClassName().hashCode();
+ }
+ };
+
+
+ /** Convenience constructor to set up some important values initially.
+ *
+ * @param class_name fully qualified class name
+ * @param super_class_name fully qualified superclass name
+ * @param file_name source file name
+ * @param access_flags access qualifiers
+ * @param interfaces implemented interfaces
+ * @param cp constant pool to use
+ */
+ public ClassGen(String class_name, String super_class_name, String file_name, int access_flags,
+ String[] interfaces, ConstantPoolGen cp) {
+ this.class_name = class_name;
+ this.super_class_name = super_class_name;
+ this.file_name = file_name;
+ this.access_flags = access_flags;
+ this.cp = cp;
+ // Put everything needed by default into the constant pool and the vectors
+ if (file_name != null) {
+ addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(file_name), cp
+ .getConstantPool()));
+ }
+ class_name_index = cp.addClass(class_name);
+ superclass_name_index = cp.addClass(super_class_name);
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; i++) {
+ addInterface(interfaces[i]);
+ }
+ }
+ }
+
+
+ /** Convenience constructor to set up some important values initially.
+ *
+ * @param class_name fully qualified class name
+ * @param super_class_name fully qualified superclass name
+ * @param file_name source file name
+ * @param access_flags access qualifiers
+ * @param interfaces implemented interfaces
+ */
+ public ClassGen(String class_name, String super_class_name, String file_name, int access_flags,
+ String[] interfaces) {
+ this(class_name, super_class_name, file_name, access_flags, interfaces,
+ new ConstantPoolGen());
+ }
+
+
+ /**
+ * Initialize with existing class.
+ * @param clazz JavaClass object (e.g. read from file)
+ */
+ public ClassGen(JavaClass clazz) {
+ class_name_index = clazz.getClassNameIndex();
+ superclass_name_index = clazz.getSuperclassNameIndex();
+ class_name = clazz.getClassName();
+ super_class_name = clazz.getSuperclassName();
+ file_name = clazz.getSourceFileName();
+ access_flags = clazz.getAccessFlags();
+ cp = new ConstantPoolGen(clazz.getConstantPool());
+ major = clazz.getMajor();
+ minor = clazz.getMinor();
+ Attribute[] attributes = clazz.getAttributes();
+ // J5TODO: Could make unpacking lazy, done on first reference
+ AnnotationEntryGen[] annotations = unpackAnnotations(attributes);
+ Method[] methods = clazz.getMethods();
+ Field[] fields = clazz.getFields();
+ String[] interfaces = clazz.getInterfaceNames();
+ for (int i = 0; i < interfaces.length; i++) {
+ addInterface(interfaces[i]);
+ }
+ for (int i = 0; i < attributes.length; i++) {
+ if (!(attributes[i] instanceof Annotations)) {
+ addAttribute(attributes[i]);
+ }
+ }
+ for(int i=0; i < annotations.length; i++) {
+ addAnnotationEntry(annotations[i]);
+ }
+ for (int i = 0; i < methods.length; i++) {
+ addMethod(methods[i]);
+ }
+ for (int i = 0; i < fields.length; i++) {
+ addField(fields[i]);
+ }
+ }
+
+ /**
+ * Look for attributes representing annotations and unpack them.
+ */
+ private AnnotationEntryGen[] unpackAnnotations(Attribute[] attrs)
+ {
+ List /* AnnotationGen */annotationGenObjs = new ArrayList();
+ for (int i = 0; i < attrs.length; i++)
+ {
+ Attribute attr = attrs[i];
+ if (attr instanceof RuntimeVisibleAnnotations)
+ {
+ RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
+ AnnotationEntry[] annos = rva.getAnnotationEntries();
+ for (int j = 0; j < annos.length; j++)
+ {
+ AnnotationEntry a = annos[j];
+ annotationGenObjs.add(new AnnotationEntryGen(a,
+ getConstantPool(), false));
+ }
+ }
+ else
+ if (attr instanceof RuntimeInvisibleAnnotations)
+ {
+ RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
+ AnnotationEntry[] annos = ria.getAnnotationEntries();
+ for (int j = 0; j < annos.length; j++)
+ {
+ AnnotationEntry a = annos[j];
+ annotationGenObjs.add(new AnnotationEntryGen(a,
+ getConstantPool(), false));
+ }
+ }
+ }
+ return (AnnotationEntryGen[]) annotationGenObjs
+ .toArray(new AnnotationEntryGen[annotationGenObjs.size()]);
+ }
+
+
+ /**
+ * @return the (finally) built up Java class object.
+ */
+ public JavaClass getJavaClass() {
+ int[] interfaces = getInterfaces();
+ Field[] fields = getFields();
+ Method[] methods = getMethods();
+ Attribute[] attributes = null;
+ if (annotation_vec.isEmpty()) {
+ attributes = getAttributes();
+ } else {
+ // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations'
+ Attribute[] annAttributes = Utility.getAnnotationAttributes(cp,annotation_vec);
+ attributes = new Attribute[attribute_vec.size()+annAttributes.length];
+ attribute_vec.toArray(attributes);
+ System.arraycopy(annAttributes,0,attributes,attribute_vec.size(),annAttributes.length);
+ }
+ // Must be last since the above calls may still add something to it
+ ConstantPool _cp = this.cp.getFinalConstantPool();
+ return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor,
+ access_flags, _cp, interfaces, fields, methods, attributes);
+ }
+
+
+ /**
+ * Add an interface to this class, i.e., this class has to implement it.
+ * @param name interface to implement (fully qualified class name)
+ */
+ public void addInterface( String name ) {
+ interface_vec.add(name);
+ }
+
+
+ /**
+ * Remove an interface from this class.
+ * @param name interface to remove (fully qualified name)
+ */
+ public void removeInterface( String name ) {
+ interface_vec.remove(name);
+ }
+
+
+ /**
+ * @return major version number of class file
+ */
+ public int getMajor() {
+ return major;
+ }
+
+
+ /** Set major version number of class file, default value is 45 (JDK 1.1)
+ * @param major major version number
+ */
+ public void setMajor( int major ) {
+ this.major = major;
+ }
+
+
+ /** Set minor version number of class file, default value is 3 (JDK 1.1)
+ * @param minor minor version number
+ */
+ public void setMinor( int minor ) {
+ this.minor = minor;
+ }
+
+
+ /**
+ * @return minor version number of class file
+ */
+ public int getMinor() {
+ return minor;
+ }
+
+
+ /**
+ * Add an attribute to this class.
+ * @param a attribute to add
+ */
+ public void addAttribute( Attribute a ) {
+ attribute_vec.add(a);
+ }
+
+ public void addAnnotationEntry(AnnotationEntryGen a) {
+ annotation_vec.add(a);
+ }
+
+
+ /**
+ * Add a method to this class.
+ * @param m method to add
+ */
+ public void addMethod( Method m ) {
+ method_vec.add(m);
+ }
+
+
+ /**
+ * Convenience method.
+ *
+ * Add an empty constructor to this class that does nothing but calling super().
+ * @param access_flags rights for constructor
+ */
+ public void addEmptyConstructor( int access_flags ) {
+ InstructionList il = new InstructionList();
+ il.append(InstructionConstants.THIS); // Push `this'
+ il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "<init>", "()V")));
+ il.append(InstructionConstants.RETURN);
+ MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>",
+ class_name, il, cp);
+ mg.setMaxStack(1);
+ addMethod(mg.getMethod());
+ }
+
+
+ /**
+ * Add a field to this class.
+ * @param f field to add
+ */
+ public void addField( Field f ) {
+ field_vec.add(f);
+ }
+
+
+ public boolean containsField( Field f ) {
+ return field_vec.contains(f);
+ }
+
+
+ /** @return field object with given name, or null
+ */
+ public Field containsField( String name ) {
+ for (Iterator e = field_vec.iterator(); e.hasNext();) {
+ Field f = (Field) e.next();
+ if (f.getName().equals(name)) {
+ return f;
+ }
+ }
+ return null;
+ }
+
+
+ /** @return method object with given name and signature, or null
+ */
+ public Method containsMethod( String name, String signature ) {
+ for (Iterator e = method_vec.iterator(); e.hasNext();) {
+ Method m = (Method) e.next();
+ if (m.getName().equals(name) && m.getSignature().equals(signature)) {
+ return m;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Remove an attribute from this class.
+ * @param a attribute to remove
+ */
+ public void removeAttribute( Attribute a ) {
+ attribute_vec.remove(a);
+ }
+
+
+ /**
+ * Remove a method from this class.
+ * @param m method to remove
+ */
+ public void removeMethod( Method m ) {
+ method_vec.remove(m);
+ }
+
+
+ /** Replace given method with new one. If the old one does not exist
+ * add the new_ method to the class anyway.
+ */
+ public void replaceMethod( Method old, Method new_ ) {
+ if (new_ == null) {
+ throw new ClassGenException("Replacement method must not be null");
+ }
+ int i = method_vec.indexOf(old);
+ if (i < 0) {
+ method_vec.add(new_);
+ } else {
+ method_vec.set(i, new_);
+ }
+ }
+
+
+ /** Replace given field with new one. If the old one does not exist
+ * add the new_ field to the class anyway.
+ */
+ public void replaceField( Field old, Field new_ ) {
+ if (new_ == null) {
+ throw new ClassGenException("Replacement method must not be null");
+ }
+ int i = field_vec.indexOf(old);
+ if (i < 0) {
+ field_vec.add(new_);
+ } else {
+ field_vec.set(i, new_);
+ }
+ }
+
+
+ /**
+ * Remove a field to this class.
+ * @param f field to remove
+ */
+ public void removeField( Field f ) {
+ field_vec.remove(f);
+ }
+
+
+ public String getClassName() {
+ return class_name;
+ }
+
+
+ public String getSuperclassName() {
+ return super_class_name;
+ }
+
+
+ public String getFileName() {
+ return file_name;
+ }
+
+
+ public void setClassName( String name ) {
+ class_name = name.replace('/', '.');
+ class_name_index = cp.addClass(name);
+ }
+
+
+ public void setSuperclassName( String name ) {
+ super_class_name = name.replace('/', '.');
+ superclass_name_index = cp.addClass(name);
+ }
+
+
+ public Method[] getMethods() {
+ return (Method[]) method_vec.toArray(new Method[method_vec.size()]);
+ }
+
+
+ public void setMethods( Method[] methods ) {
+ method_vec.clear();
+ for (int m = 0; m < methods.length; m++) {
+ addMethod(methods[m]);
+ }
+ }
+
+
+ public void setMethodAt( Method method, int pos ) {
+ method_vec.set(pos, method);
+ }
+
+
+ public Method getMethodAt( int pos ) {
+ return (Method) method_vec.get(pos);
+ }
+
+
+ public String[] getInterfaceNames() {
+ int size = interface_vec.size();
+ String[] interfaces = new String[size];
+ interface_vec.toArray(interfaces);
+ return interfaces;
+ }
+
+
+ public int[] getInterfaces() {
+ int size = interface_vec.size();
+ int[] interfaces = new int[size];
+ for (int i = 0; i < size; i++) {
+ interfaces[i] = cp.addClass((String) interface_vec.get(i));
+ }
+ return interfaces;
+ }
+
+
+ public Field[] getFields() {
+ return (Field[]) field_vec.toArray(new Field[field_vec.size()]);
+ }
+
+
+ public Attribute[] getAttributes() {
+ return (Attribute[]) attribute_vec.toArray(new Attribute[attribute_vec.size()]);
+ }
+
+ // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
+ public AnnotationEntryGen[] getAnnotationEntries() {
+ return (AnnotationEntryGen[]) annotation_vec.toArray(new AnnotationEntryGen[annotation_vec.size()]);
+ }
+
+
+ public ConstantPoolGen getConstantPool() {
+ return cp;
+ }
+
+
+ public void setConstantPool( ConstantPoolGen constant_pool ) {
+ cp = constant_pool;
+ }
+
+
+ public void setClassNameIndex( int class_name_index ) {
+ this.class_name_index = class_name_index;
+ class_name = cp.getConstantPool().getConstantString(class_name_index,
+ Constants.CONSTANT_Class).replace('/', '.');
+ }
+
+
+ public void setSuperclassNameIndex( int superclass_name_index ) {
+ this.superclass_name_index = superclass_name_index;
+ super_class_name = cp.getConstantPool().getConstantString(superclass_name_index,
+ Constants.CONSTANT_Class).replace('/', '.');
+ }
+
+
+ public int getSuperclassNameIndex() {
+ return superclass_name_index;
+ }
+
+
+ public int getClassNameIndex() {
+ return class_name_index;
+ }
+
+ private ArrayList observers;
+
+
+ /** Add observer for this object.
+ */
+ public void addObserver( ClassObserver o ) {
+ if (observers == null) {
+ observers = new ArrayList();
+ }
+ observers.add(o);
+ }
+
+
+ /** Remove observer for this object.
+ */
+ public void removeObserver( ClassObserver o ) {
+ if (observers != null) {
+ observers.remove(o);
+ }
+ }
+
+
+ /** Call notify() method on all observers. This method is not called
+ * automatically whenever the state has changed, but has to be
+ * called by the user after he has finished editing the object.
+ */
+ public void update() {
+ if (observers != null) {
+ for (Iterator e = observers.iterator(); e.hasNext();) {
+ ((ClassObserver) e.next()).notify(this);
+ }
+ }
+ }
+
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ return null;
+ }
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two ClassGen objects are said to be equal when
+ * their class names are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the class name.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Thrown on internal errors. Extends RuntimeException so it hasn't to be declared
+ * in the throws clause every time.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ClassGenException extends RuntimeException {
+
+ public ClassGenException() {
+ super();
+ }
+
+
+ public ClassGenException(String s) {
+ super(s);
+ }
+
+ public ClassGenException(String s, Throwable initCause) {
+ super(s, initCause);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Implement this interface if you're interested in changes to a ClassGen object
+ * and register yourself with addObserver().
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface ClassObserver {
+
+ public void notify( ClassGen clazz );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.classfile.CodeException;
+
+/**
+ * This class represents an exception handler, i.e., specifies the region where
+ * a handler is active and an instruction where the actual handling is done.
+ * pool as parameters. Opposed to the JVM specification the end of the handled
+ * region is set to be inclusive, i.e. all instructions between start and end
+ * are protected including the start and end instructions (handles) themselves.
+ * The end of the region is automatically mapped to be exclusive when calling
+ * getCodeException(), i.e., there is no difference semantically.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see MethodGen
+ * @see CodeException
+ * @see InstructionHandle
+ */
+public final class CodeExceptionGen implements InstructionTargeter, Cloneable, java.io.Serializable {
+
+ private InstructionHandle start_pc;
+ private InstructionHandle end_pc;
+ private InstructionHandle handler_pc;
+ private ObjectType catch_type;
+
+
+ /**
+ * Add an exception handler, i.e., specify region where a handler is active and an
+ * instruction where the actual handling is done.
+ *
+ * @param start_pc Start of handled region (inclusive)
+ * @param end_pc End of handled region (inclusive)
+ * @param handler_pc Where handling is done
+ * @param catch_type which exception is handled, null for ANY
+ */
+ public CodeExceptionGen(InstructionHandle start_pc, InstructionHandle end_pc,
+ InstructionHandle handler_pc, ObjectType catch_type) {
+ setStartPC(start_pc);
+ setEndPC(end_pc);
+ setHandlerPC(handler_pc);
+ this.catch_type = catch_type;
+ }
+
+
+ /**
+ * Get CodeException object.<BR>
+ *
+ * This relies on that the instruction list has already been dumped
+ * to byte code or or that the `setPositions' methods has been
+ * called for the instruction list.
+ *
+ * @param cp constant pool
+ */
+ public CodeException getCodeException( ConstantPoolGen cp ) {
+ return new CodeException(start_pc.getPosition(), end_pc.getPosition()
+ + end_pc.getInstruction().getLength(), handler_pc.getPosition(),
+ (catch_type == null) ? 0 : cp.addClass(catch_type));
+ }
+
+
+ /* Set start of handler
+ * @param start_pc Start of handled region (inclusive)
+ */
+ public void setStartPC( InstructionHandle start_pc ) {
+ BranchInstruction.notifyTarget(this.start_pc, start_pc, this);
+ this.start_pc = start_pc;
+ }
+
+
+ /* Set end of handler
+ * @param end_pc End of handled region (inclusive)
+ */
+ public void setEndPC( InstructionHandle end_pc ) {
+ BranchInstruction.notifyTarget(this.end_pc, end_pc, this);
+ this.end_pc = end_pc;
+ }
+
+
+ /* Set handler code
+ * @param handler_pc Start of handler
+ */
+ public void setHandlerPC( InstructionHandle handler_pc ) {
+ BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this);
+ this.handler_pc = handler_pc;
+ }
+
+
+ /**
+ * @param old_ih old target, either start or end
+ * @param new_ih new target
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ boolean targeted = false;
+ if (start_pc == old_ih) {
+ targeted = true;
+ setStartPC(new_ih);
+ }
+ if (end_pc == old_ih) {
+ targeted = true;
+ setEndPC(new_ih);
+ }
+ if (handler_pc == old_ih) {
+ targeted = true;
+ setHandlerPC(new_ih);
+ }
+ if (!targeted) {
+ throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", "
+ + end_pc + ", " + handler_pc + "}");
+ }
+ }
+
+
+ /**
+ * @return true, if ih is target of this handler
+ */
+ public boolean containsTarget( InstructionHandle ih ) {
+ return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih);
+ }
+
+
+ /** Sets the type of the Exception to catch. Set 'null' for ANY. */
+ public void setCatchType( ObjectType catch_type ) {
+ this.catch_type = catch_type;
+ }
+
+
+ /** Gets the type of the Exception to catch, 'null' for ANY. */
+ public ObjectType getCatchType() {
+ return catch_type;
+ }
+
+
+ /** @return start of handled region (inclusive)
+ */
+ public InstructionHandle getStartPC() {
+ return start_pc;
+ }
+
+
+ /** @return end of handled region (inclusive)
+ */
+ public InstructionHandle getEndPC() {
+ return end_pc;
+ }
+
+
+ /** @return start of handler
+ */
+ public InstructionHandle getHandlerPC() {
+ return handler_pc;
+ }
+
+
+ public String toString() {
+ return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")";
+ }
+
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Wrapper class for `compound' operations, virtual instructions that
+ * don't exist as byte code, but give a useful meaning. For example,
+ * the (virtual) PUSH instruction takes an arbitray argument and produces the
+ * appropiate code at dump time (ICONST, LDC, BIPUSH, ...). Also you can use the
+ * SWITCH instruction as a useful template for either LOOKUPSWITCH or
+ * TABLESWITCH.
+ *
+ * The interface provides the possibilty for the user to write
+ * `templates' or `macros' for such reuseable code patterns.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see PUSH
+ * @see SWITCH
+ */
+public interface CompoundInstruction {
+
+ public InstructionList getInstructionList();
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.classfile.ConstantCP;
+import org.apache.tomcat.util.bcel.classfile.ConstantClass;
+import org.apache.tomcat.util.bcel.classfile.ConstantDouble;
+import org.apache.tomcat.util.bcel.classfile.ConstantFieldref;
+import org.apache.tomcat.util.bcel.classfile.ConstantFloat;
+import org.apache.tomcat.util.bcel.classfile.ConstantInteger;
+import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantLong;
+import org.apache.tomcat.util.bcel.classfile.ConstantMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantString;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+
+/**
+ * This class is used to build up a constant pool. The user adds
+ * constants via `addXXX' methods, `addString', `addClass',
+ * etc.. These methods return an index into the constant
+ * pool. Finally, `getFinalConstantPool()' returns the constant pool
+ * built up. Intermediate versions of the constant pool can be
+ * obtained with `getConstantPool()'. A constant pool has capacity for
+ * Constants.MAX_SHORT entries. Note that the first (0) is used by the
+ * JVM and that Double and Long constants need two slots.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constant
+ */
+public class ConstantPoolGen implements java.io.Serializable {
+
+ protected int size;
+ protected Constant[] constants;
+ protected int index = 1; // First entry (0) used by JVM
+ private static final String METHODREF_DELIM = ":";
+ private static final String IMETHODREF_DELIM = "#";
+ private static final String FIELDREF_DELIM = "&";
+ private static final String NAT_DELIM = "%";
+
+ private static class Index implements java.io.Serializable {
+
+ int index;
+
+
+ Index(int i) {
+ index = i;
+ }
+ }
+
+
+ /**
+ * Initialize with given array of constants.
+ *
+ * @param cs array of given constants, new ones will be appended
+ */
+ public ConstantPoolGen(Constant[] cs) {
+ StringBuffer sb = new StringBuffer(256);
+
+ size = Math.max(256, cs.length + 64);
+ constants = new Constant[size];
+
+ System.arraycopy(cs, 0, constants, 0, cs.length);
+ if (cs.length > 0) {
+ index = cs.length;
+ }
+
+
+ for (int i = 1; i < index; i++) {
+ Constant c = constants[i];
+ if (c instanceof ConstantString) {
+ ConstantString s = (ConstantString) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
+ String key = u8.getBytes();
+ if (!string_table.containsKey(key)) {
+ string_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantClass) {
+ ConstantClass s = (ConstantClass) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
+ String key = u8.getBytes();
+ if (!class_table.containsKey(key)) {
+ class_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantNameAndType) {
+ ConstantNameAndType n = (ConstantNameAndType) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
+
+ sb.append(u8.getBytes());
+ sb.append(NAT_DELIM);
+ sb.append(u8_2.getBytes());
+ String key = sb.toString();
+ sb.delete(0, sb.length());
+
+ if (!n_a_t_table.containsKey(key)) {
+ n_a_t_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantUtf8) {
+ ConstantUtf8 u = (ConstantUtf8) c;
+ String key = u.getBytes();
+ if (!utf8_table.containsKey(key)) {
+ utf8_table.put(key, new Index(i));
+ }
+ } else if (c instanceof ConstantCP) {
+ ConstantCP m = (ConstantCP) c;
+ ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
+ ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
+ ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
+ String class_name = u8.getBytes().replace('/', '.');
+ u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ String method_name = u8.getBytes();
+ u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ String signature = u8.getBytes();
+ String delim = METHODREF_DELIM;
+ if (c instanceof ConstantInterfaceMethodref) {
+ delim = IMETHODREF_DELIM;
+ } else if (c instanceof ConstantFieldref) {
+ delim = FIELDREF_DELIM;
+ }
+
+ sb.append(class_name);
+ sb.append(delim);
+ sb.append(method_name);
+ sb.append(delim);
+ sb.append(signature);
+ String key = sb.toString();
+ sb.delete(0, sb.length());
+
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(i));
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Initialize with given constant pool.
+ */
+ public ConstantPoolGen(ConstantPool cp) {
+ this(cp.getConstantPool());
+ }
+
+
+ /**
+ * Create empty constant pool.
+ */
+ public ConstantPoolGen() {
+ size = 256;
+ constants = new Constant[size];
+ }
+
+
+ /** Resize internal array of constants.
+ */
+ protected void adjustSize() {
+ if (index + 3 >= size) {
+ Constant[] cs = constants;
+ size *= 2;
+ constants = new Constant[size];
+ System.arraycopy(cs, 0, constants, 0, index);
+ }
+ }
+
+ private Map string_table = new HashMap();
+
+
+ /**
+ * Look for ConstantString in ConstantPool containing String `str'.
+ *
+ * @param str String to search for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupString( String str ) {
+ Index index = (Index) string_table.get(str);
+ return (index != null) ? index.index : -1;
+ }
+
+
+ /**
+ * Add a new String constant to the ConstantPool, if it is not already in there.
+ *
+ * @param str String to add
+ * @return index of entry
+ */
+ public int addString( String str ) {
+ int ret;
+ if ((ret = lookupString(str)) != -1) {
+ return ret; // Already in CP
+ }
+ int utf8 = addUtf8(str);
+ adjustSize();
+ ConstantString s = new ConstantString(utf8);
+ ret = index;
+ constants[index++] = s;
+ if (!string_table.containsKey(str)) {
+ string_table.put(str, new Index(ret));
+ }
+ return ret;
+ }
+
+ private Map class_table = new HashMap();
+
+
+ /**
+ * Look for ConstantClass in ConstantPool named `str'.
+ *
+ * @param str String to search for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupClass( String str ) {
+ Index index = (Index) class_table.get(str.replace('.', '/'));
+ return (index != null) ? index.index : -1;
+ }
+
+
+ private int addClass_( String clazz ) {
+ int ret;
+ if ((ret = lookupClass(clazz)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ConstantClass c = new ConstantClass(addUtf8(clazz));
+ ret = index;
+ constants[index++] = c;
+ if (!class_table.containsKey(clazz)) {
+ class_table.put(clazz, new Index(ret));
+ }
+ return ret;
+ }
+
+
+ /**
+ * Add a new Class reference to the ConstantPool, if it is not already in there.
+ *
+ * @param str Class to add
+ * @return index of entry
+ */
+ public int addClass( String str ) {
+ return addClass_(str.replace('.', '/'));
+ }
+
+
+ /**
+ * Add a new Class reference to the ConstantPool for a given type.
+ *
+ * @param type Class to add
+ * @return index of entry
+ */
+ public int addClass( ObjectType type ) {
+ return addClass(type.getClassName());
+ }
+
+
+ /**
+ * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY
+ * instruction, e.g. to the ConstantPool.
+ *
+ * @param type type of array class
+ * @return index of entry
+ */
+ public int addArrayClass( ArrayType type ) {
+ return addClass_(type.getSignature());
+ }
+
+
+ /**
+ * Look for ConstantInteger in ConstantPool.
+ *
+ * @param n integer number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupInteger( int n ) {
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantInteger) {
+ ConstantInteger c = (ConstantInteger) constants[i];
+ if (c.getBytes() == n) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Add a new Integer constant to the ConstantPool, if it is not already in there.
+ *
+ * @param n integer number to add
+ * @return index of entry
+ */
+ public int addInteger( int n ) {
+ int ret;
+ if ((ret = lookupInteger(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantInteger(n);
+ return ret;
+ }
+
+
+ /**
+ * Look for ConstantFloat in ConstantPool.
+ *
+ * @param n Float number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupFloat( float n ) {
+ int bits = Float.floatToIntBits(n);
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantFloat) {
+ ConstantFloat c = (ConstantFloat) constants[i];
+ if (Float.floatToIntBits(c.getBytes()) == bits) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Add a new Float constant to the ConstantPool, if it is not already in there.
+ *
+ * @param n Float number to add
+ * @return index of entry
+ */
+ public int addFloat( float n ) {
+ int ret;
+ if ((ret = lookupFloat(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantFloat(n);
+ return ret;
+ }
+
+ private Map utf8_table = new HashMap();
+
+
+ /**
+ * Look for ConstantUtf8 in ConstantPool.
+ *
+ * @param n Utf8 string to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupUtf8( String n ) {
+ Index index = (Index) utf8_table.get(n);
+ return (index != null) ? index.index : -1;
+ }
+
+
+ /**
+ * Add a new Utf8 constant to the ConstantPool, if it is not already in there.
+ *
+ * @param n Utf8 string to add
+ * @return index of entry
+ */
+ public int addUtf8( String n ) {
+ int ret;
+ if ((ret = lookupUtf8(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index++] = new ConstantUtf8(n);
+ if (!utf8_table.containsKey(n)) {
+ utf8_table.put(n, new Index(ret));
+ }
+ return ret;
+ }
+
+
+ /**
+ * Look for ConstantLong in ConstantPool.
+ *
+ * @param n Long number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupLong( long n ) {
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantLong) {
+ ConstantLong c = (ConstantLong) constants[i];
+ if (c.getBytes() == n) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Add a new long constant to the ConstantPool, if it is not already in there.
+ *
+ * @param n Long number to add
+ * @return index of entry
+ */
+ public int addLong( long n ) {
+ int ret;
+ if ((ret = lookupLong(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index] = new ConstantLong(n);
+ index += 2; // Wastes one entry according to spec
+ return ret;
+ }
+
+
+ /**
+ * Look for ConstantDouble in ConstantPool.
+ *
+ * @param n Double number to look for
+ * @return index on success, -1 otherwise
+ */
+ public int lookupDouble( double n ) {
+ long bits = Double.doubleToLongBits(n);
+ for (int i = 1; i < index; i++) {
+ if (constants[i] instanceof ConstantDouble) {
+ ConstantDouble c = (ConstantDouble) constants[i];
+ if (Double.doubleToLongBits(c.getBytes()) == bits) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+
+ /**
+ * Add a new double constant to the ConstantPool, if it is not already in there.
+ *
+ * @param n Double number to add
+ * @return index of entry
+ */
+ public int addDouble( double n ) {
+ int ret;
+ if ((ret = lookupDouble(n)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ ret = index;
+ constants[index] = new ConstantDouble(n);
+ index += 2; // Wastes one entry according to spec
+ return ret;
+ }
+
+ private Map n_a_t_table = new HashMap();
+
+
+ /**
+ * Look for ConstantNameAndType in ConstantPool.
+ *
+ * @param name of variable/method
+ * @param signature of variable/method
+ * @return index on success, -1 otherwise
+ */
+ public int lookupNameAndType( String name, String signature ) {
+ Index _index = (Index) n_a_t_table.get(name + NAT_DELIM + signature);
+ return (_index != null) ? _index.index : -1;
+ }
+
+
+ /**
+ * Add a new NameAndType constant to the ConstantPool if it is not already
+ * in there.
+ *
+ * @param name Name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addNameAndType( String name, String signature ) {
+ int ret;
+ int name_index, signature_index;
+ if ((ret = lookupNameAndType(name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ name_index = addUtf8(name);
+ signature_index = addUtf8(signature);
+ ret = index;
+ constants[index++] = new ConstantNameAndType(name_index, signature_index);
+ String key = name + NAT_DELIM + signature;
+ if (!n_a_t_table.containsKey(key)) {
+ n_a_t_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+ private Map cp_table = new HashMap();
+
+
+ /**
+ * Look for ConstantMethodref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param method_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupMethodref( String class_name, String method_name, String signature ) {
+ Index index = (Index) cp_table.get(class_name + METHODREF_DELIM + method_name
+ + METHODREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+
+ public int lookupMethodref( MethodGen method ) {
+ return lookupMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+
+ /**
+ * Add a new Methodref constant to the ConstantPool, if it is not already
+ * in there.
+ *
+ * @param class_name class name string to add
+ * @param method_name method name string to add
+ * @param signature method signature string to add
+ * @return index of entry
+ */
+ public int addMethodref( String class_name, String method_name, String signature ) {
+ int ret, class_index, name_and_type_index;
+ if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ name_and_type_index = addNameAndType(method_name, signature);
+ class_index = addClass(class_name);
+ ret = index;
+ constants[index++] = new ConstantMethodref(class_index, name_and_type_index);
+ String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+
+ public int addMethodref( MethodGen method ) {
+ return addMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+
+ /**
+ * Look for ConstantInterfaceMethodref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param method_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupInterfaceMethodref( String class_name, String method_name, String signature ) {
+ Index index = (Index) cp_table.get(class_name + IMETHODREF_DELIM + method_name
+ + IMETHODREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+
+ public int lookupInterfaceMethodref( MethodGen method ) {
+ return lookupInterfaceMethodref(method.getClassName(), method.getName(), method
+ .getSignature());
+ }
+
+
+ /**
+ * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already
+ * in there.
+ *
+ * @param class_name class name string to add
+ * @param method_name method name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addInterfaceMethodref( String class_name, String method_name, String signature ) {
+ int ret, class_index, name_and_type_index;
+ if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ class_index = addClass(class_name);
+ name_and_type_index = addNameAndType(method_name, signature);
+ ret = index;
+ constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index);
+ String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+
+ public int addInterfaceMethodref( MethodGen method ) {
+ return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature());
+ }
+
+
+ /**
+ * Look for ConstantFieldref in ConstantPool.
+ *
+ * @param class_name Where to find method
+ * @param field_name Guess what
+ * @param signature return and argument types
+ * @return index on success, -1 otherwise
+ */
+ public int lookupFieldref( String class_name, String field_name, String signature ) {
+ Index index = (Index) cp_table.get(class_name + FIELDREF_DELIM + field_name
+ + FIELDREF_DELIM + signature);
+ return (index != null) ? index.index : -1;
+ }
+
+
+ /**
+ * Add a new Fieldref constant to the ConstantPool, if it is not already
+ * in there.
+ *
+ * @param class_name class name string to add
+ * @param field_name field name string to add
+ * @param signature signature string to add
+ * @return index of entry
+ */
+ public int addFieldref( String class_name, String field_name, String signature ) {
+ int ret;
+ int class_index, name_and_type_index;
+ if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) {
+ return ret; // Already in CP
+ }
+ adjustSize();
+ class_index = addClass(class_name);
+ name_and_type_index = addNameAndType(field_name, signature);
+ ret = index;
+ constants[index++] = new ConstantFieldref(class_index, name_and_type_index);
+ String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature;
+ if (!cp_table.containsKey(key)) {
+ cp_table.put(key, new Index(ret));
+ }
+ return ret;
+ }
+
+
+ /**
+ * @param i index in constant pool
+ * @return constant pool entry at index i
+ */
+ public Constant getConstant( int i ) {
+ return constants[i];
+ }
+
+
+ /**
+ * Use with care!
+ *
+ * @param i index in constant pool
+ * @param c new constant pool entry at index i
+ */
+ public void setConstant( int i, Constant c ) {
+ constants[i] = c;
+ }
+
+
+ /**
+ * @return intermediate constant pool
+ */
+ public ConstantPool getConstantPool() {
+ return new ConstantPool(constants);
+ }
+
+
+ /**
+ * @return current size of constant pool
+ */
+ public int getSize() {
+ return index;
+ }
+
+
+ /**
+ * @return constant pool with proper length
+ */
+ public ConstantPool getFinalConstantPool() {
+ Constant[] cs = new Constant[index];
+ System.arraycopy(constants, 0, cs, 0, index);
+ return new ConstantPool(cs);
+ }
+
+
+ /**
+ * @return String representation.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 1; i < index; i++) {
+ buf.append(i).append(")").append(constants[i]).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ /** Import constant from another ConstantPool and return new index.
+ */
+ public int addConstant( Constant c, ConstantPoolGen cp ) {
+ Constant[] constants = cp.getConstantPool().getConstantPool();
+ switch (c.getTag()) {
+ case Constants.CONSTANT_String: {
+ ConstantString s = (ConstantString) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
+ return addString(u8.getBytes());
+ }
+ case Constants.CONSTANT_Class: {
+ ConstantClass s = (ConstantClass) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
+ return addClass(u8.getBytes());
+ }
+ case Constants.CONSTANT_NameAndType: {
+ ConstantNameAndType n = (ConstantNameAndType) c;
+ ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ return addNameAndType(u8.getBytes(), u8_2.getBytes());
+ }
+ case Constants.CONSTANT_Utf8:
+ return addUtf8(((ConstantUtf8) c).getBytes());
+ case Constants.CONSTANT_Double:
+ return addDouble(((ConstantDouble) c).getBytes());
+ case Constants.CONSTANT_Float:
+ return addFloat(((ConstantFloat) c).getBytes());
+ case Constants.CONSTANT_Long:
+ return addLong(((ConstantLong) c).getBytes());
+ case Constants.CONSTANT_Integer:
+ return addInteger(((ConstantInteger) c).getBytes());
+ case Constants.CONSTANT_InterfaceMethodref:
+ case Constants.CONSTANT_Methodref:
+ case Constants.CONSTANT_Fieldref: {
+ ConstantCP m = (ConstantCP) c;
+ ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
+ ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
+ ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
+ String class_name = u8.getBytes().replace('/', '.');
+ u8 = (ConstantUtf8) constants[n.getNameIndex()];
+ String name = u8.getBytes();
+ u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
+ String signature = u8.getBytes();
+ switch (c.getTag()) {
+ case Constants.CONSTANT_InterfaceMethodref:
+ return addInterfaceMethodref(class_name, name, signature);
+ case Constants.CONSTANT_Methodref:
+ return addMethodref(class_name, name, signature);
+ case Constants.CONSTANT_Fieldref:
+ return addFieldref(class_name, name, signature);
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + c);
+ }
+ }
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + c);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes a push instruction that produces a literal on the stack
+ * such as SIPUSH, BIPUSH, ICONST, etc.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+
+ * @see ICONST
+ * @see SIPUSH
+ */
+public interface ConstantPushInstruction extends PushInstruction, TypedInstruction {
+
+ public Number getValue();
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Super class for the x2y family of instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class ConversionInstruction extends Instruction implements TypedInstruction,
+ StackProducer, StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ConversionInstruction() {
+ }
+
+
+ /**
+ * @param opcode opcode of instruction
+ */
+ protected ConversionInstruction(short opcode) {
+ super(opcode, (short) 1);
+ }
+
+
+ /** @return type associated with the instruction
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ switch (opcode) {
+ case Constants.D2I:
+ case Constants.F2I:
+ case Constants.L2I:
+ return Type.INT;
+ case Constants.D2F:
+ case Constants.I2F:
+ case Constants.L2F:
+ return Type.FLOAT;
+ case Constants.D2L:
+ case Constants.F2L:
+ case Constants.I2L:
+ return Type.LONG;
+ case Constants.F2D:
+ case Constants.I2D:
+ case Constants.L2D:
+ return Type.DOUBLE;
+ case Constants.I2B:
+ return Type.BYTE;
+ case Constants.I2C:
+ return Type.CHAR;
+ case Constants.I2S:
+ return Type.SHORT;
+ default: // Never reached
+ throw new ClassGenException("Unknown type " + opcode);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * D2F - Convert double to float
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class D2F extends ConversionInstruction {
+
+ /** Convert double to float
+ */
+ public D2F() {
+ super(org.apache.tomcat.util.bcel.Constants.D2F);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitD2F(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * D2I - Convert double to int
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class D2I extends ConversionInstruction {
+
+ /** Convert double to int
+ */
+ public D2I() {
+ super(org.apache.tomcat.util.bcel.Constants.D2I);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitD2I(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * D2L - Convert double to long
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class D2L extends ConversionInstruction {
+
+ /** Convert double to long
+ */
+ public D2L() {
+ super(org.apache.tomcat.util.bcel.Constants.D2L);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitD2L(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DADD - Add doubles
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result1.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DADD extends ArithmeticInstruction {
+
+ /** Add doubles
+ */
+ public DADD() {
+ super(org.apache.tomcat.util.bcel.Constants.DADD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDADD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DALOAD - Load double from array
+ * <PRE>Stack: ..., arrayref, index -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load double from array
+ */
+ public DALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.DALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitDALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DASTORE - Store into double array
+ * <PRE>Stack: ..., arrayref, index, value.word1, value.word2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store double into array
+ */
+ public DASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.DASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitDASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DCMPG - Compare doubles: value1 > value2
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
+
+ public DCMPG() {
+ super(org.apache.tomcat.util.bcel.Constants.DCMPG, (short) 1);
+ }
+
+
+ /** @return Type.DOUBLE
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.DOUBLE;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitDCMPG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DCMPL - Compare doubles: value1 < value2
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
+
+ public DCMPL() {
+ super(org.apache.tomcat.util.bcel.Constants.DCMPL, (short) 1);
+ }
+
+
+ /** @return Type.DOUBLE
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.DOUBLE;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitDCMPL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DCONST - Push 0.0 or 1.0, other values cause an exception
+ *
+ * <PRE>Stack: ... -> ..., </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DCONST extends Instruction implements ConstantPushInstruction, TypedInstruction {
+
+ private double value;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ DCONST() {
+ }
+
+
+ public DCONST(double f) {
+ super(org.apache.tomcat.util.bcel.Constants.DCONST_0, (short) 1);
+ if (f == 0.0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.DCONST_0;
+ } else if (f == 1.0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.DCONST_1;
+ } else {
+ throw new ClassGenException("DCONST can be used only for 0.0 and 1.0: " + f);
+ }
+ value = f;
+ }
+
+
+ public Number getValue() {
+ return new Double(value);
+ }
+
+
+ /** @return Type.DOUBLE
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.DOUBLE;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitDCONST(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DDIV - Divide doubles
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DDIV extends ArithmeticInstruction {
+
+ /** Divide doubles
+ */
+ public DDIV() {
+ super(org.apache.tomcat.util.bcel.Constants.DDIV);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDDIV(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DLOAD - Load double from local variable
+ * <PRE>Stack ... -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DLOAD extends LoadInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ DLOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.DLOAD, org.apache.tomcat.util.bcel.Constants.DLOAD_0);
+ }
+
+
+ /** Load double from local variable
+ * @param n index of local variable
+ */
+ public DLOAD(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.DLOAD, org.apache.tomcat.util.bcel.Constants.DLOAD_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitDLOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DMUL - Multiply doubles
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DMUL extends ArithmeticInstruction {
+
+ /** Multiply doubles
+ */
+ public DMUL() {
+ super(org.apache.tomcat.util.bcel.Constants.DMUL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDMUL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DNEG - Negate double
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DNEG extends ArithmeticInstruction {
+
+ public DNEG() {
+ super(org.apache.tomcat.util.bcel.Constants.DNEG);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDNEG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DREM - Remainder of doubles
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DREM extends ArithmeticInstruction {
+
+ /** Remainder of doubles
+ */
+ public DREM() {
+ super(org.apache.tomcat.util.bcel.Constants.DREM);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDREM(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DRETURN - Return double from method
+ * <PRE>Stack: ..., value.word1, value.word2 -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DRETURN extends ReturnInstruction {
+
+ /** Return double from method
+ */
+ public DRETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.DRETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitDRETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DSTORE - Store double into local variable
+ * <pre>Stack: ..., value.word1, value.word2 -> ... </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DSTORE extends StoreInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ DSTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.DSTORE, org.apache.tomcat.util.bcel.Constants.DSTORE_0);
+ }
+
+
+ /** Store double into local variable
+ * @param n index of local variable
+ */
+ public DSTORE(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.DSTORE, org.apache.tomcat.util.bcel.Constants.DSTORE_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitDSTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DSUB - Substract doubles
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DSUB extends ArithmeticInstruction {
+
+ /** Substract doubles
+ */
+ public DSUB() {
+ super(org.apache.tomcat.util.bcel.Constants.DSUB);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitDSUB(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP - Duplicate top operand stack word
+ * <PRE>Stack: ..., word -> ..., word, word</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP extends StackInstruction implements PushInstruction {
+
+ public DUP() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitStackInstruction(this);
+ v.visitDUP(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP2 - Duplicate two top operand stack words
+ * <PRE>Stack: ..., word2, word1 -> ..., word2, word1, word2, word1</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP2 extends StackInstruction implements PushInstruction {
+
+ public DUP2() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP2);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitStackInstruction(this);
+ v.visitDUP2(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP2_X1 - Duplicate two top operand stack words and put three down
+ * <PRE>Stack: ..., word3, word2, word1 -> ..., word2, word1, word3, word2, word1</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP2_X1 extends StackInstruction {
+
+ public DUP2_X1() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP2_X1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackInstruction(this);
+ v.visitDUP2_X1(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP2_X2 - Duplicate two top operand stack words and put four down
+ * <PRE>Stack: ..., word4, word3, word2, word1 -> ..., word2, word1, word4, word3, word2, word1</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP2_X2 extends StackInstruction {
+
+ public DUP2_X2() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP2_X2);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackInstruction(this);
+ v.visitDUP2_X2(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP_X1 - Duplicate top operand stack word and put two down
+ * <PRE>Stack: ..., word2, word1 -> ..., word1, word2, word1</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP_X1 extends StackInstruction {
+
+ public DUP_X1() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP_X1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackInstruction(this);
+ v.visitDUP_X1(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * DUP_X2 - Duplicate top operand stack word and put three down
+ * <PRE>Stack: ..., word3, word2, word1 -> ..., word1, word3, word2, word1</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class DUP_X2 extends StackInstruction {
+
+ public DUP_X2() {
+ super(org.apache.tomcat.util.bcel.Constants.DUP_X2);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackInstruction(this);
+ v.visitDUP_X2(this);
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.ArrayElementValue;
+import org.apache.tomcat.util.bcel.classfile.ClassElementValue;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+import org.apache.tomcat.util.bcel.classfile.EnumElementValue;
+import org.apache.tomcat.util.bcel.classfile.SimpleElementValue;
+
+public abstract class ElementValueGen
+{
+ protected int type;
+
+ protected ConstantPoolGen cpGen;
+
+ protected ElementValueGen(int type, ConstantPoolGen cpGen)
+ {
+ this.type = type;
+ this.cpGen = cpGen;
+ }
+
+ /**
+ * Subtypes return an immutable variant of the ElementValueGen
+ */
+ public abstract ElementValue getElementValue();
+
+ public int getElementValueType()
+ {
+ return type;
+ }
+
+ public abstract String stringifyValue();
+
+ public abstract void dump(DataOutputStream dos) throws IOException;
+
+ public static final int STRING = 's';
+
+ public static final int ENUM_CONSTANT = 'e';
+
+ public static final int CLASS = 'c';
+
+ public static final int ANNOTATION = '@';
+
+ public static final int ARRAY = '[';
+
+ public static final int PRIMITIVE_INT = 'I';
+
+ public static final int PRIMITIVE_BYTE = 'B';
+
+ public static final int PRIMITIVE_CHAR = 'C';
+
+ public static final int PRIMITIVE_DOUBLE = 'D';
+
+ public static final int PRIMITIVE_FLOAT = 'F';
+
+ public static final int PRIMITIVE_LONG = 'J';
+
+ public static final int PRIMITIVE_SHORT = 'S';
+
+ public static final int PRIMITIVE_BOOLEAN = 'Z';
+
+ public static ElementValueGen readElementValue(DataInputStream dis,
+ ConstantPoolGen cpGen) throws IOException
+ {
+ int type = dis.readUnsignedByte();
+ switch (type)
+ {
+ case 'B': // byte
+ return new SimpleElementValueGen(PRIMITIVE_BYTE, dis
+ .readUnsignedShort(), cpGen);
+ case 'C': // char
+ return new SimpleElementValueGen(PRIMITIVE_CHAR, dis
+ .readUnsignedShort(), cpGen);
+ case 'D': // double
+ return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis
+ .readUnsignedShort(), cpGen);
+ case 'F': // float
+ return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis
+ .readUnsignedShort(), cpGen);
+ case 'I': // int
+ return new SimpleElementValueGen(PRIMITIVE_INT, dis
+ .readUnsignedShort(), cpGen);
+ case 'J': // long
+ return new SimpleElementValueGen(PRIMITIVE_LONG, dis
+ .readUnsignedShort(), cpGen);
+ case 'S': // short
+ return new SimpleElementValueGen(PRIMITIVE_SHORT, dis
+ .readUnsignedShort(), cpGen);
+ case 'Z': // boolean
+ return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis
+ .readUnsignedShort(), cpGen);
+ case 's': // String
+ return new SimpleElementValueGen(STRING, dis.readUnsignedShort(),
+ cpGen);
+ case 'e': // Enum constant
+ return new EnumElementValueGen(dis.readUnsignedShort(), dis
+ .readUnsignedShort(), cpGen);
+ case 'c': // Class
+ return new ClassElementValueGen(dis.readUnsignedShort(), cpGen);
+ case '@': // Annotation
+ // TODO: isRuntimeVisible ??????????
+ // FIXME
+ return new AnnotationElementValueGen(ANNOTATION,
+ new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen
+ .getConstantPool(), true), cpGen, false), cpGen);
+ case '[': // Array
+ int numArrayVals = dis.readUnsignedShort();
+ ElementValue[] evalues = new ElementValue[numArrayVals];
+ for (int j = 0; j < numArrayVals; j++)
+ {
+ evalues[j] = ElementValue.readElementValue(dis, cpGen
+ .getConstantPool());
+ }
+ return new ArrayElementValueGen(ARRAY, evalues, cpGen);
+ default:
+ throw new RuntimeException(
+ "Unexpected element value kind in annotation: " + type);
+ }
+ }
+
+ protected ConstantPoolGen getConstantPool()
+ {
+ return cpGen;
+ }
+
+ /**
+ * Creates an (modifiable) ElementValueGen copy of an (immutable)
+ * ElementValue - constant pool is assumed correct.
+ */
+ public static ElementValueGen copy(ElementValue value,
+ ConstantPoolGen cpool, boolean copyPoolEntries)
+ {
+ switch (value.getElementValueType())
+ {
+ case 'B': // byte
+ case 'C': // char
+ case 'D': // double
+ case 'F': // float
+ case 'I': // int
+ case 'J': // long
+ case 'S': // short
+ case 'Z': // boolean
+ case 's': // String
+ return new SimpleElementValueGen((SimpleElementValue) value, cpool,
+ copyPoolEntries);
+ case 'e': // Enum constant
+ return new EnumElementValueGen((EnumElementValue) value, cpool,
+ copyPoolEntries);
+ case '@': // Annotation
+ return new AnnotationElementValueGen(
+ (AnnotationElementValue) value, cpool, copyPoolEntries);
+ case '[': // Array
+ return new ArrayElementValueGen((ArrayElementValue) value, cpool,
+ copyPoolEntries);
+ case 'c': // Class
+ return new ClassElementValueGen((ClassElementValue) value, cpool,
+ copyPoolEntries);
+ default:
+ throw new RuntimeException("Not implemented yet! ("
+ + value.getElementValueType() + ")");
+ }
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+import org.apache.tomcat.util.bcel.classfile.ElementValuePair;
+
+public class ElementValuePairGen
+{
+ private int nameIdx;
+
+ private ElementValueGen value;
+
+ private ConstantPoolGen cpool;
+
+ public ElementValuePairGen(ElementValuePair nvp, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ this.cpool = cpool;
+ // J5ASSERT:
+ // Could assert nvp.getNameString() points to the same thing as
+ // cpool.getConstant(nvp.getNameIndex())
+ // if
+ // (!nvp.getNameString().equals(((ConstantUtf8)cpool.getConstant(nvp.getNameIndex())).getBytes()))
+ // {
+ // throw new RuntimeException("envp buggered");
+ // }
+ if (copyPoolEntries)
+ {
+ nameIdx = cpool.addUtf8(nvp.getNameString());
+ }
+ else
+ {
+ nameIdx = nvp.getNameIndex();
+ }
+ value = ElementValueGen.copy(nvp.getValue(), cpool, copyPoolEntries);
+ }
+
+ /**
+ * Retrieve an immutable version of this ElementNameValuePairGen
+ */
+ public ElementValuePair getElementNameValuePair()
+ {
+ ElementValue immutableValue = value.getElementValue();
+ return new ElementValuePair(nameIdx, immutableValue, cpool
+ .getConstantPool());
+ }
+
+ protected ElementValuePairGen(int idx, ElementValueGen value,
+ ConstantPoolGen cpool)
+ {
+ this.nameIdx = idx;
+ this.value = value;
+ this.cpool = cpool;
+ }
+
+ public ElementValuePairGen(String name, ElementValueGen value,
+ ConstantPoolGen cpool)
+ {
+ this.nameIdx = cpool.addUtf8(name);
+ this.value = value;
+ this.cpool = cpool;
+ }
+
+ protected void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeShort(nameIdx); // u2 name of the element
+ value.dump(dos);
+ }
+
+ public int getNameIndex()
+ {
+ return nameIdx;
+ }
+
+ public final String getNameString()
+ {
+ // ConstantString cu8 = (ConstantString)cpool.getConstant(nameIdx);
+ return ((ConstantUtf8) cpool.getConstant(nameIdx)).getBytes();
+ }
+
+ public final ElementValueGen getValue()
+ {
+ return value;
+ }
+
+ public String toString()
+ {
+ return "ElementValuePair:[" + getNameString() + "="
+ + value.stringifyValue() + "]";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Supplies empty method bodies to be overridden by subclasses.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class EmptyVisitor implements Visitor {
+
+ public void visitStackInstruction( StackInstruction obj ) {
+ }
+
+
+ public void visitLocalVariableInstruction( LocalVariableInstruction obj ) {
+ }
+
+
+ public void visitBranchInstruction( BranchInstruction obj ) {
+ }
+
+
+ public void visitLoadClass( LoadClass obj ) {
+ }
+
+
+ public void visitFieldInstruction( FieldInstruction obj ) {
+ }
+
+
+ public void visitIfInstruction( IfInstruction obj ) {
+ }
+
+
+ public void visitConversionInstruction( ConversionInstruction obj ) {
+ }
+
+
+ public void visitPopInstruction( PopInstruction obj ) {
+ }
+
+
+ public void visitJsrInstruction( JsrInstruction obj ) {
+ }
+
+
+ public void visitGotoInstruction( GotoInstruction obj ) {
+ }
+
+
+ public void visitStoreInstruction( StoreInstruction obj ) {
+ }
+
+
+ public void visitTypedInstruction( TypedInstruction obj ) {
+ }
+
+
+ public void visitSelect( Select obj ) {
+ }
+
+
+ public void visitUnconditionalBranch( UnconditionalBranch obj ) {
+ }
+
+
+ public void visitPushInstruction( PushInstruction obj ) {
+ }
+
+
+ public void visitArithmeticInstruction( ArithmeticInstruction obj ) {
+ }
+
+
+ public void visitCPInstruction( CPInstruction obj ) {
+ }
+
+
+ public void visitInvokeInstruction( InvokeInstruction obj ) {
+ }
+
+
+ public void visitArrayInstruction( ArrayInstruction obj ) {
+ }
+
+
+ public void visitAllocationInstruction( AllocationInstruction obj ) {
+ }
+
+
+ public void visitReturnInstruction( ReturnInstruction obj ) {
+ }
+
+
+ public void visitFieldOrMethod( FieldOrMethod obj ) {
+ }
+
+
+ public void visitConstantPushInstruction( ConstantPushInstruction obj ) {
+ }
+
+
+ public void visitExceptionThrower( ExceptionThrower obj ) {
+ }
+
+
+ public void visitLoadInstruction( LoadInstruction obj ) {
+ }
+
+
+ public void visitVariableLengthInstruction( VariableLengthInstruction obj ) {
+ }
+
+
+ public void visitStackProducer( StackProducer obj ) {
+ }
+
+
+ public void visitStackConsumer( StackConsumer obj ) {
+ }
+
+
+ public void visitACONST_NULL( ACONST_NULL obj ) {
+ }
+
+
+ public void visitGETSTATIC( GETSTATIC obj ) {
+ }
+
+
+ public void visitIF_ICMPLT( IF_ICMPLT obj ) {
+ }
+
+
+ public void visitMONITOREXIT( MONITOREXIT obj ) {
+ }
+
+
+ public void visitIFLT( IFLT obj ) {
+ }
+
+
+ public void visitLSTORE( LSTORE obj ) {
+ }
+
+
+ public void visitPOP2( POP2 obj ) {
+ }
+
+
+ public void visitBASTORE( BASTORE obj ) {
+ }
+
+
+ public void visitISTORE( ISTORE obj ) {
+ }
+
+
+ public void visitCHECKCAST( CHECKCAST obj ) {
+ }
+
+
+ public void visitFCMPG( FCMPG obj ) {
+ }
+
+
+ public void visitI2F( I2F obj ) {
+ }
+
+
+ public void visitATHROW( ATHROW obj ) {
+ }
+
+
+ public void visitDCMPL( DCMPL obj ) {
+ }
+
+
+ public void visitARRAYLENGTH( ARRAYLENGTH obj ) {
+ }
+
+
+ public void visitDUP( DUP obj ) {
+ }
+
+
+ public void visitINVOKESTATIC( INVOKESTATIC obj ) {
+ }
+
+
+ public void visitLCONST( LCONST obj ) {
+ }
+
+
+ public void visitDREM( DREM obj ) {
+ }
+
+
+ public void visitIFGE( IFGE obj ) {
+ }
+
+
+ public void visitCALOAD( CALOAD obj ) {
+ }
+
+
+ public void visitLASTORE( LASTORE obj ) {
+ }
+
+
+ public void visitI2D( I2D obj ) {
+ }
+
+
+ public void visitDADD( DADD obj ) {
+ }
+
+
+ public void visitINVOKESPECIAL( INVOKESPECIAL obj ) {
+ }
+
+
+ public void visitIAND( IAND obj ) {
+ }
+
+
+ public void visitPUTFIELD( PUTFIELD obj ) {
+ }
+
+
+ public void visitILOAD( ILOAD obj ) {
+ }
+
+
+ public void visitDLOAD( DLOAD obj ) {
+ }
+
+
+ public void visitDCONST( DCONST obj ) {
+ }
+
+
+ public void visitNEW( NEW obj ) {
+ }
+
+
+ public void visitIFNULL( IFNULL obj ) {
+ }
+
+
+ public void visitLSUB( LSUB obj ) {
+ }
+
+
+ public void visitL2I( L2I obj ) {
+ }
+
+
+ public void visitISHR( ISHR obj ) {
+ }
+
+
+ public void visitTABLESWITCH( TABLESWITCH obj ) {
+ }
+
+
+ public void visitIINC( IINC obj ) {
+ }
+
+
+ public void visitDRETURN( DRETURN obj ) {
+ }
+
+
+ public void visitFSTORE( FSTORE obj ) {
+ }
+
+
+ public void visitDASTORE( DASTORE obj ) {
+ }
+
+
+ public void visitIALOAD( IALOAD obj ) {
+ }
+
+
+ public void visitDDIV( DDIV obj ) {
+ }
+
+
+ public void visitIF_ICMPGE( IF_ICMPGE obj ) {
+ }
+
+
+ public void visitLAND( LAND obj ) {
+ }
+
+
+ public void visitIDIV( IDIV obj ) {
+ }
+
+
+ public void visitLOR( LOR obj ) {
+ }
+
+
+ public void visitCASTORE( CASTORE obj ) {
+ }
+
+
+ public void visitFREM( FREM obj ) {
+ }
+
+
+ public void visitLDC( LDC obj ) {
+ }
+
+
+ public void visitBIPUSH( BIPUSH obj ) {
+ }
+
+
+ public void visitDSTORE( DSTORE obj ) {
+ }
+
+
+ public void visitF2L( F2L obj ) {
+ }
+
+
+ public void visitFMUL( FMUL obj ) {
+ }
+
+
+ public void visitLLOAD( LLOAD obj ) {
+ }
+
+
+ public void visitJSR( JSR obj ) {
+ }
+
+
+ public void visitFSUB( FSUB obj ) {
+ }
+
+
+ public void visitSASTORE( SASTORE obj ) {
+ }
+
+
+ public void visitALOAD( ALOAD obj ) {
+ }
+
+
+ public void visitDUP2_X2( DUP2_X2 obj ) {
+ }
+
+
+ public void visitRETURN( RETURN obj ) {
+ }
+
+
+ public void visitDALOAD( DALOAD obj ) {
+ }
+
+
+ public void visitSIPUSH( SIPUSH obj ) {
+ }
+
+
+ public void visitDSUB( DSUB obj ) {
+ }
+
+
+ public void visitL2F( L2F obj ) {
+ }
+
+
+ public void visitIF_ICMPGT( IF_ICMPGT obj ) {
+ }
+
+
+ public void visitF2D( F2D obj ) {
+ }
+
+
+ public void visitI2L( I2L obj ) {
+ }
+
+
+ public void visitIF_ACMPNE( IF_ACMPNE obj ) {
+ }
+
+
+ public void visitPOP( POP obj ) {
+ }
+
+
+ public void visitI2S( I2S obj ) {
+ }
+
+
+ public void visitIFEQ( IFEQ obj ) {
+ }
+
+
+ public void visitSWAP( SWAP obj ) {
+ }
+
+
+ public void visitIOR( IOR obj ) {
+ }
+
+
+ public void visitIREM( IREM obj ) {
+ }
+
+
+ public void visitIASTORE( IASTORE obj ) {
+ }
+
+
+ public void visitNEWARRAY( NEWARRAY obj ) {
+ }
+
+
+ public void visitINVOKEINTERFACE( INVOKEINTERFACE obj ) {
+ }
+
+
+ public void visitINEG( INEG obj ) {
+ }
+
+
+ public void visitLCMP( LCMP obj ) {
+ }
+
+
+ public void visitJSR_W( JSR_W obj ) {
+ }
+
+
+ public void visitMULTIANEWARRAY( MULTIANEWARRAY obj ) {
+ }
+
+
+ public void visitDUP_X2( DUP_X2 obj ) {
+ }
+
+
+ public void visitSALOAD( SALOAD obj ) {
+ }
+
+
+ public void visitIFNONNULL( IFNONNULL obj ) {
+ }
+
+
+ public void visitDMUL( DMUL obj ) {
+ }
+
+
+ public void visitIFNE( IFNE obj ) {
+ }
+
+
+ public void visitIF_ICMPLE( IF_ICMPLE obj ) {
+ }
+
+
+ public void visitLDC2_W( LDC2_W obj ) {
+ }
+
+
+ public void visitGETFIELD( GETFIELD obj ) {
+ }
+
+
+ public void visitLADD( LADD obj ) {
+ }
+
+
+ public void visitNOP( NOP obj ) {
+ }
+
+
+ public void visitFALOAD( FALOAD obj ) {
+ }
+
+
+ public void visitINSTANCEOF( INSTANCEOF obj ) {
+ }
+
+
+ public void visitIFLE( IFLE obj ) {
+ }
+
+
+ public void visitLXOR( LXOR obj ) {
+ }
+
+
+ public void visitLRETURN( LRETURN obj ) {
+ }
+
+
+ public void visitFCONST( FCONST obj ) {
+ }
+
+
+ public void visitIUSHR( IUSHR obj ) {
+ }
+
+
+ public void visitBALOAD( BALOAD obj ) {
+ }
+
+
+ public void visitDUP2( DUP2 obj ) {
+ }
+
+
+ public void visitIF_ACMPEQ( IF_ACMPEQ obj ) {
+ }
+
+
+ public void visitIMPDEP1( IMPDEP1 obj ) {
+ }
+
+
+ public void visitMONITORENTER( MONITORENTER obj ) {
+ }
+
+
+ public void visitLSHL( LSHL obj ) {
+ }
+
+
+ public void visitDCMPG( DCMPG obj ) {
+ }
+
+
+ public void visitD2L( D2L obj ) {
+ }
+
+
+ public void visitIMPDEP2( IMPDEP2 obj ) {
+ }
+
+
+ public void visitL2D( L2D obj ) {
+ }
+
+
+ public void visitRET( RET obj ) {
+ }
+
+
+ public void visitIFGT( IFGT obj ) {
+ }
+
+
+ public void visitIXOR( IXOR obj ) {
+ }
+
+
+ public void visitINVOKEVIRTUAL( INVOKEVIRTUAL obj ) {
+ }
+
+
+ public void visitFASTORE( FASTORE obj ) {
+ }
+
+
+ public void visitIRETURN( IRETURN obj ) {
+ }
+
+
+ public void visitIF_ICMPNE( IF_ICMPNE obj ) {
+ }
+
+
+ public void visitFLOAD( FLOAD obj ) {
+ }
+
+
+ public void visitLDIV( LDIV obj ) {
+ }
+
+
+ public void visitPUTSTATIC( PUTSTATIC obj ) {
+ }
+
+
+ public void visitAALOAD( AALOAD obj ) {
+ }
+
+
+ public void visitD2I( D2I obj ) {
+ }
+
+
+ public void visitIF_ICMPEQ( IF_ICMPEQ obj ) {
+ }
+
+
+ public void visitAASTORE( AASTORE obj ) {
+ }
+
+
+ public void visitARETURN( ARETURN obj ) {
+ }
+
+
+ public void visitDUP2_X1( DUP2_X1 obj ) {
+ }
+
+
+ public void visitFNEG( FNEG obj ) {
+ }
+
+
+ public void visitGOTO_W( GOTO_W obj ) {
+ }
+
+
+ public void visitD2F( D2F obj ) {
+ }
+
+
+ public void visitGOTO( GOTO obj ) {
+ }
+
+
+ public void visitISUB( ISUB obj ) {
+ }
+
+
+ public void visitF2I( F2I obj ) {
+ }
+
+
+ public void visitDNEG( DNEG obj ) {
+ }
+
+
+ public void visitICONST( ICONST obj ) {
+ }
+
+
+ public void visitFDIV( FDIV obj ) {
+ }
+
+
+ public void visitI2B( I2B obj ) {
+ }
+
+
+ public void visitLNEG( LNEG obj ) {
+ }
+
+
+ public void visitLREM( LREM obj ) {
+ }
+
+
+ public void visitIMUL( IMUL obj ) {
+ }
+
+
+ public void visitIADD( IADD obj ) {
+ }
+
+
+ public void visitLSHR( LSHR obj ) {
+ }
+
+
+ public void visitLOOKUPSWITCH( LOOKUPSWITCH obj ) {
+ }
+
+
+ public void visitDUP_X1( DUP_X1 obj ) {
+ }
+
+
+ public void visitFCMPL( FCMPL obj ) {
+ }
+
+
+ public void visitI2C( I2C obj ) {
+ }
+
+
+ public void visitLMUL( LMUL obj ) {
+ }
+
+
+ public void visitLUSHR( LUSHR obj ) {
+ }
+
+
+ public void visitISHL( ISHL obj ) {
+ }
+
+
+ public void visitLALOAD( LALOAD obj ) {
+ }
+
+
+ public void visitASTORE( ASTORE obj ) {
+ }
+
+
+ public void visitANEWARRAY( ANEWARRAY obj ) {
+ }
+
+
+ public void visitFRETURN( FRETURN obj ) {
+ }
+
+
+ public void visitFADD( FADD obj ) {
+ }
+
+
+ public void visitBREAKPOINT( BREAKPOINT obj ) {
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+import org.apache.tomcat.util.bcel.classfile.EnumElementValue;
+
+public class EnumElementValueGen extends ElementValueGen
+{
+ // For enum types, these two indices point to the type and value
+ private int typeIdx;
+
+ private int valueIdx;
+
+ /**
+ * This ctor assumes the constant pool already contains the right type and
+ * value - as indicated by typeIdx and valueIdx. This ctor is used for
+ * deserialization
+ */
+ protected EnumElementValueGen(int typeIdx, int valueIdx,
+ ConstantPoolGen cpool)
+ {
+ super(ElementValueGen.ENUM_CONSTANT, cpool);
+ if (type != ENUM_CONSTANT)
+ throw new RuntimeException(
+ "Only element values of type enum can be built with this ctor - type specified: " + type);
+ this.typeIdx = typeIdx;
+ this.valueIdx = valueIdx;
+ }
+
+ /**
+ * Return immutable variant of this EnumElementValue
+ */
+ public ElementValue getElementValue()
+ {
+ System.err.println("Duplicating value: " + getEnumTypeString() + ":"
+ + getEnumValueString());
+ return new EnumElementValue(type, typeIdx, valueIdx, cpGen
+ .getConstantPool());
+ }
+
+ public EnumElementValueGen(ObjectType t, String value, ConstantPoolGen cpool)
+ {
+ super(ElementValueGen.ENUM_CONSTANT, cpool);
+ typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t);
+ valueIdx = cpool.addUtf8(value);// was addString(value);
+ }
+
+ public EnumElementValueGen(EnumElementValue value, ConstantPoolGen cpool,
+ boolean copyPoolEntries)
+ {
+ super(ENUM_CONSTANT, cpool);
+ if (copyPoolEntries)
+ {
+ typeIdx = cpool.addUtf8(value.getEnumTypeString());// was
+ // addClass(value.getEnumTypeString());
+ valueIdx = cpool.addUtf8(value.getEnumValueString()); // was
+ // addString(value.getEnumValueString());
+ }
+ else
+ {
+ typeIdx = value.getTypeIndex();
+ valueIdx = value.getValueIndex();
+ }
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e')
+ dos.writeShort(typeIdx); // u2
+ dos.writeShort(valueIdx); // u2
+ }
+
+ public String stringifyValue()
+ {
+ ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(
+ valueIdx);
+ return cu8.getBytes();
+ // ConstantString cu8 =
+ // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // return
+ // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ }
+
+ // BCELBUG: Should we need to call utility.signatureToString() on the output
+ // here?
+ public String getEnumTypeString()
+ {
+ // Constant cc = getConstantPool().getConstant(typeIdx);
+ // ConstantClass cu8 =
+ // (ConstantClass)getConstantPool().getConstant(typeIdx);
+ // return
+ // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
+ return ((ConstantUtf8) getConstantPool().getConstant(typeIdx))
+ .getBytes();
+ // return Utility.signatureToString(cu8.getBytes());
+ }
+
+ public String getEnumValueString()
+ {
+ return ((ConstantUtf8) getConstantPool().getConstant(valueIdx))
+ .getBytes();
+ // ConstantString cu8 =
+ // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // return
+ // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ }
+
+ public int getValueIndex()
+ {
+ return valueIdx;
+ }
+
+ public int getTypeIndex()
+ {
+ return typeIdx;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote an instruction that may throw a run-time or a linking
+ * exception (or both) during execution. This is not quite the truth
+ * as such; because all instructions may throw an
+ * java.lang.VirtualMachineError. These exceptions are omitted.
+ *
+ * The Lava Language Specification specifies exactly which
+ * <i>RUN-TIME</i> and which <i>LINKING</i> exceptions each
+ * instruction may throw which is reflected by the implementers. Due
+ * to the structure of the JVM specification, it may be possible that
+ * an Instruction implementing this interface returns a Class[] of
+ * size 0.
+ *
+ * Please note that we speak of an "exception" here when we mean any
+ * "Throwable" object; so this term is equally used for "Exception"
+ * and "Error" objects.
+ *
+ * @version $Id$
+ * @author Enver Haase
+ */
+public interface ExceptionThrower {
+
+ public java.lang.Class[] getExceptions();
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * F2D - Convert float to double
+ * <PRE>Stack: ..., value -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class F2D extends ConversionInstruction {
+
+ /** Convert float to double
+ */
+ public F2D() {
+ super(org.apache.tomcat.util.bcel.Constants.F2D);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitF2D(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * F2I - Convert float to int
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class F2I extends ConversionInstruction {
+
+ /** Convert float to int
+ */
+ public F2I() {
+ super(org.apache.tomcat.util.bcel.Constants.F2I);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitF2I(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * F2L - Convert float to long
+ * <PRE>Stack: ..., value -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class F2L extends ConversionInstruction {
+
+ /** Convert float to long
+ */
+ public F2L() {
+ super(org.apache.tomcat.util.bcel.Constants.F2L);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitF2L(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FADD - Add floats
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FADD extends ArithmeticInstruction {
+
+ /** Add floats
+ */
+ public FADD() {
+ super(org.apache.tomcat.util.bcel.Constants.FADD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFADD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FALOAD - Load float from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load float from array
+ */
+ public FALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.FALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitFALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FASTORE - Store into float array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store float into array
+ */
+ public FASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.FASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitFASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FCMPG - Compare floats: value1 > value2
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
+
+ public FCMPG() {
+ super(org.apache.tomcat.util.bcel.Constants.FCMPG, (short) 1);
+ }
+
+
+ /** @return Type.FLOAT
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.FLOAT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitFCMPG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FCMPL - Compare floats: value1 < value2
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
+
+ public FCMPL() {
+ super(org.apache.tomcat.util.bcel.Constants.FCMPL, (short) 1);
+ }
+
+
+ /** @return Type.FLOAT
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.FLOAT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitFCMPL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FCONST - Push 0.0, 1.0 or 2.0, other values cause an exception
+ *
+ * <PRE>Stack: ... -> ..., </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FCONST extends Instruction implements ConstantPushInstruction, TypedInstruction {
+
+ private float value;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ FCONST() {
+ }
+
+
+ public FCONST(float f) {
+ super(org.apache.tomcat.util.bcel.Constants.FCONST_0, (short) 1);
+ if (f == 0.0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.FCONST_0;
+ } else if (f == 1.0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.FCONST_1;
+ } else if (f == 2.0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.FCONST_2;
+ } else {
+ throw new ClassGenException("FCONST can be used only for 0.0, 1.0 and 2.0: " + f);
+ }
+ value = f;
+ }
+
+
+ public Number getValue() {
+ return new Float(value);
+ }
+
+
+ /** @return Type.FLOAT
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.FLOAT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitFCONST(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FDIV - Divide floats
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FDIV extends ArithmeticInstruction {
+
+ /** Divide floats
+ */
+ public FDIV() {
+ super(org.apache.tomcat.util.bcel.Constants.FDIV);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFDIV(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FLOAD - Load float from local variable
+ * <PRE>Stack ... -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FLOAD extends LoadInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ FLOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.FLOAD, org.apache.tomcat.util.bcel.Constants.FLOAD_0);
+ }
+
+
+ /** Load float from local variable
+ * @param n index of local variable
+ */
+ public FLOAD(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.FLOAD, org.apache.tomcat.util.bcel.Constants.FLOAD_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitFLOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FMUL - Multiply floats
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FMUL extends ArithmeticInstruction {
+
+ /** Multiply floats
+ */
+ public FMUL() {
+ super(org.apache.tomcat.util.bcel.Constants.FMUL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFMUL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FNEG - Negate float
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FNEG extends ArithmeticInstruction {
+
+ public FNEG() {
+ super(org.apache.tomcat.util.bcel.Constants.FNEG);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFNEG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FREM - Remainder of floats
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FREM extends ArithmeticInstruction {
+
+ /** Remainder of floats
+ */
+ public FREM() {
+ super(org.apache.tomcat.util.bcel.Constants.FREM);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFREM(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FRETURN - Return float from method
+ * <PRE>Stack: ..., value -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FRETURN extends ReturnInstruction {
+
+ /** Return float from method
+ */
+ public FRETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.FRETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitFRETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FSTORE - Store float into local variable
+ * <PRE>Stack: ..., value -> ... </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FSTORE extends StoreInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ FSTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.FSTORE, org.apache.tomcat.util.bcel.Constants.FSTORE_0);
+ }
+
+
+ /** Store float into local variable
+ * @param n index of local variable
+ */
+ public FSTORE(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.FSTORE, org.apache.tomcat.util.bcel.Constants.FSTORE_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitFSTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * FSUB - Substract floats
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class FSUB extends ArithmeticInstruction {
+
+ /** Substract floats
+ */
+ public FSUB() {
+ super(org.apache.tomcat.util.bcel.Constants.FSUB);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitFSUB(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.Annotations;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.classfile.ConstantObject;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantValue;
+import org.apache.tomcat.util.bcel.classfile.Field;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * Template class for building up a field. The only extraordinary thing
+ * one can do is to add a constant value attribute to a field (which must of
+ * course be compatible with to the declared type).
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Field
+ */
+public class FieldGen extends FieldGenOrMethodGen {
+
+ private Object value = null;
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ FieldGen THIS = (FieldGen) o1;
+ FieldGen THAT = (FieldGen) o2;
+ return THIS.getName().equals(THAT.getName())
+ && THIS.getSignature().equals(THAT.getSignature());
+ }
+
+
+ public int hashCode( Object o ) {
+ FieldGen THIS = (FieldGen) o;
+ return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ }
+ };
+
+
+ /**
+ * Declare a field. If it is static (isStatic() == true) and has a
+ * basic type like int or String it may have an initial value
+ * associated with it as defined by setInitValue().
+ *
+ * @param access_flags access qualifiers
+ * @param type field type
+ * @param name field name
+ * @param cp constant pool
+ */
+ public FieldGen(int access_flags, Type type, String name, ConstantPoolGen cp) {
+ setAccessFlags(access_flags);
+ setType(type);
+ setName(name);
+ setConstantPool(cp);
+ }
+
+
+ /**
+ * Instantiate from existing field.
+ *
+ * @param field Field object
+ * @param cp constant pool (must contain the same entries as the field's constant pool)
+ */
+ public FieldGen(Field field, ConstantPoolGen cp) {
+ this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
+ Attribute[] attrs = field.getAttributes();
+ for (int i = 0; i < attrs.length; i++) {
+ if (attrs[i] instanceof ConstantValue) {
+ setValue(((ConstantValue) attrs[i]).getConstantValueIndex());
+ } else if (attrs[i] instanceof Annotations) {
+ Annotations runtimeAnnotations = (Annotations)attrs[i];
+ AnnotationEntry[] annotationEntries = runtimeAnnotations.getAnnotationEntries();
+ for (int j = 0; j < annotationEntries.length; j++) {
+ AnnotationEntry element = annotationEntries[j];
+ addAnnotationEntry(new AnnotationEntryGen(element,cp,false));
+ }
+ } else {
+ addAttribute(attrs[i]);
+ }
+ }
+ }
+
+
+ private void setValue( int index ) {
+ ConstantPool cp = this.cp.getConstantPool();
+ Constant c = cp.getConstant(index);
+ value = ((ConstantObject) c).getConstantValue(cp);
+ }
+
+
+ /**
+ * Set (optional) initial value of field, otherwise it will be set to null/0/false
+ * by the JVM automatically.
+ */
+ public void setInitValue( String str ) {
+ checkType(new ObjectType("java.lang.String"));
+ if (str != null) {
+ value = str;
+ }
+ }
+
+
+ public void setInitValue( long l ) {
+ checkType(Type.LONG);
+ if (l != 0L) {
+ value = new Long(l);
+ }
+ }
+
+
+ public void setInitValue( int i ) {
+ checkType(Type.INT);
+ if (i != 0) {
+ value = new Integer(i);
+ }
+ }
+
+
+ public void setInitValue( short s ) {
+ checkType(Type.SHORT);
+ if (s != 0) {
+ value = new Integer(s);
+ }
+ }
+
+
+ public void setInitValue( char c ) {
+ checkType(Type.CHAR);
+ if (c != 0) {
+ value = new Integer(c);
+ }
+ }
+
+
+ public void setInitValue( byte b ) {
+ checkType(Type.BYTE);
+ if (b != 0) {
+ value = new Integer(b);
+ }
+ }
+
+
+ public void setInitValue( boolean b ) {
+ checkType(Type.BOOLEAN);
+ if (b) {
+ value = new Integer(1);
+ }
+ }
+
+
+ public void setInitValue( float f ) {
+ checkType(Type.FLOAT);
+ if (f != 0.0) {
+ value = new Float(f);
+ }
+ }
+
+
+ public void setInitValue( double d ) {
+ checkType(Type.DOUBLE);
+ if (d != 0.0) {
+ value = new Double(d);
+ }
+ }
+
+
+ /** Remove any initial value.
+ */
+ public void cancelInitValue() {
+ value = null;
+ }
+
+
+ private void checkType( Type atype ) {
+ if (type == null) {
+ throw new ClassGenException("You haven't defined the type of the field yet");
+ }
+ if (!isFinal()) {
+ throw new ClassGenException("Only final fields may have an initial value!");
+ }
+ if (!type.equals(atype)) {
+ throw new ClassGenException("Types are not compatible: " + type + " vs. " + atype);
+ }
+ }
+
+
+ /**
+ * Get field object after having set up all necessary values.
+ */
+ public Field getField() {
+ String signature = getSignature();
+ int name_index = cp.addUtf8(name);
+ int signature_index = cp.addUtf8(signature);
+ if (value != null) {
+ checkType(type);
+ int index = addConstant();
+ addAttribute(new ConstantValue(cp.addUtf8("ConstantValue"), 2, index, cp
+ .getConstantPool()));
+ }
+ addAnnotationsAsAttribute(cp);
+ return new Field(access_flags, name_index, signature_index, getAttributes(), cp
+ .getConstantPool());
+ }
+
+ private void addAnnotationsAsAttribute(ConstantPoolGen cp) {
+ Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotation_vec);
+ for (int i = 0; i < attrs.length; i++) {
+ addAttribute(attrs[i]);
+ }
+ }
+
+
+ private int addConstant() {
+ switch (type.getType()) {
+ case Constants.T_INT:
+ case Constants.T_CHAR:
+ case Constants.T_BYTE:
+ case Constants.T_BOOLEAN:
+ case Constants.T_SHORT:
+ return cp.addInteger(((Integer) value).intValue());
+ case Constants.T_FLOAT:
+ return cp.addFloat(((Float) value).floatValue());
+ case Constants.T_DOUBLE:
+ return cp.addDouble(((Double) value).doubleValue());
+ case Constants.T_LONG:
+ return cp.addLong(((Long) value).longValue());
+ case Constants.T_REFERENCE:
+ return cp.addString(((String) value));
+ default:
+ throw new RuntimeException("Oops: Unhandled : " + type.getType());
+ }
+ }
+
+
+ public String getSignature() {
+ return type.getSignature();
+ }
+
+ private List observers;
+
+
+ /** Add observer for this object.
+ */
+ public void addObserver( FieldObserver o ) {
+ if (observers == null) {
+ observers = new ArrayList();
+ }
+ observers.add(o);
+ }
+
+
+ /** Remove observer for this object.
+ */
+ public void removeObserver( FieldObserver o ) {
+ if (observers != null) {
+ observers.remove(o);
+ }
+ }
+
+
+ /** Call notify() method on all observers. This method is not called
+ * automatically whenever the state has changed, but has to be
+ * called by the user after he has finished editing the object.
+ */
+ public void update() {
+ if (observers != null) {
+ for (Iterator e = observers.iterator(); e.hasNext();) {
+ ((FieldObserver) e.next()).notify(this);
+ }
+ }
+ }
+
+
+ public String getInitValue() {
+ if (value != null) {
+ return value.toString();
+ } else {
+ return null;
+ }
+ }
+
+
+ /**
+ * Return string representation close to declaration format,
+ * `public static final short MAX = 100', e.g..
+ *
+ * @return String representation of field
+ */
+ public final String toString() {
+ String name, signature, access; // Short cuts to constant pool
+ access = Utility.accessToString(access_flags);
+ access = access.equals("") ? "" : (access + " ");
+ signature = type.toString();
+ name = getName();
+ StringBuffer buf = new StringBuffer(32);
+ buf.append(access).append(signature).append(" ").append(name);
+ String value = getInitValue();
+ if (value != null) {
+ buf.append(" = ").append(value);
+ }
+ return buf.toString();
+ }
+
+
+ /** @return deep copy of this field
+ */
+ public FieldGen copy( ConstantPoolGen cp ) {
+ FieldGen fg = (FieldGen) clone();
+ fg.setConstantPool(cp);
+ return fg;
+ }
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two FieldGen objects are said to be equal when
+ * their names and signatures are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the field's name XOR signature.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.AccessFlags;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+
+/**
+ * Super class for FieldGen and MethodGen objects, since they have
+ * some methods in common!
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
+
+ protected String name;
+ protected Type type;
+ protected ConstantPoolGen cp;
+ private List attribute_vec = new ArrayList();
+ protected ArrayList annotation_vec= new ArrayList();
+
+
+ protected FieldGenOrMethodGen() {
+ }
+
+
+ public void setType( Type type ) {
+ if (type.getType() == Constants.T_ADDRESS) {
+ throw new IllegalArgumentException("Type can not be " + type);
+ }
+ this.type = type;
+ }
+
+
+ public Type getType() {
+ return type;
+ }
+
+
+ /** @return name of method/field.
+ */
+ public String getName() {
+ return name;
+ }
+
+
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+
+ public ConstantPoolGen getConstantPool() {
+ return cp;
+ }
+
+
+ public void setConstantPool( ConstantPoolGen cp ) {
+ this.cp = cp;
+ }
+
+
+ /**
+ * Add an attribute to this method. Currently, the JVM knows about
+ * the `Code', `ConstantValue', `Synthetic' and `Exceptions'
+ * attributes. Other attributes will be ignored by the JVM but do no
+ * harm.
+ *
+ * @param a attribute to be added
+ */
+ public void addAttribute( Attribute a ) {
+ attribute_vec.add(a);
+ }
+
+ public void addAnnotationEntry(AnnotationEntryGen ag)
+ {
+ annotation_vec.add(ag);
+ }
+
+
+ /**
+ * Remove an attribute.
+ */
+ public void removeAttribute( Attribute a ) {
+ attribute_vec.remove(a);
+ }
+
+ public void removeAnnotationEntry(AnnotationEntryGen ag)
+ {
+ annotation_vec.remove(ag);
+ }
+
+
+ /**
+ * Remove all attributes.
+ */
+ public void removeAttributes() {
+ attribute_vec.clear();
+ }
+
+ public void removeAnnotationEntries()
+ {
+ annotation_vec.clear();
+ }
+
+
+ /**
+ * @return all attributes of this method.
+ */
+ public Attribute[] getAttributes() {
+ Attribute[] attributes = new Attribute[attribute_vec.size()];
+ attribute_vec.toArray(attributes);
+ return attributes;
+ }
+
+ public AnnotationEntryGen[] getAnnotationEntries() {
+ AnnotationEntryGen[] annotations = new AnnotationEntryGen[annotation_vec.size()];
+ annotation_vec.toArray(annotations);
+ return annotations;
+ }
+
+
+ /** @return signature of method/field.
+ */
+ public abstract String getSignature();
+
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+
+/**
+ * Super class for the GET/PUTxxx family of instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class FieldInstruction extends FieldOrMethod implements TypedInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ FieldInstruction() {
+ }
+
+
+ /**
+ * @param index to constant pool
+ */
+ protected FieldInstruction(short opcode, int index) {
+ super(opcode, index);
+ }
+
+
+ /**
+ * @return mnemonic for instruction with symbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ return org.apache.tomcat.util.bcel.Constants.OPCODE_NAMES[opcode] + " "
+ + cp.constantToString(index, org.apache.tomcat.util.bcel.Constants.CONSTANT_Fieldref);
+ }
+
+
+ /** @return size of field (1 or 2)
+ */
+ protected int getFieldSize( ConstantPoolGen cpg ) {
+ return Type.getTypeSize(getSignature(cpg));
+ }
+
+
+ /** @return return type of referenced field
+ */
+ public Type getType( ConstantPoolGen cpg ) {
+ return getFieldType(cpg);
+ }
+
+
+ /** @return type of field
+ */
+ public Type getFieldType( ConstantPoolGen cpg ) {
+ return Type.getType(getSignature(cpg));
+ }
+
+
+ /** @return name of referenced field.
+ */
+ public String getFieldName( ConstantPoolGen cpg ) {
+ return getName(cpg);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Imnplement this interface if you're interested in changes to a FieldGen object
+ * and register yourself with addObserver().
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface FieldObserver {
+
+ public void notify( FieldGen field );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.classfile.ConstantCP;
+import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+
+/**
+ * Super class for InvokeInstruction and FieldInstruction, since they have
+ * some methods in common!
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ FieldOrMethod() {
+ }
+
+
+ /**
+ * @param index to constant pool
+ */
+ protected FieldOrMethod(short opcode, int index) {
+ super(opcode, index);
+ }
+
+
+ /** @return signature of referenced method/field.
+ */
+ public String getSignature( ConstantPoolGen cpg ) {
+ ConstantPool cp = cpg.getConstantPool();
+ ConstantCP cmr = (ConstantCP) cp.getConstant(index);
+ ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
+ return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes();
+ }
+
+
+ /** @return name of referenced method/field.
+ */
+ public String getName( ConstantPoolGen cpg ) {
+ ConstantPool cp = cpg.getConstantPool();
+ ConstantCP cmr = (ConstantCP) cp.getConstant(index);
+ ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex());
+ return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes();
+ }
+
+
+ /** @return name of the referenced class/interface
+ * @deprecated If the instruction references an array class,
+ * this method will return "java.lang.Object".
+ * For code generated by Java 1.5, this answer is
+ * sometimes wrong (e.g., if the "clone()" method is
+ * called on an array). A better idea is to use
+ * the getReferenceType() method, which correctly distinguishes
+ * between class types and array types.
+ */
+ public String getClassName( ConstantPoolGen cpg ) {
+ ConstantPool cp = cpg.getConstantPool();
+ ConstantCP cmr = (ConstantCP) cp.getConstant(index);
+ String className = cp.getConstantString(cmr.getClassIndex(),
+ org.apache.tomcat.util.bcel.Constants.CONSTANT_Class);
+ if (className.startsWith("[")) {
+ // Turn array classes into java.lang.Object.
+ return "java.lang.Object";
+ }
+ return className.replace('/', '.');
+ }
+
+
+ /** @return type of the referenced class/interface
+ * @deprecated If the instruction references an array class,
+ * the ObjectType returned will be invalid. Use
+ * getReferenceType() instead.
+ */
+ public ObjectType getClassType( ConstantPoolGen cpg ) {
+ return new ObjectType(getClassName(cpg));
+ }
+
+
+ /**
+ * Return the reference type representing the class, interface,
+ * or array class referenced by the instruction.
+ * @param cpg the ConstantPoolGen used to create the instruction
+ * @return an ObjectType (if the referenced class type is a class
+ * or interface), or an ArrayType (if the referenced class
+ * type is an array class)
+ */
+ public ReferenceType getReferenceType( ConstantPoolGen cpg ) {
+ ConstantPool cp = cpg.getConstantPool();
+ ConstantCP cmr = (ConstantCP) cp.getConstant(index);
+ String className = cp.getConstantString(cmr.getClassIndex(),
+ org.apache.tomcat.util.bcel.Constants.CONSTANT_Class);
+ if (className.startsWith("[")) {
+ return (ArrayType) Type.getType(className);
+ } else {
+ className = className.replace('/', '.');
+ return new ObjectType(className);
+ }
+ }
+
+
+ /** @return type of the referenced class/interface
+ */
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ return getClassType(cpg);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * GETFIELD - Fetch field from object
+ * <PRE>Stack: ..., objectref -> ..., value</PRE>
+ * OR
+ * <PRE>Stack: ..., objectref -> ..., value.word1, value.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class GETFIELD extends FieldInstruction implements ExceptionThrower, StackConsumer,
+ StackProducer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ GETFIELD() {
+ }
+
+
+ public GETFIELD(int index) {
+ super(Constants.GETFIELD, index);
+ }
+
+
+ public int produceStack( ConstantPoolGen cpg ) {
+ return getFieldSize(cpg);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitFieldInstruction(this);
+ v.visitGETFIELD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * GETSTATIC - Fetch static field from class
+ * <PRE>Stack: ..., -> ..., value</PRE>
+ * OR
+ * <PRE>Stack: ..., -> ..., value.word1, value.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class GETSTATIC extends FieldInstruction implements PushInstruction, ExceptionThrower {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ GETSTATIC() {
+ }
+
+
+ public GETSTATIC(int index) {
+ super(Constants.GETSTATIC, index);
+ }
+
+
+ public int produceStack( ConstantPoolGen cpg ) {
+ return getFieldSize(cpg);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[1 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitFieldInstruction(this);
+ v.visitGETSTATIC(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * GOTO - Branch always (to relative offset, not absolute address)
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class GOTO extends GotoInstruction implements VariableLengthInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ GOTO() {
+ }
+
+
+ public GOTO(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.GOTO, target);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ index = getTargetOffset();
+ if (opcode == org.apache.tomcat.util.bcel.Constants.GOTO) {
+ super.dump(out);
+ } else { // GOTO_W
+ index = getTargetOffset();
+ out.writeByte(opcode);
+ out.writeInt(index);
+ }
+ }
+
+
+ /** Called in pass 2 of InstructionList.setPositions() in order to update
+ * the branch target, that may shift due to variable length instructions.
+ */
+ protected int updatePosition( int offset, int max_offset ) {
+ int i = getTargetOffset(); // Depending on old position value
+ position += offset; // Position may be shifted by preceding expansions
+ if (Math.abs(i) >= (32767 - max_offset)) { // to large for short (estimate)
+ opcode = org.apache.tomcat.util.bcel.Constants.GOTO_W;
+ length = 5;
+ return 2; // 5 - 3
+ }
+ return 0;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitVariableLengthInstruction(this);
+ v.visitUnconditionalBranch(this);
+ v.visitBranchInstruction(this);
+ v.visitGotoInstruction(this);
+ v.visitGOTO(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * GOTO_W - Branch always (to relative offset, not absolute address)
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class GOTO_W extends GotoInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ GOTO_W() {
+ }
+
+
+ public GOTO_W(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.GOTO_W, target);
+ length = 5;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ index = getTargetOffset();
+ out.writeByte(opcode);
+ out.writeInt(index);
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ index = bytes.readInt();
+ length = 5;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitUnconditionalBranch(this);
+ v.visitBranchInstruction(this);
+ v.visitGotoInstruction(this);
+ v.visitGOTO_W(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Super class for GOTO
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class GotoInstruction extends BranchInstruction implements UnconditionalBranch {
+
+ GotoInstruction(short opcode, InstructionHandle target) {
+ super(opcode, target);
+ }
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ GotoInstruction() {
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2B - Convert int to byte
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2B extends ConversionInstruction {
+
+ /** Convert int to byte
+ */
+ public I2B() {
+ super(org.apache.tomcat.util.bcel.Constants.I2B);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2B(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2C - Convert int to char
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2C extends ConversionInstruction {
+
+ /** Convert int to char
+ */
+ public I2C() {
+ super(org.apache.tomcat.util.bcel.Constants.I2C);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2C(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2D - Convert int to double
+ * <PRE>Stack: ..., value -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2D extends ConversionInstruction {
+
+ /** Convert int to double
+ */
+ public I2D() {
+ super(org.apache.tomcat.util.bcel.Constants.I2D);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2D(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2F - Convert int to float
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2F extends ConversionInstruction {
+
+ /** Convert int to float
+ */
+ public I2F() {
+ super(org.apache.tomcat.util.bcel.Constants.I2F);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2F(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2L - Convert int to long
+ * <PRE>Stack: ..., value -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2L extends ConversionInstruction {
+
+ /** Convert int to long
+ */
+ public I2L() {
+ super(org.apache.tomcat.util.bcel.Constants.I2L);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2L(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * I2S - Convert int to short
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class I2S extends ConversionInstruction {
+
+ public I2S() {
+ super(org.apache.tomcat.util.bcel.Constants.I2S);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitI2S(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IADD - Add ints
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IADD extends ArithmeticInstruction {
+
+ /** Add ints
+ */
+ public IADD() {
+ super(org.apache.tomcat.util.bcel.Constants.IADD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIADD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IALOAD - Load int from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IALOAD extends ArrayInstruction implements StackProducer {
+
+ /**
+ * Load int from array
+ */
+ public IALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.IALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitIALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IAND - Bitwise AND int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IAND extends ArithmeticInstruction {
+
+ public IAND() {
+ super(org.apache.tomcat.util.bcel.Constants.IAND);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIAND(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IASTORE - Store into int array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IASTORE extends ArrayInstruction implements StackConsumer {
+
+ /**
+ * Store into int array
+ */
+ public IASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.IASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitIASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ICONST - Push value between -1, ..., 5, other values cause an exception
+ *
+ * <PRE>Stack: ... -> ..., </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ICONST extends Instruction implements ConstantPushInstruction, TypedInstruction {
+
+ private int value;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ICONST() {
+ }
+
+
+ public ICONST(int i) {
+ super(org.apache.tomcat.util.bcel.Constants.ICONST_0, (short) 1);
+ if ((i >= -1) && (i <= 5)) {
+ opcode = (short) (org.apache.tomcat.util.bcel.Constants.ICONST_0 + i); // Even works for i == -1
+ } else {
+ throw new ClassGenException("ICONST can be used only for value between -1 and 5: " + i);
+ }
+ value = i;
+ }
+
+
+ public Number getValue() {
+ return new Integer(value);
+ }
+
+
+ /** @return Type.INT
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.INT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitICONST(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IDIV - Divide ints
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IDIV extends ArithmeticInstruction implements ExceptionThrower {
+
+ /** Divide ints
+ */
+ public IDIV() {
+ super(org.apache.tomcat.util.bcel.Constants.IDIV);
+ }
+
+
+ /** @return exceptions this instruction may cause
+ */
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIDIV(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFEQ - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFEQ extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFEQ() {
+ }
+
+
+ public IFEQ(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFEQ, target);
+ }
+
+
+ /**
+ * @return negation of instruction, e.g. IFEQ.negate() == IFNE
+ */
+ public IfInstruction negate() {
+ return new IFNE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFEQ(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFGE - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFGE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFGE() {
+ }
+
+
+ public IFGE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFGE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFLT(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFGE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFGT - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFGT extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFGT() {
+ }
+
+
+ public IFGT(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFGT, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFLE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFGT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFLE - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFLE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFLE() {
+ }
+
+
+ public IFLE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFLE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFGT(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFLE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFLT - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFLT extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFLT() {
+ }
+
+
+ public IFLT(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFLT, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFGE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFLT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFNE - Branch if int comparison with zero succeeds
+ *
+ * <PRE>Stack: ..., value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFNE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFNE() {
+ }
+
+
+ public IFNE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFNE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFEQ(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFNE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFNONNULL - Branch if reference is not null
+ *
+ * <PRE>Stack: ..., reference -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFNONNULL extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFNONNULL() {
+ }
+
+
+ public IFNONNULL(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFNONNULL, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFNULL(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFNONNULL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IFNULL - Branch if reference is not null
+ *
+ * <PRE>Stack: ..., reference -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IFNULL extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IFNULL() {
+ }
+
+
+ public IFNULL(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IFNULL, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IFNONNULL(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIFNULL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ACMPEQ - Branch if reference comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ACMPEQ extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ACMPEQ() {
+ }
+
+
+ public IF_ACMPEQ(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ACMPEQ, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ACMPNE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ACMPEQ(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ACMPNE - Branch if reference comparison doesn't succeed
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ACMPNE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ACMPNE() {
+ }
+
+
+ public IF_ACMPNE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ACMPNE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ACMPEQ(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ACMPNE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPEQ - Branch if int comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPEQ extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPEQ() {
+ }
+
+
+ public IF_ICMPEQ(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPEQ, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPNE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPEQ(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPGE - Branch if int comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPGE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPGE() {
+ }
+
+
+ public IF_ICMPGE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPGE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPLT(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPGE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPGT - Branch if int comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPGT extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPGT() {
+ }
+
+
+ public IF_ICMPGT(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPGT, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPLE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPGT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPLE - Branch if int comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPLE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPLE() {
+ }
+
+
+ public IF_ICMPLE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPLE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPGT(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPLE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPLT - Branch if int comparison succeeds
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPLT extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPLT() {
+ }
+
+
+ public IF_ICMPLT(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPLT, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPGE(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPLT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IF_ICMPNE - Branch if int comparison doesn't succeed
+ *
+ * <PRE>Stack: ..., value1, value2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IF_ICMPNE extends IfInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IF_ICMPNE() {
+ }
+
+
+ public IF_ICMPNE(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.IF_ICMPNE, target);
+ }
+
+
+ /**
+ * @return negation of instruction
+ */
+ public IfInstruction negate() {
+ return new IF_ICMPEQ(target);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitBranchInstruction(this);
+ v.visitIfInstruction(this);
+ v.visitIF_ICMPNE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * IINC - Increment local variable by constant
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IINC extends LocalVariableInstruction {
+
+ private boolean wide;
+ private int c;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IINC() {
+ }
+
+
+ /**
+ * @param n index of local variable
+ * @param c increment factor
+ */
+ public IINC(int n, int c) {
+ super(); // Default behaviour of LocalVariableInstruction causes error
+ this.opcode = org.apache.tomcat.util.bcel.Constants.IINC;
+ this.length = (short) 3;
+ setIndex(n); // May set wide as side effect
+ setIncrement(c);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ if (wide) {
+ out.writeByte(org.apache.tomcat.util.bcel.Constants.WIDE);
+ }
+ out.writeByte(opcode);
+ if (wide) {
+ out.writeShort(n);
+ out.writeShort(c);
+ } else {
+ out.writeByte(n);
+ out.writeByte(c);
+ }
+ }
+
+
+ private final void setWide() {
+ wide = (n > org.apache.tomcat.util.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE);
+ if (wide) {
+ length = 6; // wide byte included
+ } else {
+ length = 3;
+ }
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ this.wide = wide;
+ if (wide) {
+ length = 6;
+ n = bytes.readUnsignedShort();
+ c = bytes.readShort();
+ } else {
+ length = 3;
+ n = bytes.readUnsignedByte();
+ c = bytes.readByte();
+ }
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + c;
+ }
+
+
+ /**
+ * Set index of local variable.
+ */
+ public final void setIndex( int n ) {
+ if (n < 0) {
+ throw new ClassGenException("Negative index value: " + n);
+ }
+ this.n = n;
+ setWide();
+ }
+
+
+ /**
+ * @return increment factor
+ */
+ public final int getIncrement() {
+ return c;
+ }
+
+
+ /**
+ * Set increment factor.
+ */
+ public final void setIncrement( int c ) {
+ this.c = c;
+ setWide();
+ }
+
+
+ /** @return int type
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.INT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLocalVariableInstruction(this);
+ v.visitIINC(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ILOAD - Load int from local variable onto stack
+ * <PRE>Stack: ... -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ILOAD extends LoadInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ILOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.ILOAD, org.apache.tomcat.util.bcel.Constants.ILOAD_0);
+ }
+
+
+ /** Load int from local variable
+ * @param n index of local variable
+ */
+ public ILOAD(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.ILOAD, org.apache.tomcat.util.bcel.Constants.ILOAD_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitILOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IMPDEP1 - Implementation dependent
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IMPDEP1 extends Instruction {
+
+ public IMPDEP1() {
+ super(org.apache.tomcat.util.bcel.Constants.IMPDEP1, (short) 1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitIMPDEP1(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IMPDEP2 - Implementation dependent
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IMPDEP2 extends Instruction {
+
+ public IMPDEP2() {
+ super(org.apache.tomcat.util.bcel.Constants.IMPDEP2, (short) 1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitIMPDEP2(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IMUL - Multiply ints
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IMUL extends ArithmeticInstruction {
+
+ /** Multiply ints
+ */
+ public IMUL() {
+ super(org.apache.tomcat.util.bcel.Constants.IMUL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIMUL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * INEG - Negate int
+ * <PRE>Stack: ..., value -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class INEG extends ArithmeticInstruction {
+
+ public INEG() {
+ super(org.apache.tomcat.util.bcel.Constants.INEG);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitINEG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * INSTANCEOF - Determine if object is of given type
+ * <PRE>Stack: ..., objectref -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class INSTANCEOF extends CPInstruction implements LoadClass, ExceptionThrower,
+ StackProducer, StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ INSTANCEOF() {
+ }
+
+
+ public INSTANCEOF(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.INSTANCEOF, index);
+ }
+
+
+ public Class[] getExceptions() {
+ return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION;
+ }
+
+
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ Type t = getType(cpg);
+ if (t instanceof ArrayType) {
+ t = ((ArrayType) t).getBasicType();
+ }
+ return (t instanceof ObjectType) ? (ObjectType) t : null;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLoadClass(this);
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitINSTANCEOF(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * INVOKEINTERFACE - Invoke interface method
+ * <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class INVOKEINTERFACE extends InvokeInstruction {
+
+ private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ INVOKEINTERFACE() {
+ }
+
+
+ public INVOKEINTERFACE(int index, int nargs) {
+ super(Constants.INVOKEINTERFACE, index);
+ length = 5;
+ if (nargs < 1) {
+ throw new ClassGenException("Number of arguments must be > 0 " + nargs);
+ }
+ this.nargs = nargs;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ out.writeShort(index);
+ out.writeByte(nargs);
+ out.writeByte(0);
+ }
+
+
+ /**
+ * The <B>count</B> argument according to the Java Language Specification,
+ * Second Edition.
+ */
+ public int getCount() {
+ return nargs;
+ }
+
+
+ /**
+ * Read needed data (i.e., index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ super.initFromFile(bytes, wide);
+ length = 5;
+ nargs = bytes.readUnsignedByte();
+ bytes.readByte(); // Skip 0 byte
+ }
+
+
+ /**
+ * @return mnemonic for instruction with symbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ return super.toString(cp) + " " + nargs;
+ }
+
+
+ public int consumeStack( ConstantPoolGen cpg ) { // nargs is given in byte-code
+ return nargs; // nargs includes this reference
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[4 + ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 3] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
+ cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 1] = ExceptionConstants.ABSTRACT_METHOD_ERROR;
+ cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length] = ExceptionConstants.UNSATISFIED_LINK_ERROR;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitInvokeInstruction(this);
+ v.visitINVOKEINTERFACE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * INVOKESPECIAL - Invoke instance method; special handling for superclass, private
+ * and instance initialization method invocations
+ *
+ * <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class INVOKESPECIAL extends InvokeInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ INVOKESPECIAL() {
+ }
+
+
+ public INVOKESPECIAL(int index) {
+ super(Constants.INVOKESPECIAL, index);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[4 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 3] = ExceptionConstants.UNSATISFIED_LINK_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ABSTRACT_METHOD_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitInvokeInstruction(this);
+ v.visitINVOKESPECIAL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * INVOKESTATIC - Invoke a class (static) method
+ *
+ * <PRE>Stack: ..., [arg1, [arg2 ...]] -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class INVOKESTATIC extends InvokeInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ INVOKESTATIC() {
+ }
+
+
+ public INVOKESTATIC(int index) {
+ super(Constants.INVOKESTATIC, index);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.UNSATISFIED_LINK_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitInvokeInstruction(this);
+ v.visitINVOKESTATIC(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * INVOKEVIRTUAL - Invoke instance method; dispatch based on class
+ *
+ * <PRE>Stack: ..., objectref, [arg1, [arg2 ...]] -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class INVOKEVIRTUAL extends InvokeInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ INVOKEVIRTUAL() {
+ }
+
+
+ public INVOKEVIRTUAL(int index) {
+ super(Constants.INVOKEVIRTUAL, index);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[4 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 3] = ExceptionConstants.UNSATISFIED_LINK_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ABSTRACT_METHOD_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitInvokeInstruction(this);
+ v.visitINVOKEVIRTUAL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IOR - Bitwise OR int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IOR extends ArithmeticInstruction {
+
+ public IOR() {
+ super(org.apache.tomcat.util.bcel.Constants.IOR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIOR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IREM - Remainder of int
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IREM extends ArithmeticInstruction implements ExceptionThrower {
+
+ /** Remainder of ints
+ */
+ public IREM() {
+ super(org.apache.tomcat.util.bcel.Constants.IREM);
+ }
+
+
+ /** @return exceptions this instruction may cause
+ */
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIREM(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IRETURN - Return int from method
+ * <PRE>Stack: ..., value -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IRETURN extends ReturnInstruction {
+
+ /** Return int from method
+ */
+ public IRETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.IRETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitIRETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ISHL - Arithmetic shift left int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ISHL extends ArithmeticInstruction {
+
+ public ISHL() {
+ super(org.apache.tomcat.util.bcel.Constants.ISHL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitISHL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ISHR - Arithmetic shift right int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ISHR extends ArithmeticInstruction {
+
+ public ISHR() {
+ super(org.apache.tomcat.util.bcel.Constants.ISHR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitISHR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ISTORE - Store int from stack into local variable
+ * <PRE>Stack: ..., value -> ... </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ISTORE extends StoreInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ISTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.ISTORE, org.apache.tomcat.util.bcel.Constants.ISTORE_0);
+ }
+
+
+ /** Store int into local variable
+ * @param n index of local variable
+ */
+ public ISTORE(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.ISTORE, org.apache.tomcat.util.bcel.Constants.ISTORE_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitISTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * ISUB - Substract ints
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ISUB extends ArithmeticInstruction {
+
+ /** Substract ints
+ */
+ public ISUB() {
+ super(org.apache.tomcat.util.bcel.Constants.ISUB);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitISUB(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IUSHR - Logical shift right int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IUSHR extends ArithmeticInstruction {
+
+ public IUSHR() {
+ super(org.apache.tomcat.util.bcel.Constants.IUSHR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIUSHR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * IXOR - Bitwise XOR int
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class IXOR extends ArithmeticInstruction {
+
+ public IXOR() {
+ super(org.apache.tomcat.util.bcel.Constants.IXOR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitIXOR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Super class for the IFxxx family of instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class IfInstruction extends BranchInstruction implements StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ IfInstruction() {
+ }
+
+
+ /**
+ * @param opcode opcode of instruction
+ * @param target Target instruction to branch to
+ */
+ protected IfInstruction(short opcode, InstructionHandle target) {
+ super(opcode, target);
+ }
+
+
+ /**
+ * @return negation of instruction, e.g. IFEQ.negate() == IFNE
+ */
+ public abstract IfInstruction negate();
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote entity that refers to an index, e.g. local variable instructions,
+ * RET, CPInstruction, etc.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface IndexedInstruction {
+
+ public int getIndex();
+
+
+ public void setIndex( int index );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Locale;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Abstract super class for all Java byte codes.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class Instruction implements Cloneable, Serializable {
+
+ protected short length = 1; // Length of instruction in bytes
+ protected short opcode = -1; // Opcode number
+ private static InstructionComparator cmp = InstructionComparator.DEFAULT;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ Instruction() {
+ }
+
+
+ public Instruction(short opcode, short length) {
+ this.length = length;
+ this.opcode = opcode;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode); // Common for all instructions
+ }
+
+
+ /** @return name of instruction, i.e., opcode name
+ */
+ public String getName() {
+ return Constants.OPCODE_NAMES[opcode];
+ }
+
+
+ /**
+ * Long output format:
+ *
+ * <name of opcode> "["<opcode number>"]"
+ * "("<length of instruction>")"
+ *
+ * @param verbose long/short format switch
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ if (verbose) {
+ return getName() + "[" + opcode + "](" + length + ")";
+ } else {
+ return getName();
+ }
+ }
+
+
+ /**
+ * @return mnemonic for instruction in verbose format
+ */
+ public String toString() {
+ return toString(true);
+ }
+
+
+ /**
+ * @return mnemonic for instruction with sumbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ return toString(false);
+ }
+
+
+ /**
+ * Use with caution, since `BranchInstruction's have a `target' reference which
+ * is not copied correctly (only basic types are). This also applies for
+ * `Select' instructions with their multiple branch targets.
+ *
+ * @see BranchInstruction
+ * @return (shallow) copy of an instruction
+ */
+ public Instruction copy() {
+ Instruction i = null;
+ // "Constant" instruction, no need to duplicate
+ if (InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null) {
+ i = this;
+ } else {
+ try {
+ i = (Instruction) clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ }
+ }
+ return i;
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ *
+ * @param bytes byte sequence to read from
+ * @param wide "wide" instruction flag
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ }
+
+
+ /**
+ * Read an instruction from (byte code) input stream and return the
+ * appropiate object.
+ *
+ * @param bytes input stream bytes
+ * @return instruction object being read
+ */
+ public static final Instruction readInstruction( ByteSequence bytes ) throws IOException {
+ boolean wide = false;
+ short opcode = (short) bytes.readUnsignedByte();
+ Instruction obj = null;
+ if (opcode == Constants.WIDE) { // Read next opcode after wide byte
+ wide = true;
+ opcode = (short) bytes.readUnsignedByte();
+ }
+ if (InstructionConstants.INSTRUCTIONS[opcode] != null) {
+ return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available
+ }
+
+ switch (opcode) {
+ case Constants.BIPUSH:
+ obj = new BIPUSH();
+ break;
+ case Constants.SIPUSH:
+ obj = new SIPUSH();
+ break;
+ case Constants.LDC:
+ obj = new LDC();
+ break;
+ case Constants.LDC_W:
+ obj = new LDC_W();
+ break;
+ case Constants.LDC2_W:
+ obj = new LDC2_W();
+ break;
+ case Constants.ILOAD:
+ obj = new ILOAD();
+ break;
+ case Constants.LLOAD:
+ obj = new LLOAD();
+ break;
+ case Constants.FLOAD:
+ obj = new FLOAD();
+ break;
+ case Constants.DLOAD:
+ obj = new DLOAD();
+ break;
+ case Constants.ALOAD:
+ obj = new ALOAD();
+ break;
+ case Constants.ILOAD_0:
+ obj = new ILOAD(0);
+ break;
+ case Constants.ILOAD_1:
+ obj = new ILOAD(1);
+ break;
+ case Constants.ILOAD_2:
+ obj = new ILOAD(2);
+ break;
+ case Constants.ILOAD_3:
+ obj = new ILOAD(3);
+ break;
+ case Constants.LLOAD_0:
+ obj = new LLOAD(0);
+ break;
+ case Constants.LLOAD_1:
+ obj = new LLOAD(1);
+ break;
+ case Constants.LLOAD_2:
+ obj = new LLOAD(2);
+ break;
+ case Constants.LLOAD_3:
+ obj = new LLOAD(3);
+ break;
+ case Constants.FLOAD_0:
+ obj = new FLOAD(0);
+ break;
+ case Constants.FLOAD_1:
+ obj = new FLOAD(1);
+ break;
+ case Constants.FLOAD_2:
+ obj = new FLOAD(2);
+ break;
+ case Constants.FLOAD_3:
+ obj = new FLOAD(3);
+ break;
+ case Constants.DLOAD_0:
+ obj = new DLOAD(0);
+ break;
+ case Constants.DLOAD_1:
+ obj = new DLOAD(1);
+ break;
+ case Constants.DLOAD_2:
+ obj = new DLOAD(2);
+ break;
+ case Constants.DLOAD_3:
+ obj = new DLOAD(3);
+ break;
+ case Constants.ALOAD_0:
+ obj = new ALOAD(0);
+ break;
+ case Constants.ALOAD_1:
+ obj = new ALOAD(1);
+ break;
+ case Constants.ALOAD_2:
+ obj = new ALOAD(2);
+ break;
+ case Constants.ALOAD_3:
+ obj = new ALOAD(3);
+ break;
+ case Constants.ISTORE:
+ obj = new ISTORE();
+ break;
+ case Constants.LSTORE:
+ obj = new LSTORE();
+ break;
+ case Constants.FSTORE:
+ obj = new FSTORE();
+ break;
+ case Constants.DSTORE:
+ obj = new DSTORE();
+ break;
+ case Constants.ASTORE:
+ obj = new ASTORE();
+ break;
+ case Constants.ISTORE_0:
+ obj = new ISTORE(0);
+ break;
+ case Constants.ISTORE_1:
+ obj = new ISTORE(1);
+ break;
+ case Constants.ISTORE_2:
+ obj = new ISTORE(2);
+ break;
+ case Constants.ISTORE_3:
+ obj = new ISTORE(3);
+ break;
+ case Constants.LSTORE_0:
+ obj = new LSTORE(0);
+ break;
+ case Constants.LSTORE_1:
+ obj = new LSTORE(1);
+ break;
+ case Constants.LSTORE_2:
+ obj = new LSTORE(2);
+ break;
+ case Constants.LSTORE_3:
+ obj = new LSTORE(3);
+ break;
+ case Constants.FSTORE_0:
+ obj = new FSTORE(0);
+ break;
+ case Constants.FSTORE_1:
+ obj = new FSTORE(1);
+ break;
+ case Constants.FSTORE_2:
+ obj = new FSTORE(2);
+ break;
+ case Constants.FSTORE_3:
+ obj = new FSTORE(3);
+ break;
+ case Constants.DSTORE_0:
+ obj = new DSTORE(0);
+ break;
+ case Constants.DSTORE_1:
+ obj = new DSTORE(1);
+ break;
+ case Constants.DSTORE_2:
+ obj = new DSTORE(2);
+ break;
+ case Constants.DSTORE_3:
+ obj = new DSTORE(3);
+ break;
+ case Constants.ASTORE_0:
+ obj = new ASTORE(0);
+ break;
+ case Constants.ASTORE_1:
+ obj = new ASTORE(1);
+ break;
+ case Constants.ASTORE_2:
+ obj = new ASTORE(2);
+ break;
+ case Constants.ASTORE_3:
+ obj = new ASTORE(3);
+ break;
+ case Constants.IINC:
+ obj = new IINC();
+ break;
+ case Constants.IFEQ:
+ obj = new IFEQ();
+ break;
+ case Constants.IFNE:
+ obj = new IFNE();
+ break;
+ case Constants.IFLT:
+ obj = new IFLT();
+ break;
+ case Constants.IFGE:
+ obj = new IFGE();
+ break;
+ case Constants.IFGT:
+ obj = new IFGT();
+ break;
+ case Constants.IFLE:
+ obj = new IFLE();
+ break;
+ case Constants.IF_ICMPEQ:
+ obj = new IF_ICMPEQ();
+ break;
+ case Constants.IF_ICMPNE:
+ obj = new IF_ICMPNE();
+ break;
+ case Constants.IF_ICMPLT:
+ obj = new IF_ICMPLT();
+ break;
+ case Constants.IF_ICMPGE:
+ obj = new IF_ICMPGE();
+ break;
+ case Constants.IF_ICMPGT:
+ obj = new IF_ICMPGT();
+ break;
+ case Constants.IF_ICMPLE:
+ obj = new IF_ICMPLE();
+ break;
+ case Constants.IF_ACMPEQ:
+ obj = new IF_ACMPEQ();
+ break;
+ case Constants.IF_ACMPNE:
+ obj = new IF_ACMPNE();
+ break;
+ case Constants.GOTO:
+ obj = new GOTO();
+ break;
+ case Constants.JSR:
+ obj = new JSR();
+ break;
+ case Constants.RET:
+ obj = new RET();
+ break;
+ case Constants.TABLESWITCH:
+ obj = new TABLESWITCH();
+ break;
+ case Constants.LOOKUPSWITCH:
+ obj = new LOOKUPSWITCH();
+ break;
+ case Constants.GETSTATIC:
+ obj = new GETSTATIC();
+ break;
+ case Constants.PUTSTATIC:
+ obj = new PUTSTATIC();
+ break;
+ case Constants.GETFIELD:
+ obj = new GETFIELD();
+ break;
+ case Constants.PUTFIELD:
+ obj = new PUTFIELD();
+ break;
+ case Constants.INVOKEVIRTUAL:
+ obj = new INVOKEVIRTUAL();
+ break;
+ case Constants.INVOKESPECIAL:
+ obj = new INVOKESPECIAL();
+ break;
+ case Constants.INVOKESTATIC:
+ obj = new INVOKESTATIC();
+ break;
+ case Constants.INVOKEINTERFACE:
+ obj = new INVOKEINTERFACE();
+ break;
+ case Constants.NEW:
+ obj = new NEW();
+ break;
+ case Constants.NEWARRAY:
+ obj = new NEWARRAY();
+ break;
+ case Constants.ANEWARRAY:
+ obj = new ANEWARRAY();
+ break;
+ case Constants.CHECKCAST:
+ obj = new CHECKCAST();
+ break;
+ case Constants.INSTANCEOF:
+ obj = new INSTANCEOF();
+ break;
+ case Constants.MULTIANEWARRAY:
+ obj = new MULTIANEWARRAY();
+ break;
+ case Constants.IFNULL:
+ obj = new IFNULL();
+ break;
+ case Constants.IFNONNULL:
+ obj = new IFNONNULL();
+ break;
+ case Constants.GOTO_W:
+ obj = new GOTO_W();
+ break;
+ case Constants.JSR_W:
+ obj = new JSR_W();
+ break;
+ case Constants.BREAKPOINT:
+ obj = new BREAKPOINT();
+ break;
+ case Constants.IMPDEP1:
+ obj = new IMPDEP1();
+ break;
+ case Constants.IMPDEP2:
+ obj = new IMPDEP2();
+ break;
+ default:
+ throw new ClassGenException("Illegal opcode detected: " + opcode);
+
+ }
+
+ if (wide
+ && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) {
+ throw new ClassGenException("Illegal opcode after wide: " + opcode);
+ }
+ obj.setOpcode(opcode);
+ obj.initFromFile(bytes, wide); // Do further initializations, if any
+ return obj;
+ }
+
+ /**
+ * This method also gives right results for instructions whose
+ * effect on the stack depends on the constant pool entry they
+ * reference.
+ * @return Number of words consumed from stack by this instruction,
+ * or Constants.UNPREDICTABLE, if this can not be computed statically
+ */
+ public int consumeStack( ConstantPoolGen cpg ) {
+ return Constants.CONSUME_STACK[opcode];
+ }
+
+
+ /**
+ * This method also gives right results for instructions whose
+ * effect on the stack depends on the constant pool entry they
+ * reference.
+ * @return Number of words produced onto stack by this instruction,
+ * or Constants.UNPREDICTABLE, if this can not be computed statically
+ */
+ public int produceStack( ConstantPoolGen cpg ) {
+ return Constants.PRODUCE_STACK[opcode];
+ }
+
+
+ /**
+ * @return this instructions opcode
+ */
+ public short getOpcode() {
+ return opcode;
+ }
+
+
+ /**
+ * @return length (in bytes) of instruction
+ */
+ public int getLength() {
+ return length;
+ }
+
+
+ /**
+ * Needed in readInstruction.
+ */
+ private void setOpcode( short opcode ) {
+ this.opcode = opcode;
+ }
+
+
+ /** Some instructions may be reused, so don't do anything by default.
+ */
+ void dispose() {
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public abstract void accept( Visitor v );
+
+
+ /** Get Comparator object used in the equals() method to determine
+ * equality of instructions.
+ *
+ * @return currently used comparator for equals()
+ */
+ public static InstructionComparator getComparator() {
+ return cmp;
+ }
+
+
+ /** Set comparator to be used for equals().
+ */
+ public static void setComparator( InstructionComparator c ) {
+ cmp = c;
+ }
+
+
+ /** Check for equality, delegated to comparator
+ * @return true if that is an Instruction and has the same opcode
+ */
+ public boolean equals( Object that ) {
+ return (that instanceof Instruction) ? cmp.equals(this, (Instruction) that) : false;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Equality of instructions isn't clearly to be defined. You might
+ * wish, for example, to compare whether instructions have the same
+ * meaning. E.g., whether two INVOKEVIRTUALs describe the same
+ * call.<br>The DEFAULT comparator however, considers two instructions
+ * to be equal if they have same opcode and point to the same indexes
+ * (if any) in the constant pool or the same local variable index. Branch
+ * instructions must have the same target.
+ *
+ * @see Instruction
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface InstructionComparator {
+
+ public static final InstructionComparator DEFAULT = new InstructionComparator() {
+
+ public boolean equals( Instruction i1, Instruction i2 ) {
+ if (i1.opcode == i2.opcode) {
+ if (i1 instanceof Select) {
+ InstructionHandle[] t1 = ((Select) i1).getTargets();
+ InstructionHandle[] t2 = ((Select) i2).getTargets();
+ if (t1.length == t2.length) {
+ for (int i = 0; i < t1.length; i++) {
+ if (t1[i] != t2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ } else if (i1 instanceof BranchInstruction) {
+ return ((BranchInstruction) i1).target == ((BranchInstruction) i2).target;
+ } else if (i1 instanceof ConstantPushInstruction) {
+ return ((ConstantPushInstruction) i1).getValue().equals(
+ ((ConstantPushInstruction) i2).getValue());
+ } else if (i1 instanceof IndexedInstruction) {
+ return ((IndexedInstruction) i1).getIndex() == ((IndexedInstruction) i2)
+ .getIndex();
+ } else if (i1 instanceof NEWARRAY) {
+ return ((NEWARRAY) i1).getTypecode() == ((NEWARRAY) i2).getTypecode();
+ } else {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+
+
+ public boolean equals( Instruction i1, Instruction i2 );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * This interface contains shareable instruction objects.
+ *
+ * In order to save memory you can use some instructions multiply,
+ * since they have an immutable state and are directly derived from
+ * Instruction. I.e. they have no instance fields that could be
+ * changed. Since some of these instructions like ICONST_0 occur
+ * very frequently this can save a lot of time and space. This
+ * feature is an adaptation of the FlyWeight design pattern, we
+ * just use an array instead of a factory.
+ *
+ * The Instructions can also accessed directly under their names, so
+ * it's possible to write il.append(Instruction.ICONST_0);
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface InstructionConstants {
+
+ /** Predefined instruction objects
+ */
+ public static final Instruction NOP = new NOP();
+ public static final Instruction ACONST_NULL = new ACONST_NULL();
+ public static final Instruction ICONST_M1 = new ICONST(-1);
+ public static final Instruction ICONST_0 = new ICONST(0);
+ public static final Instruction ICONST_1 = new ICONST(1);
+ public static final Instruction ICONST_2 = new ICONST(2);
+ public static final Instruction ICONST_3 = new ICONST(3);
+ public static final Instruction ICONST_4 = new ICONST(4);
+ public static final Instruction ICONST_5 = new ICONST(5);
+ public static final Instruction LCONST_0 = new LCONST(0);
+ public static final Instruction LCONST_1 = new LCONST(1);
+ public static final Instruction FCONST_0 = new FCONST(0);
+ public static final Instruction FCONST_1 = new FCONST(1);
+ public static final Instruction FCONST_2 = new FCONST(2);
+ public static final Instruction DCONST_0 = new DCONST(0);
+ public static final Instruction DCONST_1 = new DCONST(1);
+ public static final ArrayInstruction IALOAD = new IALOAD();
+ public static final ArrayInstruction LALOAD = new LALOAD();
+ public static final ArrayInstruction FALOAD = new FALOAD();
+ public static final ArrayInstruction DALOAD = new DALOAD();
+ public static final ArrayInstruction AALOAD = new AALOAD();
+ public static final ArrayInstruction BALOAD = new BALOAD();
+ public static final ArrayInstruction CALOAD = new CALOAD();
+ public static final ArrayInstruction SALOAD = new SALOAD();
+ public static final ArrayInstruction IASTORE = new IASTORE();
+ public static final ArrayInstruction LASTORE = new LASTORE();
+ public static final ArrayInstruction FASTORE = new FASTORE();
+ public static final ArrayInstruction DASTORE = new DASTORE();
+ public static final ArrayInstruction AASTORE = new AASTORE();
+ public static final ArrayInstruction BASTORE = new BASTORE();
+ public static final ArrayInstruction CASTORE = new CASTORE();
+ public static final ArrayInstruction SASTORE = new SASTORE();
+ public static final StackInstruction POP = new POP();
+ public static final StackInstruction POP2 = new POP2();
+ public static final StackInstruction DUP = new DUP();
+ public static final StackInstruction DUP_X1 = new DUP_X1();
+ public static final StackInstruction DUP_X2 = new DUP_X2();
+ public static final StackInstruction DUP2 = new DUP2();
+ public static final StackInstruction DUP2_X1 = new DUP2_X1();
+ public static final StackInstruction DUP2_X2 = new DUP2_X2();
+ public static final StackInstruction SWAP = new SWAP();
+ public static final ArithmeticInstruction IADD = new IADD();
+ public static final ArithmeticInstruction LADD = new LADD();
+ public static final ArithmeticInstruction FADD = new FADD();
+ public static final ArithmeticInstruction DADD = new DADD();
+ public static final ArithmeticInstruction ISUB = new ISUB();
+ public static final ArithmeticInstruction LSUB = new LSUB();
+ public static final ArithmeticInstruction FSUB = new FSUB();
+ public static final ArithmeticInstruction DSUB = new DSUB();
+ public static final ArithmeticInstruction IMUL = new IMUL();
+ public static final ArithmeticInstruction LMUL = new LMUL();
+ public static final ArithmeticInstruction FMUL = new FMUL();
+ public static final ArithmeticInstruction DMUL = new DMUL();
+ public static final ArithmeticInstruction IDIV = new IDIV();
+ public static final ArithmeticInstruction LDIV = new LDIV();
+ public static final ArithmeticInstruction FDIV = new FDIV();
+ public static final ArithmeticInstruction DDIV = new DDIV();
+ public static final ArithmeticInstruction IREM = new IREM();
+ public static final ArithmeticInstruction LREM = new LREM();
+ public static final ArithmeticInstruction FREM = new FREM();
+ public static final ArithmeticInstruction DREM = new DREM();
+ public static final ArithmeticInstruction INEG = new INEG();
+ public static final ArithmeticInstruction LNEG = new LNEG();
+ public static final ArithmeticInstruction FNEG = new FNEG();
+ public static final ArithmeticInstruction DNEG = new DNEG();
+ public static final ArithmeticInstruction ISHL = new ISHL();
+ public static final ArithmeticInstruction LSHL = new LSHL();
+ public static final ArithmeticInstruction ISHR = new ISHR();
+ public static final ArithmeticInstruction LSHR = new LSHR();
+ public static final ArithmeticInstruction IUSHR = new IUSHR();
+ public static final ArithmeticInstruction LUSHR = new LUSHR();
+ public static final ArithmeticInstruction IAND = new IAND();
+ public static final ArithmeticInstruction LAND = new LAND();
+ public static final ArithmeticInstruction IOR = new IOR();
+ public static final ArithmeticInstruction LOR = new LOR();
+ public static final ArithmeticInstruction IXOR = new IXOR();
+ public static final ArithmeticInstruction LXOR = new LXOR();
+ public static final ConversionInstruction I2L = new I2L();
+ public static final ConversionInstruction I2F = new I2F();
+ public static final ConversionInstruction I2D = new I2D();
+ public static final ConversionInstruction L2I = new L2I();
+ public static final ConversionInstruction L2F = new L2F();
+ public static final ConversionInstruction L2D = new L2D();
+ public static final ConversionInstruction F2I = new F2I();
+ public static final ConversionInstruction F2L = new F2L();
+ public static final ConversionInstruction F2D = new F2D();
+ public static final ConversionInstruction D2I = new D2I();
+ public static final ConversionInstruction D2L = new D2L();
+ public static final ConversionInstruction D2F = new D2F();
+ public static final ConversionInstruction I2B = new I2B();
+ public static final ConversionInstruction I2C = new I2C();
+ public static final ConversionInstruction I2S = new I2S();
+ public static final Instruction LCMP = new LCMP();
+ public static final Instruction FCMPL = new FCMPL();
+ public static final Instruction FCMPG = new FCMPG();
+ public static final Instruction DCMPL = new DCMPL();
+ public static final Instruction DCMPG = new DCMPG();
+ public static final ReturnInstruction IRETURN = new IRETURN();
+ public static final ReturnInstruction LRETURN = new LRETURN();
+ public static final ReturnInstruction FRETURN = new FRETURN();
+ public static final ReturnInstruction DRETURN = new DRETURN();
+ public static final ReturnInstruction ARETURN = new ARETURN();
+ public static final ReturnInstruction RETURN = new RETURN();
+ public static final Instruction ARRAYLENGTH = new ARRAYLENGTH();
+ public static final Instruction ATHROW = new ATHROW();
+ public static final Instruction MONITORENTER = new MONITORENTER();
+ public static final Instruction MONITOREXIT = new MONITOREXIT();
+ /** You can use these constants in multiple places safely, if you can guarantee
+ * that you will never alter their internal values, e.g. call setIndex().
+ */
+ public static final LocalVariableInstruction THIS = new ALOAD(0);
+ public static final LocalVariableInstruction ALOAD_0 = THIS;
+ public static final LocalVariableInstruction ALOAD_1 = new ALOAD(1);
+ public static final LocalVariableInstruction ALOAD_2 = new ALOAD(2);
+ public static final LocalVariableInstruction ILOAD_0 = new ILOAD(0);
+ public static final LocalVariableInstruction ILOAD_1 = new ILOAD(1);
+ public static final LocalVariableInstruction ILOAD_2 = new ILOAD(2);
+ public static final LocalVariableInstruction ASTORE_0 = new ASTORE(0);
+ public static final LocalVariableInstruction ASTORE_1 = new ASTORE(1);
+ public static final LocalVariableInstruction ASTORE_2 = new ASTORE(2);
+ public static final LocalVariableInstruction ISTORE_0 = new ISTORE(0);
+ public static final LocalVariableInstruction ISTORE_1 = new ISTORE(1);
+ public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2);
+ /** Get object via its opcode, for immutable instructions like
+ * branch instructions entries are set to null.
+ */
+ public static final Instruction[] INSTRUCTIONS = new Instruction[256];
+ /** Interfaces may have no static initializers, so we simulate this
+ * with an inner class.
+ */
+ static final Clinit bla = new Clinit();
+
+ static class Clinit {
+
+ Clinit() {
+ INSTRUCTIONS[Constants.NOP] = NOP;
+ INSTRUCTIONS[Constants.ACONST_NULL] = ACONST_NULL;
+ INSTRUCTIONS[Constants.ICONST_M1] = ICONST_M1;
+ INSTRUCTIONS[Constants.ICONST_0] = ICONST_0;
+ INSTRUCTIONS[Constants.ICONST_1] = ICONST_1;
+ INSTRUCTIONS[Constants.ICONST_2] = ICONST_2;
+ INSTRUCTIONS[Constants.ICONST_3] = ICONST_3;
+ INSTRUCTIONS[Constants.ICONST_4] = ICONST_4;
+ INSTRUCTIONS[Constants.ICONST_5] = ICONST_5;
+ INSTRUCTIONS[Constants.LCONST_0] = LCONST_0;
+ INSTRUCTIONS[Constants.LCONST_1] = LCONST_1;
+ INSTRUCTIONS[Constants.FCONST_0] = FCONST_0;
+ INSTRUCTIONS[Constants.FCONST_1] = FCONST_1;
+ INSTRUCTIONS[Constants.FCONST_2] = FCONST_2;
+ INSTRUCTIONS[Constants.DCONST_0] = DCONST_0;
+ INSTRUCTIONS[Constants.DCONST_1] = DCONST_1;
+ INSTRUCTIONS[Constants.IALOAD] = IALOAD;
+ INSTRUCTIONS[Constants.LALOAD] = LALOAD;
+ INSTRUCTIONS[Constants.FALOAD] = FALOAD;
+ INSTRUCTIONS[Constants.DALOAD] = DALOAD;
+ INSTRUCTIONS[Constants.AALOAD] = AALOAD;
+ INSTRUCTIONS[Constants.BALOAD] = BALOAD;
+ INSTRUCTIONS[Constants.CALOAD] = CALOAD;
+ INSTRUCTIONS[Constants.SALOAD] = SALOAD;
+ INSTRUCTIONS[Constants.IASTORE] = IASTORE;
+ INSTRUCTIONS[Constants.LASTORE] = LASTORE;
+ INSTRUCTIONS[Constants.FASTORE] = FASTORE;
+ INSTRUCTIONS[Constants.DASTORE] = DASTORE;
+ INSTRUCTIONS[Constants.AASTORE] = AASTORE;
+ INSTRUCTIONS[Constants.BASTORE] = BASTORE;
+ INSTRUCTIONS[Constants.CASTORE] = CASTORE;
+ INSTRUCTIONS[Constants.SASTORE] = SASTORE;
+ INSTRUCTIONS[Constants.POP] = POP;
+ INSTRUCTIONS[Constants.POP2] = POP2;
+ INSTRUCTIONS[Constants.DUP] = DUP;
+ INSTRUCTIONS[Constants.DUP_X1] = DUP_X1;
+ INSTRUCTIONS[Constants.DUP_X2] = DUP_X2;
+ INSTRUCTIONS[Constants.DUP2] = DUP2;
+ INSTRUCTIONS[Constants.DUP2_X1] = DUP2_X1;
+ INSTRUCTIONS[Constants.DUP2_X2] = DUP2_X2;
+ INSTRUCTIONS[Constants.SWAP] = SWAP;
+ INSTRUCTIONS[Constants.IADD] = IADD;
+ INSTRUCTIONS[Constants.LADD] = LADD;
+ INSTRUCTIONS[Constants.FADD] = FADD;
+ INSTRUCTIONS[Constants.DADD] = DADD;
+ INSTRUCTIONS[Constants.ISUB] = ISUB;
+ INSTRUCTIONS[Constants.LSUB] = LSUB;
+ INSTRUCTIONS[Constants.FSUB] = FSUB;
+ INSTRUCTIONS[Constants.DSUB] = DSUB;
+ INSTRUCTIONS[Constants.IMUL] = IMUL;
+ INSTRUCTIONS[Constants.LMUL] = LMUL;
+ INSTRUCTIONS[Constants.FMUL] = FMUL;
+ INSTRUCTIONS[Constants.DMUL] = DMUL;
+ INSTRUCTIONS[Constants.IDIV] = IDIV;
+ INSTRUCTIONS[Constants.LDIV] = LDIV;
+ INSTRUCTIONS[Constants.FDIV] = FDIV;
+ INSTRUCTIONS[Constants.DDIV] = DDIV;
+ INSTRUCTIONS[Constants.IREM] = IREM;
+ INSTRUCTIONS[Constants.LREM] = LREM;
+ INSTRUCTIONS[Constants.FREM] = FREM;
+ INSTRUCTIONS[Constants.DREM] = DREM;
+ INSTRUCTIONS[Constants.INEG] = INEG;
+ INSTRUCTIONS[Constants.LNEG] = LNEG;
+ INSTRUCTIONS[Constants.FNEG] = FNEG;
+ INSTRUCTIONS[Constants.DNEG] = DNEG;
+ INSTRUCTIONS[Constants.ISHL] = ISHL;
+ INSTRUCTIONS[Constants.LSHL] = LSHL;
+ INSTRUCTIONS[Constants.ISHR] = ISHR;
+ INSTRUCTIONS[Constants.LSHR] = LSHR;
+ INSTRUCTIONS[Constants.IUSHR] = IUSHR;
+ INSTRUCTIONS[Constants.LUSHR] = LUSHR;
+ INSTRUCTIONS[Constants.IAND] = IAND;
+ INSTRUCTIONS[Constants.LAND] = LAND;
+ INSTRUCTIONS[Constants.IOR] = IOR;
+ INSTRUCTIONS[Constants.LOR] = LOR;
+ INSTRUCTIONS[Constants.IXOR] = IXOR;
+ INSTRUCTIONS[Constants.LXOR] = LXOR;
+ INSTRUCTIONS[Constants.I2L] = I2L;
+ INSTRUCTIONS[Constants.I2F] = I2F;
+ INSTRUCTIONS[Constants.I2D] = I2D;
+ INSTRUCTIONS[Constants.L2I] = L2I;
+ INSTRUCTIONS[Constants.L2F] = L2F;
+ INSTRUCTIONS[Constants.L2D] = L2D;
+ INSTRUCTIONS[Constants.F2I] = F2I;
+ INSTRUCTIONS[Constants.F2L] = F2L;
+ INSTRUCTIONS[Constants.F2D] = F2D;
+ INSTRUCTIONS[Constants.D2I] = D2I;
+ INSTRUCTIONS[Constants.D2L] = D2L;
+ INSTRUCTIONS[Constants.D2F] = D2F;
+ INSTRUCTIONS[Constants.I2B] = I2B;
+ INSTRUCTIONS[Constants.I2C] = I2C;
+ INSTRUCTIONS[Constants.I2S] = I2S;
+ INSTRUCTIONS[Constants.LCMP] = LCMP;
+ INSTRUCTIONS[Constants.FCMPL] = FCMPL;
+ INSTRUCTIONS[Constants.FCMPG] = FCMPG;
+ INSTRUCTIONS[Constants.DCMPL] = DCMPL;
+ INSTRUCTIONS[Constants.DCMPG] = DCMPG;
+ INSTRUCTIONS[Constants.IRETURN] = IRETURN;
+ INSTRUCTIONS[Constants.LRETURN] = LRETURN;
+ INSTRUCTIONS[Constants.FRETURN] = FRETURN;
+ INSTRUCTIONS[Constants.DRETURN] = DRETURN;
+ INSTRUCTIONS[Constants.ARETURN] = ARETURN;
+ INSTRUCTIONS[Constants.RETURN] = RETURN;
+ INSTRUCTIONS[Constants.ARRAYLENGTH] = ARRAYLENGTH;
+ INSTRUCTIONS[Constants.ATHROW] = ATHROW;
+ INSTRUCTIONS[Constants.MONITORENTER] = MONITORENTER;
+ INSTRUCTIONS[Constants.MONITOREXIT] = MONITOREXIT;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Instances of this class may be used, e.g., to generate typed
+ * versions of instructions. Its main purpose is to be used as the
+ * byte code generating backend of a compiler. You can subclass it to
+ * add your own create methods.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Constants
+ */
+public class InstructionFactory implements InstructionConstants, java.io.Serializable {
+
+ private static final String[] short_names = {
+ "C", "F", "D", "B", "S", "I", "L"
+ };
+
+ protected ClassGen cg;
+ protected ConstantPoolGen cp;
+
+
+ public InstructionFactory(ClassGen cg, ConstantPoolGen cp) {
+ this.cg = cg;
+ this.cp = cp;
+ }
+
+
+ /** Initialize with ClassGen object
+ */
+ public InstructionFactory(ClassGen cg) {
+ this(cg, cg.getConstantPool());
+ }
+
+
+ /** Initialize just with ConstantPoolGen object
+ */
+ public InstructionFactory(ConstantPoolGen cp) {
+ this(null, cp);
+ }
+
+
+ /** Create an invoke instruction.
+ *
+ * @param class_name name of the called class
+ * @param name name of the called method
+ * @param ret_type return type of method
+ * @param arg_types argument types of method
+ * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
+ * or INVOKESPECIAL
+ * @see Constants
+ */
+ public InvokeInstruction createInvoke( String class_name, String name, Type ret_type,
+ Type[] arg_types, short kind ) {
+ int index;
+ int nargs = 0;
+ String signature = Type.getMethodSignature(ret_type, arg_types);
+ for (int i = 0; i < arg_types.length; i++) {
+ nargs += arg_types[i].getSize();
+ }
+ if (kind == Constants.INVOKEINTERFACE) {
+ index = cp.addInterfaceMethodref(class_name, name, signature);
+ } else {
+ index = cp.addMethodref(class_name, name, signature);
+ }
+ switch (kind) {
+ case Constants.INVOKESPECIAL:
+ return new INVOKESPECIAL(index);
+ case Constants.INVOKEVIRTUAL:
+ return new INVOKEVIRTUAL(index);
+ case Constants.INVOKESTATIC:
+ return new INVOKESTATIC(index);
+ case Constants.INVOKEINTERFACE:
+ return new INVOKEINTERFACE(index, nargs + 1);
+ default:
+ throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
+ }
+ }
+
+
+ /** Create a call to the most popular System.out.println() method.
+ *
+ * @param s the string to print
+ */
+ public InstructionList createPrintln( String s ) {
+ InstructionList il = new InstructionList();
+ int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
+ int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
+ il.append(new GETSTATIC(out));
+ il.append(new PUSH(cp, s));
+ il.append(new INVOKEVIRTUAL(println));
+ return il;
+ }
+
+
+ /** Uses PUSH to push a constant value onto the stack.
+ * @param value must be of type Number, Boolean, Character or String
+ */
+ public Instruction createConstant( Object value ) {
+ PUSH push;
+ if (value instanceof Number) {
+ push = new PUSH(cp, (Number) value);
+ } else if (value instanceof String) {
+ push = new PUSH(cp, (String) value);
+ } else if (value instanceof Boolean) {
+ push = new PUSH(cp, (Boolean) value);
+ } else if (value instanceof Character) {
+ push = new PUSH(cp, (Character) value);
+ } else {
+ throw new ClassGenException("Illegal type: " + value.getClass());
+ }
+ return push.getInstruction();
+ }
+
+ private static class MethodObject {
+
+ Type[] arg_types;
+ Type result_type;
+ String class_name;
+ String name;
+ int access;
+
+
+ MethodObject(String c, String n, Type r, Type[] a, int acc) {
+ class_name = c;
+ name = n;
+ result_type = r;
+ arg_types = a;
+ access = acc;
+ }
+ }
+
+
+ private InvokeInstruction createInvoke( MethodObject m, short kind ) {
+ return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
+ }
+
+ private static MethodObject[] append_mos = {
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.STRING
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.OBJECT
+ }, Constants.ACC_PUBLIC),
+ null,
+ null, // indices 2, 3
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.BOOLEAN
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.CHAR
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.FLOAT
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.DOUBLE
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.INT
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte)
+ new Type[] {
+ Type.INT
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short)
+ new Type[] {
+ Type.INT
+ }, Constants.ACC_PUBLIC),
+ new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
+ Type.LONG
+ }, Constants.ACC_PUBLIC)
+ };
+
+
+ private static final boolean isString( Type type ) {
+ return ((type instanceof ObjectType) && ((ObjectType) type).getClassName().equals(
+ "java.lang.String"));
+ }
+
+
+ public Instruction createAppend( Type type ) {
+ byte t = type.getType();
+ if (isString(type)) {
+ return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL);
+ }
+ switch (t) {
+ case Constants.T_BOOLEAN:
+ case Constants.T_CHAR:
+ case Constants.T_FLOAT:
+ case Constants.T_DOUBLE:
+ case Constants.T_BYTE:
+ case Constants.T_SHORT:
+ case Constants.T_INT:
+ case Constants.T_LONG:
+ return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL);
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL);
+ default:
+ throw new RuntimeException("Oops: No append for this type? " + type);
+ }
+ }
+
+
+ /** Create a field instruction.
+ *
+ * @param class_name name of the accessed class
+ * @param name name of the referenced field
+ * @param type type of field
+ * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
+ * @see Constants
+ */
+ public FieldInstruction createFieldAccess( String class_name, String name, Type type, short kind ) {
+ int index;
+ String signature = type.getSignature();
+ index = cp.addFieldref(class_name, name, signature);
+ switch (kind) {
+ case Constants.GETFIELD:
+ return new GETFIELD(index);
+ case Constants.PUTFIELD:
+ return new PUTFIELD(index);
+ case Constants.GETSTATIC:
+ return new GETSTATIC(index);
+ case Constants.PUTSTATIC:
+ return new PUTSTATIC(index);
+ default:
+ throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
+ }
+ }
+
+
+ /** Create reference to `this'
+ */
+ public static Instruction createThis() {
+ return new ALOAD(0);
+ }
+
+
+ /** Create typed return
+ */
+ public static ReturnInstruction createReturn( Type type ) {
+ switch (type.getType()) {
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return ARETURN;
+ case Constants.T_INT:
+ case Constants.T_SHORT:
+ case Constants.T_BOOLEAN:
+ case Constants.T_CHAR:
+ case Constants.T_BYTE:
+ return IRETURN;
+ case Constants.T_FLOAT:
+ return FRETURN;
+ case Constants.T_DOUBLE:
+ return DRETURN;
+ case Constants.T_LONG:
+ return LRETURN;
+ case Constants.T_VOID:
+ return RETURN;
+ default:
+ throw new RuntimeException("Invalid type: " + type);
+ }
+ }
+
+
+ private static final ArithmeticInstruction createBinaryIntOp( char first, String op ) {
+ switch (first) {
+ case '-':
+ return ISUB;
+ case '+':
+ return IADD;
+ case '%':
+ return IREM;
+ case '*':
+ return IMUL;
+ case '/':
+ return IDIV;
+ case '&':
+ return IAND;
+ case '|':
+ return IOR;
+ case '^':
+ return IXOR;
+ case '<':
+ return ISHL;
+ case '>':
+ return op.equals(">>>")
+ ? (ArithmeticInstruction) IUSHR
+ : (ArithmeticInstruction) ISHR;
+ default:
+ throw new RuntimeException("Invalid operand " + op);
+ }
+ }
+
+
+ private static final ArithmeticInstruction createBinaryLongOp( char first, String op ) {
+ switch (first) {
+ case '-':
+ return LSUB;
+ case '+':
+ return LADD;
+ case '%':
+ return LREM;
+ case '*':
+ return LMUL;
+ case '/':
+ return LDIV;
+ case '&':
+ return LAND;
+ case '|':
+ return LOR;
+ case '^':
+ return LXOR;
+ case '<':
+ return LSHL;
+ case '>':
+ return op.equals(">>>")
+ ? (ArithmeticInstruction) LUSHR
+ : (ArithmeticInstruction) LSHR;
+ default:
+ throw new RuntimeException("Invalid operand " + op);
+ }
+ }
+
+
+ private static final ArithmeticInstruction createBinaryFloatOp( char op ) {
+ switch (op) {
+ case '-':
+ return FSUB;
+ case '+':
+ return FADD;
+ case '*':
+ return FMUL;
+ case '/':
+ return FDIV;
+ case '%':
+ return FREM;
+ default:
+ throw new RuntimeException("Invalid operand " + op);
+ }
+ }
+
+
+ private static final ArithmeticInstruction createBinaryDoubleOp( char op ) {
+ switch (op) {
+ case '-':
+ return DSUB;
+ case '+':
+ return DADD;
+ case '*':
+ return DMUL;
+ case '/':
+ return DDIV;
+ case '%':
+ return DREM;
+ default:
+ throw new RuntimeException("Invalid operand " + op);
+ }
+ }
+
+
+ /**
+ * Create binary operation for simple basic types, such as int and float.
+ *
+ * @param op operation, such as "+", "*", "<<", etc.
+ */
+ public static ArithmeticInstruction createBinaryOperation( String op, Type type ) {
+ char first = op.toCharArray()[0];
+ switch (type.getType()) {
+ case Constants.T_BYTE:
+ case Constants.T_SHORT:
+ case Constants.T_INT:
+ case Constants.T_CHAR:
+ return createBinaryIntOp(first, op);
+ case Constants.T_LONG:
+ return createBinaryLongOp(first, op);
+ case Constants.T_FLOAT:
+ return createBinaryFloatOp(first);
+ case Constants.T_DOUBLE:
+ return createBinaryDoubleOp(first);
+ default:
+ throw new RuntimeException("Invalid type " + type);
+ }
+ }
+
+
+ /**
+ * @param size size of operand, either 1 (int, e.g.) or 2 (double)
+ */
+ public static StackInstruction createPop( int size ) {
+ return (size == 2) ? (StackInstruction) POP2 : (StackInstruction) POP;
+ }
+
+
+ /**
+ * @param size size of operand, either 1 (int, e.g.) or 2 (double)
+ */
+ public static StackInstruction createDup( int size ) {
+ return (size == 2) ? (StackInstruction) DUP2 : (StackInstruction) DUP;
+ }
+
+
+ /**
+ * @param size size of operand, either 1 (int, e.g.) or 2 (double)
+ */
+ public static StackInstruction createDup_2( int size ) {
+ return (size == 2) ? (StackInstruction) DUP2_X2 : (StackInstruction) DUP_X2;
+ }
+
+
+ /**
+ * @param size size of operand, either 1 (int, e.g.) or 2 (double)
+ */
+ public static StackInstruction createDup_1( int size ) {
+ return (size == 2) ? (StackInstruction) DUP2_X1 : (StackInstruction) DUP_X1;
+ }
+
+
+ /**
+ * @param index index of local variable
+ */
+ public static LocalVariableInstruction createStore( Type type, int index ) {
+ switch (type.getType()) {
+ case Constants.T_BOOLEAN:
+ case Constants.T_CHAR:
+ case Constants.T_BYTE:
+ case Constants.T_SHORT:
+ case Constants.T_INT:
+ return new ISTORE(index);
+ case Constants.T_FLOAT:
+ return new FSTORE(index);
+ case Constants.T_DOUBLE:
+ return new DSTORE(index);
+ case Constants.T_LONG:
+ return new LSTORE(index);
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return new ASTORE(index);
+ default:
+ throw new RuntimeException("Invalid type " + type);
+ }
+ }
+
+
+ /**
+ * @param index index of local variable
+ */
+ public static LocalVariableInstruction createLoad( Type type, int index ) {
+ switch (type.getType()) {
+ case Constants.T_BOOLEAN:
+ case Constants.T_CHAR:
+ case Constants.T_BYTE:
+ case Constants.T_SHORT:
+ case Constants.T_INT:
+ return new ILOAD(index);
+ case Constants.T_FLOAT:
+ return new FLOAD(index);
+ case Constants.T_DOUBLE:
+ return new DLOAD(index);
+ case Constants.T_LONG:
+ return new LLOAD(index);
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return new ALOAD(index);
+ default:
+ throw new RuntimeException("Invalid type " + type);
+ }
+ }
+
+
+ /**
+ * @param type type of elements of array, i.e., array.getElementType()
+ */
+ public static ArrayInstruction createArrayLoad( Type type ) {
+ switch (type.getType()) {
+ case Constants.T_BOOLEAN:
+ case Constants.T_BYTE:
+ return BALOAD;
+ case Constants.T_CHAR:
+ return CALOAD;
+ case Constants.T_SHORT:
+ return SALOAD;
+ case Constants.T_INT:
+ return IALOAD;
+ case Constants.T_FLOAT:
+ return FALOAD;
+ case Constants.T_DOUBLE:
+ return DALOAD;
+ case Constants.T_LONG:
+ return LALOAD;
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return AALOAD;
+ default:
+ throw new RuntimeException("Invalid type " + type);
+ }
+ }
+
+
+ /**
+ * @param type type of elements of array, i.e., array.getElementType()
+ */
+ public static ArrayInstruction createArrayStore( Type type ) {
+ switch (type.getType()) {
+ case Constants.T_BOOLEAN:
+ case Constants.T_BYTE:
+ return BASTORE;
+ case Constants.T_CHAR:
+ return CASTORE;
+ case Constants.T_SHORT:
+ return SASTORE;
+ case Constants.T_INT:
+ return IASTORE;
+ case Constants.T_FLOAT:
+ return FASTORE;
+ case Constants.T_DOUBLE:
+ return DASTORE;
+ case Constants.T_LONG:
+ return LASTORE;
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return AASTORE;
+ default:
+ throw new RuntimeException("Invalid type " + type);
+ }
+ }
+
+
+ /** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g.,
+ * if the operands are basic types and CHECKCAST if they are reference types.
+ */
+ public Instruction createCast( Type src_type, Type dest_type ) {
+ if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
+ byte dest = dest_type.getType();
+ byte src = src_type.getType();
+ if (dest == Constants.T_LONG
+ && (src == Constants.T_CHAR || src == Constants.T_BYTE || src == Constants.T_SHORT)) {
+ src = Constants.T_INT;
+ }
+ String name = "org.apache.tomcat.util.bcel.generic." + short_names[src - Constants.T_CHAR] + "2"
+ + short_names[dest - Constants.T_CHAR];
+ Instruction i = null;
+ try {
+ i = (Instruction) java.lang.Class.forName(name).newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Could not find instruction: " + name, e);
+ }
+ return i;
+ } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
+ if (dest_type instanceof ArrayType) {
+ return new CHECKCAST(cp.addArrayClass((ArrayType) dest_type));
+ } else {
+ return new CHECKCAST(cp.addClass(((ObjectType) dest_type).getClassName()));
+ }
+ } else {
+ throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
+ }
+ }
+
+
+ public GETFIELD createGetField( String class_name, String name, Type t ) {
+ return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
+ }
+
+
+ public GETSTATIC createGetStatic( String class_name, String name, Type t ) {
+ return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
+ }
+
+
+ public PUTFIELD createPutField( String class_name, String name, Type t ) {
+ return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
+ }
+
+
+ public PUTSTATIC createPutStatic( String class_name, String name, Type t ) {
+ return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
+ }
+
+
+ public CHECKCAST createCheckCast( ReferenceType t ) {
+ if (t instanceof ArrayType) {
+ return new CHECKCAST(cp.addArrayClass((ArrayType) t));
+ } else {
+ return new CHECKCAST(cp.addClass((ObjectType) t));
+ }
+ }
+
+
+ public INSTANCEOF createInstanceOf( ReferenceType t ) {
+ if (t instanceof ArrayType) {
+ return new INSTANCEOF(cp.addArrayClass((ArrayType) t));
+ } else {
+ return new INSTANCEOF(cp.addClass((ObjectType) t));
+ }
+ }
+
+
+ public NEW createNew( ObjectType t ) {
+ return new NEW(cp.addClass(t));
+ }
+
+
+ public NEW createNew( String s ) {
+ return createNew(new ObjectType(s));
+ }
+
+
+ /** Create new array of given size and type.
+ * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction
+ */
+ public Instruction createNewArray( Type t, short dim ) {
+ if (dim == 1) {
+ if (t instanceof ObjectType) {
+ return new ANEWARRAY(cp.addClass((ObjectType) t));
+ } else if (t instanceof ArrayType) {
+ return new ANEWARRAY(cp.addArrayClass((ArrayType) t));
+ } else {
+ return new NEWARRAY(((BasicType) t).getType());
+ }
+ } else {
+ ArrayType at;
+ if (t instanceof ArrayType) {
+ at = (ArrayType) t;
+ } else {
+ at = new ArrayType(t, dim);
+ }
+ return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
+ }
+ }
+
+
+ /** Create "null" value for reference types, 0 for basic types like int
+ */
+ public static Instruction createNull( Type type ) {
+ switch (type.getType()) {
+ case Constants.T_ARRAY:
+ case Constants.T_OBJECT:
+ return ACONST_NULL;
+ case Constants.T_INT:
+ case Constants.T_SHORT:
+ case Constants.T_BOOLEAN:
+ case Constants.T_CHAR:
+ case Constants.T_BYTE:
+ return ICONST_0;
+ case Constants.T_FLOAT:
+ return FCONST_0;
+ case Constants.T_DOUBLE:
+ return DCONST_0;
+ case Constants.T_LONG:
+ return LCONST_0;
+ case Constants.T_VOID:
+ return NOP;
+ default:
+ throw new RuntimeException("Invalid type: " + type);
+ }
+ }
+
+
+ /** Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH.
+ * For those you should use the SWITCH compound instruction.
+ */
+ public static BranchInstruction createBranchInstruction( short opcode, InstructionHandle target ) {
+ switch (opcode) {
+ case Constants.IFEQ:
+ return new IFEQ(target);
+ case Constants.IFNE:
+ return new IFNE(target);
+ case Constants.IFLT:
+ return new IFLT(target);
+ case Constants.IFGE:
+ return new IFGE(target);
+ case Constants.IFGT:
+ return new IFGT(target);
+ case Constants.IFLE:
+ return new IFLE(target);
+ case Constants.IF_ICMPEQ:
+ return new IF_ICMPEQ(target);
+ case Constants.IF_ICMPNE:
+ return new IF_ICMPNE(target);
+ case Constants.IF_ICMPLT:
+ return new IF_ICMPLT(target);
+ case Constants.IF_ICMPGE:
+ return new IF_ICMPGE(target);
+ case Constants.IF_ICMPGT:
+ return new IF_ICMPGT(target);
+ case Constants.IF_ICMPLE:
+ return new IF_ICMPLE(target);
+ case Constants.IF_ACMPEQ:
+ return new IF_ACMPEQ(target);
+ case Constants.IF_ACMPNE:
+ return new IF_ACMPNE(target);
+ case Constants.GOTO:
+ return new GOTO(target);
+ case Constants.JSR:
+ return new JSR(target);
+ case Constants.IFNULL:
+ return new IFNULL(target);
+ case Constants.IFNONNULL:
+ return new IFNONNULL(target);
+ case Constants.GOTO_W:
+ return new GOTO_W(target);
+ case Constants.JSR_W:
+ return new JSR_W(target);
+ default:
+ throw new RuntimeException("Invalid opcode: " + opcode);
+ }
+ }
+
+
+ public void setClassGen( ClassGen c ) {
+ cg = c;
+ }
+
+
+ public ClassGen getClassGen() {
+ return cg;
+ }
+
+
+ public void setConstantPool( ConstantPoolGen c ) {
+ cp = c;
+ }
+
+
+ public ConstantPoolGen getConstantPool() {
+ return cp;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Instances of this class give users a handle to the instructions contained in
+ * an InstructionList. Instruction objects may be used more than once within a
+ * list, this is useful because it saves memory and may be much faster.
+ *
+ * Within an InstructionList an InstructionHandle object is wrapped
+ * around all instructions, i.e., it implements a cell in a
+ * doubly-linked list. From the outside only the next and the
+ * previous instruction (handle) are accessible. One
+ * can traverse the list via an Enumeration returned by
+ * InstructionList.elements().
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Instruction
+ * @see BranchHandle
+ * @see InstructionList
+ */
+public class InstructionHandle implements java.io.Serializable {
+
+ InstructionHandle next, prev; // Will be set from the outside
+ Instruction instruction;
+ protected int i_position = -1; // byte code offset of instruction
+ private Set targeters;
+ private Map attributes;
+
+
+ public final InstructionHandle getNext() {
+ return next;
+ }
+
+
+ public final InstructionHandle getPrev() {
+ return prev;
+ }
+
+
+ public final Instruction getInstruction() {
+ return instruction;
+ }
+
+
+ /**
+ * Replace current instruction contained in this handle.
+ * Old instruction is disposed using Instruction.dispose().
+ */
+ public void setInstruction( Instruction i ) { // Overridden in BranchHandle
+ if (i == null) {
+ throw new ClassGenException("Assigning null to handle");
+ }
+ if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
+ throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
+ }
+ if (instruction != null) {
+ instruction.dispose();
+ }
+ instruction = i;
+ }
+
+
+ /**
+ * Temporarily swap the current instruction, without disturbing
+ * anything. Meant to be used by a debugger, implementing
+ * breakpoints. Current instruction is returned.
+ */
+ public Instruction swapInstruction( Instruction i ) {
+ Instruction oldInstruction = instruction;
+ instruction = i;
+ return oldInstruction;
+ }
+
+
+ /*private*/protected InstructionHandle(Instruction i) {
+ setInstruction(i);
+ }
+
+ private static InstructionHandle ih_list = null; // List of reusable handles
+
+
+ /** Factory method.
+ */
+ static final InstructionHandle getInstructionHandle( Instruction i ) {
+ if (ih_list == null) {
+ return new InstructionHandle(i);
+ } else {
+ InstructionHandle ih = ih_list;
+ ih_list = ih.next;
+ ih.setInstruction(i);
+ return ih;
+ }
+ }
+
+
+ /**
+ * Called by InstructionList.setPositions when setting the position for every
+ * instruction. In the presence of variable length instructions `setPositions()'
+ * performs multiple passes over the instruction list to calculate the
+ * correct (byte) positions and offsets by calling this function.
+ *
+ * @param offset additional offset caused by preceding (variable length) instructions
+ * @param max_offset the maximum offset that may be caused by these instructions
+ * @return additional offset caused by possible change of this instruction's length
+ */
+ protected int updatePosition( int offset, int max_offset ) {
+ i_position += offset;
+ return 0;
+ }
+
+
+ /** @return the position, i.e., the byte code offset of the contained
+ * instruction. This is accurate only after
+ * InstructionList.setPositions() has been called.
+ */
+ public int getPosition() {
+ return i_position;
+ }
+
+
+ /** Set the position, i.e., the byte code offset of the contained
+ * instruction.
+ */
+ void setPosition( int pos ) {
+ i_position = pos;
+ }
+
+
+ /** Overridden in BranchHandle
+ */
+ protected void addHandle() {
+ next = ih_list;
+ ih_list = this;
+ }
+
+
+ /**
+ * Delete contents, i.e., remove user access and make handle reusable.
+ */
+ void dispose() {
+ next = prev = null;
+ instruction.dispose();
+ instruction = null;
+ i_position = -1;
+ attributes = null;
+ removeAllTargeters();
+ addHandle();
+ }
+
+
+ /** Remove all targeters, if any.
+ */
+ public void removeAllTargeters() {
+ if (targeters != null) {
+ targeters.clear();
+ }
+ }
+
+
+ /**
+ * Denote this handle isn't referenced anymore by t.
+ */
+ public void removeTargeter( InstructionTargeter t ) {
+ if (targeters != null) {
+ targeters.remove(t);
+ }
+ }
+
+
+ /**
+ * Denote this handle is being referenced by t.
+ */
+ public void addTargeter( InstructionTargeter t ) {
+ if (targeters == null) {
+ targeters = new HashSet();
+ }
+ //if(!targeters.contains(t))
+ targeters.add(t);
+ }
+
+
+ public boolean hasTargeters() {
+ return (targeters != null) && (targeters.size() > 0);
+ }
+
+
+ /**
+ * @return null, if there are no targeters
+ */
+ public InstructionTargeter[] getTargeters() {
+ if (!hasTargeters()) {
+ return new InstructionTargeter[0];
+ }
+ InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
+ targeters.toArray(t);
+ return t;
+ }
+
+
+ /** @return a (verbose) string representation of the contained instruction.
+ */
+ public String toString( boolean verbose ) {
+ return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
+ }
+
+
+ /** @return a string representation of the contained instruction.
+ */
+ public String toString() {
+ return toString(true);
+ }
+
+
+ /** Add an attribute to an instruction handle.
+ *
+ * @param key the key object to store/retrieve the attribute
+ * @param attr the attribute to associate with this handle
+ */
+ public void addAttribute( Object key, Object attr ) {
+ if (attributes == null) {
+ attributes = new HashMap(3);
+ }
+ attributes.put(key, attr);
+ }
+
+
+ /** Delete an attribute of an instruction handle.
+ *
+ * @param key the key object to retrieve the attribute
+ */
+ public void removeAttribute( Object key ) {
+ if (attributes != null) {
+ attributes.remove(key);
+ }
+ }
+
+
+ /** Get attribute of an instruction handle.
+ *
+ * @param key the key object to store/retrieve the attribute
+ */
+ public Object getAttribute( Object key ) {
+ if (attributes != null) {
+ return attributes.get(key);
+ }
+ return null;
+ }
+
+
+ /** @return all attributes associated with this handle
+ */
+ public Collection getAttributes() {
+ if (attributes == null) {
+ attributes = new HashMap(3);
+ }
+ return attributes.values();
+ }
+
+
+ /** Convenience method, simply calls accept() on the contained instruction.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ instruction.accept(v);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * This class is a container for a list of <a
+ * href="Instruction.html">Instruction</a> objects. Instructions can
+ * be appended, inserted, moved, deleted, etc.. Instructions are being
+ * wrapped into <a
+ * href="InstructionHandle.html">InstructionHandles</a> objects that
+ * are returned upon append/insert operations. They give the user
+ * (read only) access to the list structure, such that it can be traversed and
+ * manipulated in a controlled way.
+ *
+ * A list is finally dumped to a byte code array with <a
+ * href="#getByteCode()">getByteCode</a>.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Instruction
+ * @see InstructionHandle
+ * @see BranchHandle
+ */
+public class InstructionList implements Serializable {
+
+ private InstructionHandle start = null, end = null;
+ private int length = 0; // number of elements in list
+ private int[] byte_positions; // byte code offsets corresponding to instructions
+
+
+ /**
+ * Create (empty) instruction list.
+ */
+ public InstructionList() {
+ }
+
+
+ /**
+ * Create instruction list containing one instruction.
+ * @param i initial instruction
+ */
+ public InstructionList(Instruction i) {
+ append(i);
+ }
+
+
+ /**
+ * Create instruction list containing one instruction.
+ * @param i initial instruction
+ */
+ public InstructionList(BranchInstruction i) {
+ append(i);
+ }
+
+
+ /**
+ * Initialize list with (nonnull) compound instruction. Consumes argument
+ * list, i.e., it becomes empty.
+ *
+ * @param c compound instruction (list)
+ */
+ public InstructionList(CompoundInstruction c) {
+ append(c.getInstructionList());
+ }
+
+
+ /**
+ * Test for empty list.
+ */
+ public boolean isEmpty() {
+ return start == null;
+ } // && end == null
+
+
+ /**
+ * Find the target instruction (handle) that corresponds to the given target
+ * position (byte code offset).
+ *
+ * @param ihs array of instruction handles, i.e. il.getInstructionHandles()
+ * @param pos array of positions corresponding to ihs, i.e. il.getInstructionPositions()
+ * @param count length of arrays
+ * @param target target position to search for
+ * @return target position's instruction handle if available
+ */
+ public static InstructionHandle findHandle( InstructionHandle[] ihs, int[] pos, int count,
+ int target ) {
+ int l = 0, r = count - 1;
+ /* Do a binary search since the pos array is orderd.
+ */
+ do {
+ int i = (l + r) / 2;
+ int j = pos[i];
+ if (j == target) {
+ return ihs[i];
+ } else if (target < j) {
+ r = i - 1;
+ } else {
+ l = i + 1;
+ }
+ } while (l <= r);
+ return null;
+ }
+
+
+ /**
+ * Get instruction handle for instruction at byte code position pos.
+ * This only works properly, if the list is freshly initialized from a byte array or
+ * setPositions() has been called before this method.
+ *
+ * @param pos byte code position to search for
+ * @return target position's instruction handle if available
+ */
+ public InstructionHandle findHandle( int pos ) {
+ int[] positions = byte_positions;
+ InstructionHandle ih = start;
+ for (int i = 0; i < length; i++) {
+ if(positions[i] == pos) {
+ return ih;
+ }
+ ih = ih.next;
+ }
+ return null;
+ }
+
+
+ /**
+ * Initialize instruction list from byte array.
+ *
+ * @param code byte array containing the instructions
+ */
+ public InstructionList(byte[] code) {
+ ByteSequence bytes = new ByteSequence(code);
+ InstructionHandle[] ihs = new InstructionHandle[code.length];
+ int[] pos = new int[code.length]; // Can't be more than that
+ int count = 0; // Contains actual length
+ /* Pass 1: Create an object for each byte code and append them
+ * to the list.
+ */
+ try {
+ while (bytes.available() > 0) {
+ // Remember byte offset and associate it with the instruction
+ int off = bytes.getIndex();
+ pos[count] = off;
+ /* Read one instruction from the byte stream, the byte position is set
+ * accordingly.
+ */
+ Instruction i = Instruction.readInstruction(bytes);
+ InstructionHandle ih;
+ if (i instanceof BranchInstruction) {
+ ih = append((BranchInstruction) i);
+ } else {
+ ih = append(i);
+ }
+ ih.setPosition(off);
+ ihs[count] = ih;
+ count++;
+ }
+ } catch (IOException e) {
+ throw new ClassGenException(e.toString(), e);
+ }
+ byte_positions = new int[count]; // Trim to proper size
+ System.arraycopy(pos, 0, byte_positions, 0, count);
+ /* Pass 2: Look for BranchInstruction and update their targets, i.e.,
+ * convert offsets to instruction handles.
+ */
+ for (int i = 0; i < count; i++) {
+ if (ihs[i] instanceof BranchHandle) {
+ BranchInstruction bi = (BranchInstruction) ihs[i].instruction;
+ int target = bi.position + bi.getIndex(); /* Byte code position:
+ * relative -> absolute. */
+ // Search for target position
+ InstructionHandle ih = findHandle(ihs, pos, count, target);
+ if (ih == null) {
+ throw new ClassGenException("Couldn't find target for branch: " + bi);
+ }
+ bi.setTarget(ih); // Update target
+ // If it is a Select instruction, update all branch targets
+ if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH
+ Select s = (Select) bi;
+ int[] indices = s.getIndices();
+ for (int j = 0; j < indices.length; j++) {
+ target = bi.position + indices[j];
+ ih = findHandle(ihs, pos, count, target);
+ if (ih == null) {
+ throw new ClassGenException("Couldn't find target for switch: " + bi);
+ }
+ s.setTarget(j, ih); // Update target
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Append another list after instruction (handle) ih contained in this list.
+ * Consumes argument list, i.e., it becomes empty.
+ *
+ * @param ih where to append the instruction list
+ * @param il Instruction list to append to this one
+ * @return instruction handle pointing to the <B>first</B> appended instruction
+ */
+ public InstructionHandle append( InstructionHandle ih, InstructionList il ) {
+ if (il == null) {
+ throw new ClassGenException("Appending null InstructionList");
+ }
+ if (il.isEmpty()) {
+ return ih;
+ }
+ InstructionHandle next = ih.next, ret = il.start;
+ ih.next = il.start;
+ il.start.prev = ih;
+ il.end.next = next;
+ if (next != null) {
+ next.prev = il.end;
+ } else {
+ end = il.end; // Update end ...
+ }
+ length += il.length; // Update length
+ il.clear();
+ return ret;
+ }
+
+
+ /**
+ * Append another list after instruction i contained in this list.
+ * Consumes argument list, i.e., it becomes empty.
+ *
+ * @param i where to append the instruction list
+ * @param il Instruction list to append to this one
+ * @return instruction handle pointing to the <B>first</B> appended instruction
+ */
+ public InstructionHandle append( Instruction i, InstructionList il ) {
+ InstructionHandle ih;
+ if ((ih = findInstruction2(i)) == null) {
+ throw new ClassGenException("Instruction " + i + " is not contained in this list.");
+ }
+ return append(ih, il);
+ }
+
+
+ /**
+ * Append another list to this one.
+ * Consumes argument list, i.e., it becomes empty.
+ *
+ * @param il list to append to end of this list
+ * @return instruction handle of the <B>first</B> appended instruction
+ */
+ public InstructionHandle append( InstructionList il ) {
+ if (il == null) {
+ throw new ClassGenException("Appending null InstructionList");
+ }
+ if (il.isEmpty()) {
+ return null;
+ }
+ if (isEmpty()) {
+ start = il.start;
+ end = il.end;
+ length = il.length;
+ il.clear();
+ return start;
+ } else {
+ return append(end, il); // was end.instruction
+ }
+ }
+
+
+ /**
+ * Append an instruction to the end of this list.
+ *
+ * @param ih instruction to append
+ */
+ private void append( InstructionHandle ih ) {
+ if (isEmpty()) {
+ start = end = ih;
+ ih.next = ih.prev = null;
+ } else {
+ end.next = ih;
+ ih.prev = end;
+ ih.next = null;
+ end = ih;
+ }
+ length++; // Update length
+ }
+
+
+ /**
+ * Append an instruction to the end of this list.
+ *
+ * @param i instruction to append
+ * @return instruction handle of the appended instruction
+ */
+ public InstructionHandle append( Instruction i ) {
+ InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
+ append(ih);
+ return ih;
+ }
+
+
+ /**
+ * Append a branch instruction to the end of this list.
+ *
+ * @param i branch instruction to append
+ * @return branch instruction handle of the appended instruction
+ */
+ public BranchHandle append( BranchInstruction i ) {
+ BranchHandle ih = BranchHandle.getBranchHandle(i);
+ append(ih);
+ return ih;
+ }
+
+
+ /**
+ * Append a single instruction j after another instruction i, which
+ * must be in this list of course!
+ *
+ * @param i Instruction in list
+ * @param j Instruction to append after i in list
+ * @return instruction handle of the first appended instruction
+ */
+ public InstructionHandle append( Instruction i, Instruction j ) {
+ return append(i, new InstructionList(j));
+ }
+
+
+ /**
+ * Append a compound instruction, after instruction i.
+ *
+ * @param i Instruction in list
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first appended instruction
+ */
+ public InstructionHandle append( Instruction i, CompoundInstruction c ) {
+ return append(i, c.getInstructionList());
+ }
+
+
+ /**
+ * Append a compound instruction.
+ *
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first appended instruction
+ */
+ public InstructionHandle append( CompoundInstruction c ) {
+ return append(c.getInstructionList());
+ }
+
+
+ /**
+ * Append a compound instruction.
+ *
+ * @param ih where to append the instruction list
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first appended instruction
+ */
+ public InstructionHandle append( InstructionHandle ih, CompoundInstruction c ) {
+ return append(ih, c.getInstructionList());
+ }
+
+
+ /**
+ * Append an instruction after instruction (handle) ih contained in this list.
+ *
+ * @param ih where to append the instruction list
+ * @param i Instruction to append
+ * @return instruction handle pointing to the <B>first</B> appended instruction
+ */
+ public InstructionHandle append( InstructionHandle ih, Instruction i ) {
+ return append(ih, new InstructionList(i));
+ }
+
+
+ /**
+ * Append an instruction after instruction (handle) ih contained in this list.
+ *
+ * @param ih where to append the instruction list
+ * @param i Instruction to append
+ * @return instruction handle pointing to the <B>first</B> appended instruction
+ */
+ public BranchHandle append( InstructionHandle ih, BranchInstruction i ) {
+ BranchHandle bh = BranchHandle.getBranchHandle(i);
+ InstructionList il = new InstructionList();
+ il.append(bh);
+ append(ih, il);
+ return bh;
+ }
+
+
+ /**
+ * Insert another list before Instruction handle ih contained in this list.
+ * Consumes argument list, i.e., it becomes empty.
+ *
+ * @param ih where to append the instruction list
+ * @param il Instruction list to insert
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( InstructionHandle ih, InstructionList il ) {
+ if (il == null) {
+ throw new ClassGenException("Inserting null InstructionList");
+ }
+ if (il.isEmpty()) {
+ return ih;
+ }
+ InstructionHandle prev = ih.prev, ret = il.start;
+ ih.prev = il.end;
+ il.end.next = ih;
+ il.start.prev = prev;
+ if (prev != null) {
+ prev.next = il.start;
+ } else {
+ start = il.start; // Update start ...
+ }
+ length += il.length; // Update length
+ il.clear();
+ return ret;
+ }
+
+
+ /**
+ * Insert another list.
+ *
+ * @param il list to insert before start of this list
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( InstructionList il ) {
+ if (isEmpty()) {
+ append(il); // Code is identical for this case
+ return start;
+ } else {
+ return insert(start, il);
+ }
+ }
+
+
+ /**
+ * Insert an instruction at start of this list.
+ *
+ * @param ih instruction to insert
+ */
+ private void insert( InstructionHandle ih ) {
+ if (isEmpty()) {
+ start = end = ih;
+ ih.next = ih.prev = null;
+ } else {
+ start.prev = ih;
+ ih.next = start;
+ ih.prev = null;
+ start = ih;
+ }
+ length++;
+ }
+
+
+ /**
+ * Insert another list before Instruction i contained in this list.
+ * Consumes argument list, i.e., it becomes empty.
+ *
+ * @param i where to append the instruction list
+ * @param il Instruction list to insert
+ * @return instruction handle pointing to the first inserted instruction,
+ * i.e., il.getStart()
+ */
+ public InstructionHandle insert( Instruction i, InstructionList il ) {
+ InstructionHandle ih;
+ if ((ih = findInstruction1(i)) == null) {
+ throw new ClassGenException("Instruction " + i + " is not contained in this list.");
+ }
+ return insert(ih, il);
+ }
+
+
+ /**
+ * Insert an instruction at start of this list.
+ *
+ * @param i instruction to insert
+ * @return instruction handle of the inserted instruction
+ */
+ public InstructionHandle insert( Instruction i ) {
+ InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
+ insert(ih);
+ return ih;
+ }
+
+
+ /**
+ * Insert a branch instruction at start of this list.
+ *
+ * @param i branch instruction to insert
+ * @return branch instruction handle of the appended instruction
+ */
+ public BranchHandle insert( BranchInstruction i ) {
+ BranchHandle ih = BranchHandle.getBranchHandle(i);
+ insert(ih);
+ return ih;
+ }
+
+
+ /**
+ * Insert a single instruction j before another instruction i, which
+ * must be in this list of course!
+ *
+ * @param i Instruction in list
+ * @param j Instruction to insert before i in list
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( Instruction i, Instruction j ) {
+ return insert(i, new InstructionList(j));
+ }
+
+
+ /**
+ * Insert a compound instruction before instruction i.
+ *
+ * @param i Instruction in list
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( Instruction i, CompoundInstruction c ) {
+ return insert(i, c.getInstructionList());
+ }
+
+
+ /**
+ * Insert a compound instruction.
+ *
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( CompoundInstruction c ) {
+ return insert(c.getInstructionList());
+ }
+
+
+ /**
+ * Insert an instruction before instruction (handle) ih contained in this list.
+ *
+ * @param ih where to insert to the instruction list
+ * @param i Instruction to insert
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( InstructionHandle ih, Instruction i ) {
+ return insert(ih, new InstructionList(i));
+ }
+
+
+ /**
+ * Insert a compound instruction.
+ *
+ * @param ih where to insert the instruction list
+ * @param c The composite instruction (containing an InstructionList)
+ * @return instruction handle of the first inserted instruction
+ */
+ public InstructionHandle insert( InstructionHandle ih, CompoundInstruction c ) {
+ return insert(ih, c.getInstructionList());
+ }
+
+
+ /**
+ * Insert an instruction before instruction (handle) ih contained in this list.
+ *
+ * @param ih where to insert to the instruction list
+ * @param i Instruction to insert
+ * @return instruction handle of the first inserted instruction
+ */
+ public BranchHandle insert( InstructionHandle ih, BranchInstruction i ) {
+ BranchHandle bh = BranchHandle.getBranchHandle(i);
+ InstructionList il = new InstructionList();
+ il.append(bh);
+ insert(ih, il);
+ return bh;
+ }
+
+
+ /**
+ * Take all instructions (handles) from "start" to "end" and append them after the
+ * new location "target". Of course, "end" must be after "start" and target must
+ * not be located withing this range. If you want to move something to the start of
+ * the list use null as value for target.<br>
+ * Any instruction targeters pointing to handles within the block, keep their targets.
+ *
+ * @param start of moved block
+ * @param end of moved block
+ * @param target of moved block
+ */
+ public void move( InstructionHandle start, InstructionHandle end, InstructionHandle target ) {
+ // Step 1: Check constraints
+ if ((start == null) || (end == null)) {
+ throw new ClassGenException("Invalid null handle: From " + start + " to " + end);
+ }
+ if ((target == start) || (target == end)) {
+ throw new ClassGenException("Invalid range: From " + start + " to " + end
+ + " contains target " + target);
+ }
+ for (InstructionHandle ih = start; ih != end.next; ih = ih.next) {
+ if (ih == null) {
+ throw new ClassGenException("Invalid range: From " + start + " to " + end);
+ } else if (ih == target) {
+ throw new ClassGenException("Invalid range: From " + start + " to " + end
+ + " contains target " + target);
+ }
+ }
+ // Step 2: Temporarily remove the given instructions from the list
+ InstructionHandle prev = start.prev, next = end.next;
+ if (prev != null) {
+ prev.next = next;
+ } else {
+ this.start = next;
+ }
+ if (next != null) {
+ next.prev = prev;
+ } else {
+ this.end = prev;
+ }
+ start.prev = end.next = null;
+ // Step 3: append after target
+ if (target == null) { // append to start of list
+ if (this.start != null) {
+ this.start.prev = end;
+ }
+ end.next = this.start;
+ this.start = start;
+ } else {
+ next = target.next;
+ target.next = start;
+ start.prev = target;
+ end.next = next;
+ if (next != null) {
+ next.prev = end;
+ } else {
+ this.end = end;
+ }
+ }
+ }
+
+
+ /**
+ * Move a single instruction (handle) to a new location.
+ *
+ * @param ih moved instruction
+ * @param target new location of moved instruction
+ */
+ public void move( InstructionHandle ih, InstructionHandle target ) {
+ move(ih, ih, target);
+ }
+
+
+ /**
+ * Remove from instruction `prev' to instruction `next' both contained
+ * in this list. Throws TargetLostException when one of the removed instruction handles
+ * is still being targeted.
+ *
+ * @param prev where to start deleting (predecessor, exclusive)
+ * @param next where to end deleting (successor, exclusive)
+ */
+ private void remove( InstructionHandle prev, InstructionHandle next )
+ throws TargetLostException {
+ InstructionHandle first, last; // First and last deleted instruction
+ if ((prev == null) && (next == null)) {
+ first = start;
+ last = end;
+ start = end = null;
+ } else {
+ if (prev == null) { // At start of list
+ first = start;
+ start = next;
+ } else {
+ first = prev.next;
+ prev.next = next;
+ }
+ if (next == null) { // At end of list
+ last = end;
+ end = prev;
+ } else {
+ last = next.prev;
+ next.prev = prev;
+ }
+ }
+ first.prev = null; // Completely separated from rest of list
+ last.next = null;
+ List target_vec = new ArrayList();
+ for (InstructionHandle ih = first; ih != null; ih = ih.next) {
+ ih.getInstruction().dispose(); // e.g. BranchInstructions release their targets
+ }
+ StringBuffer buf = new StringBuffer("{ ");
+ for (InstructionHandle ih = first; ih != null; ih = next) {
+ next = ih.next;
+ length--;
+ if (ih.hasTargeters()) { // Still got targeters?
+ target_vec.add(ih);
+ buf.append(ih.toString(true) + " ");
+ ih.next = ih.prev = null;
+ } else {
+ ih.dispose();
+ }
+ }
+ buf.append("}");
+ if (!target_vec.isEmpty()) {
+ InstructionHandle[] targeted = new InstructionHandle[target_vec.size()];
+ target_vec.toArray(targeted);
+ throw new TargetLostException(targeted, buf.toString());
+ }
+ }
+
+
+ /**
+ * Remove instruction from this list. The corresponding Instruction
+ * handles must not be reused!
+ *
+ * @param ih instruction (handle) to remove
+ */
+ public void delete( InstructionHandle ih ) throws TargetLostException {
+ remove(ih.prev, ih.next);
+ }
+
+
+ /**
+ * Remove instruction from this list. The corresponding Instruction
+ * handles must not be reused!
+ *
+ * @param i instruction to remove
+ */
+ public void delete( Instruction i ) throws TargetLostException {
+ InstructionHandle ih;
+ if ((ih = findInstruction1(i)) == null) {
+ throw new ClassGenException("Instruction " + i + " is not contained in this list.");
+ }
+ delete(ih);
+ }
+
+
+ /**
+ * Remove instructions from instruction `from' to instruction `to' contained
+ * in this list. The user must ensure that `from' is an instruction before
+ * `to', or risk havoc. The corresponding Instruction handles must not be reused!
+ *
+ * @param from where to start deleting (inclusive)
+ * @param to where to end deleting (inclusive)
+ */
+ public void delete( InstructionHandle from, InstructionHandle to ) throws TargetLostException {
+ remove(from.prev, to.next);
+ }
+
+
+ /**
+ * Remove instructions from instruction `from' to instruction `to' contained
+ * in this list. The user must ensure that `from' is an instruction before
+ * `to', or risk havoc. The corresponding Instruction handles must not be reused!
+ *
+ * @param from where to start deleting (inclusive)
+ * @param to where to end deleting (inclusive)
+ */
+ public void delete( Instruction from, Instruction to ) throws TargetLostException {
+ InstructionHandle from_ih, to_ih;
+ if ((from_ih = findInstruction1(from)) == null) {
+ throw new ClassGenException("Instruction " + from + " is not contained in this list.");
+ }
+ if ((to_ih = findInstruction2(to)) == null) {
+ throw new ClassGenException("Instruction " + to + " is not contained in this list.");
+ }
+ delete(from_ih, to_ih);
+ }
+
+
+ /**
+ * Search for given Instruction reference, start at beginning of list.
+ *
+ * @param i instruction to search for
+ * @return instruction found on success, null otherwise
+ */
+ private InstructionHandle findInstruction1( Instruction i ) {
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ if (ih.instruction == i) {
+ return ih;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Search for given Instruction reference, start at end of list
+ *
+ * @param i instruction to search for
+ * @return instruction found on success, null otherwise
+ */
+ private InstructionHandle findInstruction2( Instruction i ) {
+ for (InstructionHandle ih = end; ih != null; ih = ih.prev) {
+ if (ih.instruction == i) {
+ return ih;
+ }
+ }
+ return null;
+ }
+
+
+ public boolean contains( InstructionHandle i ) {
+ if (i == null) {
+ return false;
+ }
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ if (ih == i) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ public boolean contains( Instruction i ) {
+ return findInstruction1(i) != null;
+ }
+
+
+ public void setPositions() {
+ setPositions(false);
+ }
+
+
+ /**
+ * Give all instructions their position number (offset in byte stream), i.e.,
+ * make the list ready to be dumped.
+ *
+ * @param check Perform sanity checks, e.g. if all targeted instructions really belong
+ * to this list
+ */
+ public void setPositions( boolean check ) {
+ int max_additional_bytes = 0, additional_bytes = 0;
+ int index = 0, count = 0;
+ int[] pos = new int[length];
+ /* Pass 0: Sanity checks
+ */
+ if (check) {
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ if (i instanceof BranchInstruction) { // target instruction within list?
+ Instruction inst = ((BranchInstruction) i).getTarget().instruction;
+ if (!contains(inst)) {
+ throw new ClassGenException("Branch target of "
+ + Constants.OPCODE_NAMES[i.opcode] + ":" + inst
+ + " not in instruction list");
+ }
+ if (i instanceof Select) {
+ InstructionHandle[] targets = ((Select) i).getTargets();
+ for (int j = 0; j < targets.length; j++) {
+ inst = targets[j].instruction;
+ if (!contains(inst)) {
+ throw new ClassGenException("Branch target of "
+ + Constants.OPCODE_NAMES[i.opcode] + ":" + inst
+ + " not in instruction list");
+ }
+ }
+ }
+ if (!(ih instanceof BranchHandle)) {
+ throw new ClassGenException("Branch instruction "
+ + Constants.OPCODE_NAMES[i.opcode] + ":" + inst
+ + " not contained in BranchHandle.");
+ }
+ }
+ }
+ }
+ /* Pass 1: Set position numbers and sum up the maximum number of bytes an
+ * instruction may be shifted.
+ */
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ ih.setPosition(index);
+ pos[count++] = index;
+ /* Get an estimate about how many additional bytes may be added, because
+ * BranchInstructions may have variable length depending on the target
+ * offset (short vs. int) or alignment issues (TABLESWITCH and
+ * LOOKUPSWITCH).
+ */
+ switch (i.getOpcode()) {
+ case Constants.JSR:
+ case Constants.GOTO:
+ max_additional_bytes += 2;
+ break;
+ case Constants.TABLESWITCH:
+ case Constants.LOOKUPSWITCH:
+ max_additional_bytes += 3;
+ break;
+ }
+ index += i.getLength();
+ }
+ /* Pass 2: Expand the variable-length (Branch)Instructions depending on
+ * the target offset (short or int) and ensure that branch targets are
+ * within this list.
+ */
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes);
+ }
+ /* Pass 3: Update position numbers (which may have changed due to the
+ * preceding expansions), like pass 1.
+ */
+ index = count = 0;
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ ih.setPosition(index);
+ pos[count++] = index;
+ index += i.getLength();
+ }
+ byte_positions = new int[count]; // Trim to proper size
+ System.arraycopy(pos, 0, byte_positions, 0, count);
+ }
+
+
+ /**
+ * When everything is finished, use this method to convert the instruction
+ * list into an array of bytes.
+ *
+ * @return the byte code ready to be dumped
+ */
+ public byte[] getByteCode() {
+ // Update position indices of instructions
+ setPositions();
+ ByteArrayOutputStream b = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(b);
+ try {
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ i.dump(out); // Traverse list
+ }
+ } catch (IOException e) {
+ System.err.println(e);
+ return new byte[0];
+ }
+ return b.toByteArray();
+ }
+
+
+ /**
+ * @return an array of instructions without target information for branch instructions.
+ */
+ public Instruction[] getInstructions() {
+ ByteSequence bytes = new ByteSequence(getByteCode());
+ List instructions = new ArrayList();
+ try {
+ while (bytes.available() > 0) {
+ instructions.add(Instruction.readInstruction(bytes));
+ }
+ } catch (IOException e) {
+ throw new ClassGenException(e.toString(), e);
+ }
+ return (Instruction[]) instructions.toArray(new Instruction[instructions.size()]);
+ }
+
+
+ public String toString() {
+ return toString(true);
+ }
+
+
+ /**
+ * @param verbose toggle output format
+ * @return String containing all instructions in this list.
+ */
+ public String toString( boolean verbose ) {
+ StringBuffer buf = new StringBuffer();
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ buf.append(ih.toString(verbose)).append("\n");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return Enumeration that lists all instructions (handles)
+ */
+ public Iterator iterator() {
+ return new Iterator() {
+
+ private InstructionHandle ih = start;
+
+
+ public Object next() throws NoSuchElementException {
+ if (ih == null)
+ throw new NoSuchElementException();
+ InstructionHandle i = ih;
+ ih = ih.next;
+ return i;
+ }
+
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ public boolean hasNext() {
+ return ih != null;
+ }
+ };
+ }
+
+
+ /**
+ * @return array containing all instructions (handles)
+ */
+ public InstructionHandle[] getInstructionHandles() {
+ InstructionHandle[] ihs = new InstructionHandle[length];
+ InstructionHandle ih = start;
+ for (int i = 0; i < length; i++) {
+ ihs[i] = ih;
+ ih = ih.next;
+ }
+ return ihs;
+ }
+
+
+ /**
+ * Get positions (offsets) of all instructions in the list. This relies on that
+ * the list has been freshly created from an byte code array, or that setPositions()
+ * has been called. Otherwise this may be inaccurate.
+ *
+ * @return array containing all instruction's offset in byte code
+ */
+ public int[] getInstructionPositions() {
+ return byte_positions;
+ }
+
+
+ /**
+ * @return complete, i.e., deep copy of this list
+ */
+ public InstructionList copy() {
+ Map map = new HashMap();
+ InstructionList il = new InstructionList();
+ /* Pass 1: Make copies of all instructions, append them to the new list
+ * and associate old instruction references with the new ones, i.e.,
+ * a 1:1 mapping.
+ */
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ Instruction c = i.copy(); // Use clone for shallow copy
+ if (c instanceof BranchInstruction) {
+ map.put(ih, il.append((BranchInstruction) c));
+ } else {
+ map.put(ih, il.append(c));
+ }
+ }
+ /* Pass 2: Update branch targets.
+ */
+ InstructionHandle ih = start;
+ InstructionHandle ch = il.start;
+ while (ih != null) {
+ Instruction i = ih.instruction;
+ Instruction c = ch.instruction;
+ if (i instanceof BranchInstruction) {
+ BranchInstruction bi = (BranchInstruction) i;
+ BranchInstruction bc = (BranchInstruction) c;
+ InstructionHandle itarget = bi.getTarget(); // old target
+ // New target is in hash map
+ bc.setTarget((InstructionHandle) map.get(itarget));
+ if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH
+ InstructionHandle[] itargets = ((Select) bi).getTargets();
+ InstructionHandle[] ctargets = ((Select) bc).getTargets();
+ for (int j = 0; j < itargets.length; j++) { // Update all targets
+ ctargets[j] = (InstructionHandle) map.get(itargets[j]);
+ }
+ }
+ }
+ ih = ih.next;
+ ch = ch.next;
+ }
+ return il;
+ }
+
+
+ /** Replace all references to the old constant pool with references to the new
+ * constant pool
+ */
+ public void replaceConstantPool( ConstantPoolGen old_cp, ConstantPoolGen new_cp ) {
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.instruction;
+ if (i instanceof CPInstruction) {
+ CPInstruction ci = (CPInstruction) i;
+ Constant c = old_cp.getConstant(ci.getIndex());
+ ci.setIndex(new_cp.addConstant(c, old_cp));
+ }
+ }
+ }
+
+
+ private void clear() {
+ start = end = null;
+ length = 0;
+ }
+
+
+ /**
+ * Delete contents of list. Provides besser memory utilization,
+ * because the system then may reuse the instruction handles. This
+ * method is typically called right after
+ * <href="MethodGen.html#getMethod()">MethodGen.getMethod()</a>.
+ */
+ public void dispose() {
+ // Traverse in reverse order, because ih.next is overwritten
+ for (InstructionHandle ih = end; ih != null; ih = ih.prev) {
+ /* Causes BranchInstructions to release target and targeters, because it
+ * calls dispose() on the contained instruction.
+ */
+ ih.dispose();
+ }
+ clear();
+ }
+
+
+ /**
+ * @return start of list
+ */
+ public InstructionHandle getStart() {
+ return start;
+ }
+
+
+ /**
+ * @return end of list
+ */
+ public InstructionHandle getEnd() {
+ return end;
+ }
+
+
+ /**
+ * @return length of list (Number of instructions, not bytes)
+ */
+ public int getLength() {
+ return length;
+ }
+
+
+ /**
+ * @return length of list (Number of instructions, not bytes)
+ */
+ public int size() {
+ return length;
+ }
+
+
+ /**
+ * Redirect all references from old_target to new_target, i.e., update targets
+ * of branch instructions.
+ *
+ * @param old_target the old target instruction handle
+ * @param new_target the new target instruction handle
+ */
+ public void redirectBranches( InstructionHandle old_target, InstructionHandle new_target ) {
+ for (InstructionHandle ih = start; ih != null; ih = ih.next) {
+ Instruction i = ih.getInstruction();
+ if (i instanceof BranchInstruction) {
+ BranchInstruction b = (BranchInstruction) i;
+ InstructionHandle target = b.getTarget();
+ if (target == old_target) {
+ b.setTarget(new_target);
+ }
+ if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH
+ InstructionHandle[] targets = ((Select) b).getTargets();
+ for (int j = 0; j < targets.length; j++) {
+ if (targets[j] == old_target) {
+ ((Select) b).setTarget(j, new_target);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Redirect all references of local variables from old_target to new_target.
+ *
+ * @param lg array of local variables
+ * @param old_target the old target instruction handle
+ * @param new_target the new target instruction handle
+ * @see MethodGen
+ */
+ public void redirectLocalVariables( LocalVariableGen[] lg, InstructionHandle old_target,
+ InstructionHandle new_target ) {
+ for (int i = 0; i < lg.length; i++) {
+ InstructionHandle start = lg[i].getStart();
+ InstructionHandle end = lg[i].getEnd();
+ if (start == old_target) {
+ lg[i].setStart(new_target);
+ }
+ if (end == old_target) {
+ lg[i].setEnd(new_target);
+ }
+ }
+ }
+
+
+ /**
+ * Redirect all references of exception handlers from old_target to new_target.
+ *
+ * @param exceptions array of exception handlers
+ * @param old_target the old target instruction handle
+ * @param new_target the new target instruction handle
+ * @see MethodGen
+ */
+ public void redirectExceptionHandlers( CodeExceptionGen[] exceptions,
+ InstructionHandle old_target, InstructionHandle new_target ) {
+ for (int i = 0; i < exceptions.length; i++) {
+ if (exceptions[i].getStartPC() == old_target) {
+ exceptions[i].setStartPC(new_target);
+ }
+ if (exceptions[i].getEndPC() == old_target) {
+ exceptions[i].setEndPC(new_target);
+ }
+ if (exceptions[i].getHandlerPC() == old_target) {
+ exceptions[i].setHandlerPC(new_target);
+ }
+ }
+ }
+
+ private List observers;
+
+
+ /** Add observer for this object.
+ */
+ public void addObserver( InstructionListObserver o ) {
+ if (observers == null) {
+ observers = new ArrayList();
+ }
+ observers.add(o);
+ }
+
+
+ /** Remove observer for this object.
+ */
+ public void removeObserver( InstructionListObserver o ) {
+ if (observers != null) {
+ observers.remove(o);
+ }
+ }
+
+
+ /** Call notify() method on all observers. This method is not called
+ * automatically whenever the state has changed, but has to be
+ * called by the user after he has finished editing the object.
+ */
+ public void update() {
+ if (observers != null) {
+ for (Iterator e = observers.iterator(); e.hasNext();) {
+ ((InstructionListObserver) e.next()).notify(this);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Implement this interface if you're interested in changes to an InstructionList object
+ * and register yourself with addObserver().
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface InstructionListObserver {
+
+ public void notify( InstructionList list );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote that a class targets InstructionHandles within an InstructionList. Namely
+ * the following implementers:
+ *
+ * @see BranchHandle
+ * @see LocalVariableGen
+ * @see CodeExceptionGen
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface InstructionTargeter {
+
+ public boolean containsTarget( InstructionHandle ih );
+
+
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.StringTokenizer;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+
+/**
+ * Super class for the INVOKExxx family of instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower,
+ TypedInstruction, StackConsumer, StackProducer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ InvokeInstruction() {
+ }
+
+
+ /**
+ * @param index to constant pool
+ */
+ protected InvokeInstruction(short opcode, int index) {
+ super(opcode, index);
+ }
+
+
+ /**
+ * @return mnemonic for instruction with symbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ Constant c = cp.getConstant(index);
+ StringTokenizer tok = new StringTokenizer(cp.constantToString(c));
+ return Constants.OPCODE_NAMES[opcode] + " " + tok.nextToken().replace('.', '/')
+ + tok.nextToken();
+ }
+
+
+ /**
+ * Also works for instructions whose stack effect depends on the
+ * constant pool entry they reference.
+ * @return Number of words consumed from stack by this instruction
+ */
+ public int consumeStack( ConstantPoolGen cpg ) {
+ int sum;
+ if (opcode == Constants.INVOKESTATIC) {
+ sum = 0;
+ } else {
+ sum = 1; // this reference
+ }
+
+ String signature = getSignature(cpg);
+ sum += Type.getArgumentTypesSize(signature);
+ return sum;
+ }
+
+
+ /**
+ * Also works for instructions whose stack effect depends on the
+ * constant pool entry they reference.
+ * @return Number of words produced onto stack by this instruction
+ */
+ public int produceStack( ConstantPoolGen cpg ) {
+ String signature = getSignature(cpg);
+ return Type.getReturnTypeSize(signature);
+ }
+
+
+ /** @return return type of referenced method.
+ */
+ public Type getType( ConstantPoolGen cpg ) {
+ return getReturnType(cpg);
+ }
+
+
+ /** @return name of referenced method.
+ */
+ public String getMethodName( ConstantPoolGen cpg ) {
+ return getName(cpg);
+ }
+
+
+ /** @return return type of referenced method.
+ */
+ public Type getReturnType( ConstantPoolGen cpg ) {
+ return Type.getReturnType(getSignature(cpg));
+ }
+
+
+ /** @return argument types of referenced method.
+ */
+ public Type[] getArgumentTypes( ConstantPoolGen cpg ) {
+ return Type.getArgumentTypes(getSignature(cpg));
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * JSR - Jump to subroutine
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class JSR extends JsrInstruction implements VariableLengthInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ JSR() {
+ }
+
+
+ public JSR(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.JSR, target);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ index = getTargetOffset();
+ if (opcode == org.apache.tomcat.util.bcel.Constants.JSR) {
+ super.dump(out);
+ } else { // JSR_W
+ index = getTargetOffset();
+ out.writeByte(opcode);
+ out.writeInt(index);
+ }
+ }
+
+
+ protected int updatePosition( int offset, int max_offset ) {
+ int i = getTargetOffset(); // Depending on old position value
+ position += offset; // Position may be shifted by preceding expansions
+ if (Math.abs(i) >= (32767 - max_offset)) { // to large for short (estimate)
+ opcode = org.apache.tomcat.util.bcel.Constants.JSR_W;
+ length = 5;
+ return 2; // 5 - 3
+ }
+ return 0;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitVariableLengthInstruction(this);
+ v.visitBranchInstruction(this);
+ v.visitJsrInstruction(this);
+ v.visitJSR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * JSR_W - Jump to subroutine
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class JSR_W extends JsrInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ JSR_W() {
+ }
+
+
+ public JSR_W(InstructionHandle target) {
+ super(org.apache.tomcat.util.bcel.Constants.JSR_W, target);
+ length = 5;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ index = getTargetOffset();
+ out.writeByte(opcode);
+ out.writeInt(index);
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ index = bytes.readInt();
+ length = 5;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitBranchInstruction(this);
+ v.visitJsrInstruction(this);
+ v.visitJSR_W(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Super class for JSR - Jump to subroutine
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch,
+ TypedInstruction, StackProducer {
+
+ JsrInstruction(short opcode, InstructionHandle target) {
+ super(opcode, target);
+ }
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ JsrInstruction() {
+ }
+
+
+ /** @return return address type
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return new ReturnaddressType(physicalSuccessor());
+ }
+
+
+ /**
+ * Returns an InstructionHandle to the physical successor
+ * of this JsrInstruction. <B>For this method to work,
+ * this JsrInstruction object must not be shared between
+ * multiple InstructionHandle objects!</B>
+ * Formally, there must not be InstructionHandle objects
+ * i, j where i != j and i.getInstruction() == this ==
+ * j.getInstruction().
+ * @return an InstructionHandle to the "next" instruction that
+ * will be executed when RETurned from a subroutine.
+ */
+ public InstructionHandle physicalSuccessor() {
+ InstructionHandle ih = this.target;
+ // Rewind!
+ while (ih.getPrev() != null) {
+ ih = ih.getPrev();
+ }
+ // Find the handle for "this" JsrInstruction object.
+ while (ih.getInstruction() != this) {
+ ih = ih.getNext();
+ }
+ InstructionHandle toThis = ih;
+ while (ih != null) {
+ ih = ih.getNext();
+ if ((ih != null) && (ih.getInstruction() == this)) {
+ throw new RuntimeException("physicalSuccessor() called on a shared JsrInstruction.");
+ }
+ }
+ // Return the physical successor
+ return toThis.getNext();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * L2D - Convert long to double
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class L2D extends ConversionInstruction {
+
+ public L2D() {
+ super(org.apache.tomcat.util.bcel.Constants.L2D);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitL2D(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * L2F - Convert long to float
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class L2F extends ConversionInstruction {
+
+ public L2F() {
+ super(org.apache.tomcat.util.bcel.Constants.L2F);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitL2F(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * L2I - Convert long to int
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class L2I extends ConversionInstruction {
+
+ public L2I() {
+ super(org.apache.tomcat.util.bcel.Constants.L2I);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitConversionInstruction(this);
+ v.visitL2I(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LADD - Add longs
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LADD extends ArithmeticInstruction {
+
+ public LADD() {
+ super(org.apache.tomcat.util.bcel.Constants.LADD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLADD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LALOAD - Load long from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value1, value2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LALOAD extends ArrayInstruction implements StackProducer {
+
+ /** Load long from array
+ */
+ public LALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.LALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitLALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LAND - Bitwise AND longs
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LAND extends ArithmeticInstruction {
+
+ public LAND() {
+ super(org.apache.tomcat.util.bcel.Constants.LAND);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLAND(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LASTORE - Store into long array
+ * <PRE>Stack: ..., arrayref, index, value.word1, value.word2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LASTORE extends ArrayInstruction implements StackConsumer {
+
+ /** Store long into array
+ */
+ public LASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.LASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitLASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LCMP - Compare longs:
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result <= -1, 0, 1>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
+
+ public LCMP() {
+ super(org.apache.tomcat.util.bcel.Constants.LCMP, (short) 1);
+ }
+
+
+ /** @return Type.LONG
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.LONG;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitLCMP(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LCONST - Push 0 or 1, other values cause an exception
+ *
+ * <PRE>Stack: ... -> ..., </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LCONST extends Instruction implements ConstantPushInstruction, TypedInstruction {
+
+ private long value;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LCONST() {
+ }
+
+
+ public LCONST(long l) {
+ super(org.apache.tomcat.util.bcel.Constants.LCONST_0, (short) 1);
+ if (l == 0) {
+ opcode = org.apache.tomcat.util.bcel.Constants.LCONST_0;
+ } else if (l == 1) {
+ opcode = org.apache.tomcat.util.bcel.Constants.LCONST_1;
+ } else {
+ throw new ClassGenException("LCONST can be used only for 0 and 1: " + l);
+ }
+ value = l;
+ }
+
+
+ public Number getValue() {
+ return new Long(value);
+ }
+
+
+ /** @return Type.LONG
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.LONG;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitLCONST(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * LDC - Push item from constant pool.
+ *
+ * <PRE>Stack: ... -> ..., item</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower,
+ TypedInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LDC() {
+ }
+
+
+ public LDC(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.LDC_W, index);
+ setSize();
+ }
+
+
+ // Adjust to proper size
+ protected final void setSize() {
+ if (index <= org.apache.tomcat.util.bcel.Constants.MAX_BYTE) { // Fits in one byte?
+ opcode = org.apache.tomcat.util.bcel.Constants.LDC;
+ length = 2;
+ } else {
+ opcode = org.apache.tomcat.util.bcel.Constants.LDC_W;
+ length = 3;
+ }
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ if (length == 2) {
+ out.writeByte(index);
+ } else {
+ out.writeShort(index);
+ }
+ }
+
+
+ /**
+ * Set the index to constant pool and adjust size.
+ */
+ public final void setIndex( int index ) {
+ super.setIndex(index);
+ setSize();
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ length = 2;
+ index = bytes.readUnsignedByte();
+ }
+
+
+ public Object getValue( ConstantPoolGen cpg ) {
+ org.apache.tomcat.util.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(index);
+ switch (c.getTag()) {
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_String:
+ int i = ((org.apache.tomcat.util.bcel.classfile.ConstantString) c).getStringIndex();
+ c = cpg.getConstantPool().getConstant(i);
+ return ((org.apache.tomcat.util.bcel.classfile.ConstantUtf8) c).getBytes();
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Float:
+ return new Float(((org.apache.tomcat.util.bcel.classfile.ConstantFloat) c).getBytes());
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Integer:
+ return new Integer(((org.apache.tomcat.util.bcel.classfile.ConstantInteger) c).getBytes());
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Class:
+ return c;
+ default: // Never reached
+ throw new RuntimeException("Unknown or invalid constant type at " + index);
+ }
+ }
+
+
+ public Type getType( ConstantPoolGen cpg ) {
+ switch (cpg.getConstantPool().getConstant(index).getTag()) {
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_String:
+ return Type.STRING;
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Float:
+ return Type.FLOAT;
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Integer:
+ return Type.INT;
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Class:
+ return Type.CLASS;
+ default: // Never reached
+ throw new RuntimeException("Unknown or invalid constant type at " + index);
+ }
+ }
+
+
+ public Class[] getExceptions() {
+ return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_STRING_RESOLUTION;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitLDC(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LDC2_W - Push long or double from constant pool
+ *
+ * <PRE>Stack: ... -> ..., item.word1, item.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LDC2_W extends CPInstruction implements PushInstruction, TypedInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LDC2_W() {
+ }
+
+
+ public LDC2_W(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.LDC2_W, index);
+ }
+
+
+ public Type getType( ConstantPoolGen cpg ) {
+ switch (cpg.getConstantPool().getConstant(index).getTag()) {
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Long:
+ return Type.LONG;
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Double:
+ return Type.DOUBLE;
+ default: // Never reached
+ throw new RuntimeException("Unknown constant type " + opcode);
+ }
+ }
+
+
+ public Number getValue( ConstantPoolGen cpg ) {
+ org.apache.tomcat.util.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(index);
+ switch (c.getTag()) {
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Long:
+ return new Long(((org.apache.tomcat.util.bcel.classfile.ConstantLong) c).getBytes());
+ case org.apache.tomcat.util.bcel.Constants.CONSTANT_Double:
+ return new Double(((org.apache.tomcat.util.bcel.classfile.ConstantDouble) c).getBytes());
+ default: // Never reached
+ throw new RuntimeException("Unknown or invalid constant type at " + index);
+ }
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitLDC2_W(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * LDC_W - Push item from constant pool (wide index)
+ *
+ * <PRE>Stack: ... -> ..., item.word1, item.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LDC_W extends LDC {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LDC_W() {
+ }
+
+
+ public LDC_W(int index) {
+ super(index);
+ }
+
+
+ /**
+ * Read needed data (i.e., index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ setIndex(bytes.readUnsignedShort());
+ // Override just in case it has been changed
+ opcode = org.apache.tomcat.util.bcel.Constants.LDC_W;
+ length = 3;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LDIV - Divide longs
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LDIV extends ArithmeticInstruction implements ExceptionThrower {
+
+ public LDIV() {
+ super(org.apache.tomcat.util.bcel.Constants.LDIV);
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLDIV(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LLOAD - Load long from local variable
+ *<PRE>Stack ... -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LLOAD extends LoadInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LLOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.LLOAD, org.apache.tomcat.util.bcel.Constants.LLOAD_0);
+ }
+
+
+ public LLOAD(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.LLOAD, org.apache.tomcat.util.bcel.Constants.LLOAD_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitLLOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LMUL - Multiply longs
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LMUL extends ArithmeticInstruction {
+
+ public LMUL() {
+ super(org.apache.tomcat.util.bcel.Constants.LMUL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLMUL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LNEG - Negate long
+ * <PRE>Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LNEG extends ArithmeticInstruction {
+
+ public LNEG() {
+ super(org.apache.tomcat.util.bcel.Constants.LNEG);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLNEG(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * LOOKUPSWITCH - Switch with unordered set of values
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see SWITCH
+ */
+public class LOOKUPSWITCH extends Select {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LOOKUPSWITCH() {
+ }
+
+
+ public LOOKUPSWITCH(int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) {
+ super(org.apache.tomcat.util.bcel.Constants.LOOKUPSWITCH, match, targets, defaultTarget);
+ length = (short) (9 + match_length * 8); /* alignment remainder assumed
+ * 0 here, until dump time. */
+ fixed_length = length;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ super.dump(out);
+ out.writeInt(match_length); // npairs
+ for (int i = 0; i < match_length; i++) {
+ out.writeInt(match[i]); // match-offset pairs
+ out.writeInt(indices[i] = getTargetOffset(targets[i]));
+ }
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ super.initFromFile(bytes, wide); // reads padding
+ match_length = bytes.readInt();
+ fixed_length = (short) (9 + match_length * 8);
+ length = (short) (fixed_length + padding);
+ match = new int[match_length];
+ indices = new int[match_length];
+ targets = new InstructionHandle[match_length];
+ for (int i = 0; i < match_length; i++) {
+ match[i] = bytes.readInt();
+ indices[i] = bytes.readInt();
+ }
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitVariableLengthInstruction(this);
+ v.visitStackProducer(this);
+ v.visitBranchInstruction(this);
+ v.visitSelect(this);
+ v.visitLOOKUPSWITCH(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LOR - Bitwise OR long
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LOR extends ArithmeticInstruction {
+
+ public LOR() {
+ super(org.apache.tomcat.util.bcel.Constants.LOR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLOR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LREM - Remainder of long
+ * <PRE>Stack: ..., value1, value2 -> result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LREM extends ArithmeticInstruction implements ExceptionThrower {
+
+ public LREM() {
+ super(org.apache.tomcat.util.bcel.Constants.LREM);
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLREM(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LRETURN - Return long from method
+ * <PRE>Stack: ..., value.word1, value.word2 -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LRETURN extends ReturnInstruction {
+
+ public LRETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.LRETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitLRETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LSHL - Arithmetic shift left long
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LSHL extends ArithmeticInstruction {
+
+ public LSHL() {
+ super(org.apache.tomcat.util.bcel.Constants.LSHL);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLSHL(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LSHR - Arithmetic shift right long
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LSHR extends ArithmeticInstruction {
+
+ public LSHR() {
+ super(org.apache.tomcat.util.bcel.Constants.LSHR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLSHR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LSTORE - Store long into local variable
+ * <PRE>Stack: ..., value.word1, value.word2 -> ... </PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LSTORE extends StoreInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ LSTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.LSTORE, org.apache.tomcat.util.bcel.Constants.LSTORE_0);
+ }
+
+
+ public LSTORE(int n) {
+ super(org.apache.tomcat.util.bcel.Constants.LSTORE, org.apache.tomcat.util.bcel.Constants.LSTORE_0, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ super.accept(v);
+ v.visitLSTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LSUB - Substract longs
+ * <PRE>Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -></PRE>
+ * ..., result.word1, result.word2
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LSUB extends ArithmeticInstruction {
+
+ public LSUB() {
+ super(org.apache.tomcat.util.bcel.Constants.LSUB);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLSUB(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LUSHR - Logical shift right long
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LUSHR extends ArithmeticInstruction {
+
+ public LUSHR() {
+ super(org.apache.tomcat.util.bcel.Constants.LUSHR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLUSHR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * LXOR - Bitwise XOR long
+ * <PRE>Stack: ..., value1, value2 -> ..., result</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class LXOR extends ArithmeticInstruction {
+
+ public LXOR() {
+ super(org.apache.tomcat.util.bcel.Constants.LXOR);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitTypedInstruction(this);
+ v.visitStackProducer(this);
+ v.visitStackConsumer(this);
+ v.visitArithmeticInstruction(this);
+ v.visitLXOR(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.classfile.LineNumber;
+
+/**
+ * This class represents a line number within a method, i.e., give an instruction
+ * a line number corresponding to the source code line.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see LineNumber
+ * @see MethodGen
+ */
+public class LineNumberGen implements InstructionTargeter, Cloneable, java.io.Serializable {
+
+ private InstructionHandle ih;
+ private int src_line;
+
+
+ /**
+ * Create a line number.
+ *
+ * @param ih instruction handle to reference
+ */
+ public LineNumberGen(InstructionHandle ih, int src_line) {
+ setInstruction(ih);
+ setSourceLine(src_line);
+ }
+
+
+ /**
+ * @return true, if ih is target of this line number
+ */
+ public boolean containsTarget( InstructionHandle ih ) {
+ return this.ih == ih;
+ }
+
+
+ /**
+ * @param old_ih old target
+ * @param new_ih new target
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ if (old_ih != ih) {
+ throw new ClassGenException("Not targeting " + old_ih + ", but " + ih + "}");
+ } else {
+ setInstruction(new_ih);
+ }
+ }
+
+
+ /**
+ * Get LineNumber attribute .
+ *
+ * This relies on that the instruction list has already been dumped to byte code or
+ * or that the `setPositions' methods has been called for the instruction list.
+ */
+ public LineNumber getLineNumber() {
+ return new LineNumber(ih.getPosition(), src_line);
+ }
+
+
+ public void setInstruction( InstructionHandle ih ) {
+ BranchInstruction.notifyTarget(this.ih, ih, this);
+ this.ih = ih;
+ }
+
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ return null;
+ }
+ }
+
+
+ public InstructionHandle getInstruction() {
+ return ih;
+ }
+
+
+ public void setSourceLine( int src_line ) {
+ this.src_line = src_line;
+ }
+
+
+ public int getSourceLine() {
+ return src_line;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes that an instruction may start the process of loading and resolving
+ * the referenced class in the Virtual Machine.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface LoadClass {
+
+ /**
+ * Returns the ObjectType of the referenced class or interface
+ * that may be loaded and resolved.
+ * @return object type that may be loaded or null if a primitive is
+ * referenced
+ */
+ public ObjectType getLoadClassType( ConstantPoolGen cpg );
+
+
+ /**
+ * Returns the type associated with this instruction.
+ * LoadClass instances are always typed, but this type
+ * does not always refer to the type of the class or interface
+ * that it possibly forces to load. For example, GETFIELD would
+ * return the type of the field and not the type of the class
+ * where the field is defined.
+ * If no class is forced to be loaded, <B>null</B> is returned.
+ * An example for this is an ANEWARRAY instruction that creates
+ * an int[][].
+ * @see #getLoadClassType(ConstantPoolGen)
+ */
+ public Type getType( ConstantPoolGen cpg );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an unparameterized instruction to load a value from a local
+ * variable, e.g. ILOAD.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class LoadInstruction extends LocalVariableInstruction implements PushInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ * tag and length are defined in readInstruction and initFromFile, respectively.
+ */
+ LoadInstruction(short canon_tag, short c_tag) {
+ super(canon_tag, c_tag);
+ }
+
+
+ /**
+ * @param opcode Instruction opcode
+ * @param c_tag Instruction number for compact version, ALOAD_0, e.g.
+ * @param n local variable index (unsigned short)
+ */
+ protected LoadInstruction(short opcode, short c_tag, int n) {
+ super(opcode, c_tag, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitPushInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitLocalVariableInstruction(this);
+ v.visitLoadInstruction(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.LocalVariable;
+
+/**
+ * This class represents a local variable within a method. It contains its
+ * scope, name and type. The generated LocalVariable object can be obtained
+ * with getLocalVariable which needs the instruction list and the constant
+ * pool as parameters.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see LocalVariable
+ * @see MethodGen
+ */
+public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable,
+ java.io.Serializable {
+
+ private int index;
+ private String name;
+ private Type type;
+ private InstructionHandle start, end;
+
+
+ /**
+ * Generate a local variable that with index `index'. Note that double and long
+ * variables need two indexs. Index indices have to be provided by the user.
+ *
+ * @param index index of local variable
+ * @param name its name
+ * @param type its type
+ * @param start from where the instruction is valid (null means from the start)
+ * @param end until where the instruction is valid (null means to the end)
+ */
+ public LocalVariableGen(int index, String name, Type type, InstructionHandle start,
+ InstructionHandle end) {
+ if ((index < 0) || (index > Constants.MAX_SHORT)) {
+ throw new ClassGenException("Invalid index index: " + index);
+ }
+ this.name = name;
+ this.type = type;
+ this.index = index;
+ setStart(start);
+ setEnd(end);
+ }
+
+
+ /**
+ * Get LocalVariable object.
+ *
+ * This relies on that the instruction list has already been dumped to byte code or
+ * or that the `setPositions' methods has been called for the instruction list.
+ *
+ * Note that for local variables whose scope end at the last
+ * instruction of the method's code, the JVM specification is ambiguous:
+ * both a start_pc+length ending at the last instruction and
+ * start_pc+length ending at first index beyond the end of the code are
+ * valid.
+ *
+ * @param cp constant pool
+ */
+ public LocalVariable getLocalVariable( ConstantPoolGen cp ) {
+ int start_pc = start.getPosition();
+ int length = end.getPosition() - start_pc;
+ if (length > 0) {
+ length += end.getInstruction().getLength();
+ }
+ int name_index = cp.addUtf8(name);
+ int signature_index = cp.addUtf8(type.getSignature());
+ return new LocalVariable(start_pc, length, name_index, signature_index, index, cp
+ .getConstantPool());
+ }
+
+
+ public void setIndex( int index ) {
+ this.index = index;
+ }
+
+
+ public int getIndex() {
+ return index;
+ }
+
+
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+
+ public void setType( Type type ) {
+ this.type = type;
+ }
+
+
+ public Type getType() {
+ return type;
+ }
+
+
+ public InstructionHandle getStart() {
+ return start;
+ }
+
+
+ public InstructionHandle getEnd() {
+ return end;
+ }
+
+
+ public void setStart( InstructionHandle start ) {
+ BranchInstruction.notifyTarget(this.start, start, this);
+ this.start = start;
+ }
+
+
+ public void setEnd( InstructionHandle end ) {
+ BranchInstruction.notifyTarget(this.end, end, this);
+ this.end = end;
+ }
+
+
+ /**
+ * @param old_ih old target, either start or end
+ * @param new_ih new target
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ boolean targeted = false;
+ if (start == old_ih) {
+ targeted = true;
+ setStart(new_ih);
+ }
+ if (end == old_ih) {
+ targeted = true;
+ setEnd(new_ih);
+ }
+ if (!targeted) {
+ throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end
+ + "}");
+ }
+ }
+
+
+ /**
+ * @return true, if ih is target of this variable
+ */
+ public boolean containsTarget( InstructionHandle ih ) {
+ return (start == ih) || (end == ih);
+ }
+
+
+ /** @return a hash code value for the object.
+ */
+ public int hashCode() {
+ //If the user changes the name or type, problems with the targeter hashmap will occur
+ int hc = index ^ name.hashCode() ^ type.hashCode();
+ return hc;
+ }
+
+
+ /**
+ * We consider to local variables to be equal, if the use the same index and
+ * are valid in the same range.
+ */
+ public boolean equals( Object o ) {
+ if (!(o instanceof LocalVariableGen)) {
+ return false;
+ }
+ LocalVariableGen l = (LocalVariableGen) o;
+ return (l.index == index) && (l.start == start) && (l.end == end);
+ }
+
+
+ public String toString() {
+ return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")";
+ }
+
+
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ System.err.println(e);
+ return null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Abstract super class for instructions dealing with local variables.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction,
+ IndexedInstruction {
+
+ protected int n = -1; // index of referenced variable
+ private short c_tag = -1; // compact version, such as ILOAD_0
+ private short canon_tag = -1; // canonical tag such as ILOAD
+
+
+ private final boolean wide() {
+ return n > Constants.MAX_BYTE;
+ }
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ * tag and length are defined in readInstruction and initFromFile, respectively.
+ */
+ LocalVariableInstruction(short canon_tag, short c_tag) {
+ super();
+ this.canon_tag = canon_tag;
+ this.c_tag = c_tag;
+ }
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Also used by IINC()!
+ */
+ LocalVariableInstruction() {
+ }
+
+
+ /**
+ * @param opcode Instruction opcode
+ * @param c_tag Instruction number for compact version, ALOAD_0, e.g.
+ * @param n local variable index (unsigned short)
+ */
+ protected LocalVariableInstruction(short opcode, short c_tag, int n) {
+ super(opcode, (short) 2);
+ this.c_tag = c_tag;
+ canon_tag = opcode;
+ setIndex(n);
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ if (wide()) {
+ out.writeByte(Constants.WIDE);
+ }
+ out.writeByte(opcode);
+ if (length > 1) { // Otherwise ILOAD_n, instruction, e.g.
+ if (wide()) {
+ out.writeShort(n);
+ } else {
+ out.writeByte(n);
+ }
+ }
+ }
+
+
+ /**
+ * Long output format:
+ *
+ * <name of opcode> "["<opcode number>"]"
+ * "("<length of instruction>")" "<"< local variable index>">"
+ *
+ * @param verbose long/short format switch
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ if (((opcode >= Constants.ILOAD_0) && (opcode <= Constants.ALOAD_3))
+ || ((opcode >= Constants.ISTORE_0) && (opcode <= Constants.ASTORE_3))) {
+ return super.toString(verbose);
+ } else {
+ return super.toString(verbose) + " " + n;
+ }
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ * PRE: (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3)
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ if (wide) {
+ n = bytes.readUnsignedShort();
+ length = 4;
+ } else if (((opcode >= Constants.ILOAD) && (opcode <= Constants.ALOAD))
+ || ((opcode >= Constants.ISTORE) && (opcode <= Constants.ASTORE))) {
+ n = bytes.readUnsignedByte();
+ length = 2;
+ } else if (opcode <= Constants.ALOAD_3) { // compact load instruction such as ILOAD_2
+ n = (opcode - Constants.ILOAD_0) % 4;
+ length = 1;
+ } else { // Assert ISTORE_0 <= tag <= ASTORE_3
+ n = (opcode - Constants.ISTORE_0) % 4;
+ length = 1;
+ }
+ }
+
+
+ /**
+ * @return local variable index referred by this instruction.
+ */
+ public final int getIndex() {
+ return n;
+ }
+
+
+ /**
+ * Set the local variable index
+ */
+ public void setIndex( int n ) {
+ if ((n < 0) || (n > Constants.MAX_SHORT)) {
+ throw new ClassGenException("Illegal value: " + n);
+ }
+ this.n = n;
+ if (n >= 0 && n <= 3) { // Use more compact instruction xLOAD_n
+ opcode = (short) (c_tag + n);
+ length = 1;
+ } else {
+ opcode = canon_tag;
+ if (wide()) {
+ length = 4;
+ } else {
+ length = 2;
+ }
+ }
+ }
+
+
+ /** @return canonical tag for instruction, e.g., ALOAD for ALOAD_0
+ */
+ public short getCanonicalTag() {
+ return canon_tag;
+ }
+
+
+ /**
+ * Returns the type associated with the instruction -
+ * in case of ALOAD or ASTORE Type.OBJECT is returned.
+ * This is just a bit incorrect, because ALOAD and ASTORE
+ * may work on every ReferenceType (including Type.NULL) and
+ * ASTORE may even work on a ReturnaddressType .
+ * @return type associated with the instruction
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ switch (canon_tag) {
+ case Constants.ILOAD:
+ case Constants.ISTORE:
+ return Type.INT;
+ case Constants.LLOAD:
+ case Constants.LSTORE:
+ return Type.LONG;
+ case Constants.DLOAD:
+ case Constants.DSTORE:
+ return Type.DOUBLE;
+ case Constants.FLOAD:
+ case Constants.FSTORE:
+ return Type.FLOAT;
+ case Constants.ALOAD:
+ case Constants.ASTORE:
+ return Type.OBJECT;
+ default:
+ throw new ClassGenException("Oops: unknown case in switch" + canon_tag);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * MONITORENTER - Enter monitor for object
+ * <PRE>Stack: ..., objectref -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class MONITORENTER extends Instruction implements ExceptionThrower, StackConsumer {
+
+ public MONITORENTER() {
+ super(org.apache.tomcat.util.bcel.Constants.MONITORENTER, (short) 1);
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
+ v.visitMONITORENTER(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * MONITOREXIT - Exit monitor for object
+ * <PRE>Stack: ..., objectref -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class MONITOREXIT extends Instruction implements ExceptionThrower, StackConsumer {
+
+ public MONITOREXIT() {
+ super(org.apache.tomcat.util.bcel.Constants.MONITOREXIT, (short) 1);
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
+ v.visitMONITOREXIT(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * MULTIANEWARRAY - Create new mutidimensional array of references
+ * <PRE>Stack: ..., count1, [count2, ...] -> ..., arrayref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction,
+ ExceptionThrower {
+
+ private short dimensions;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ MULTIANEWARRAY() {
+ }
+
+
+ public MULTIANEWARRAY(int index, short dimensions) {
+ super(org.apache.tomcat.util.bcel.Constants.MULTIANEWARRAY, index);
+ if (dimensions < 1) {
+ throw new ClassGenException("Invalid dimensions value: " + dimensions);
+ }
+ this.dimensions = dimensions;
+ length = 4;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ out.writeShort(index);
+ out.writeByte(dimensions);
+ }
+
+
+ /**
+ * Read needed data (i.e., no. dimension) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ super.initFromFile(bytes, wide);
+ dimensions = bytes.readByte();
+ length = 4;
+ }
+
+
+ /**
+ * @return number of dimensions to be created
+ */
+ public final short getDimensions() {
+ return dimensions;
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + index + " " + dimensions;
+ }
+
+
+ /**
+ * @return mnemonic for instruction with symbolic references resolved
+ */
+ public String toString( ConstantPool cp ) {
+ return super.toString(cp) + " " + dimensions;
+ }
+
+
+ /**
+ * Also works for instructions whose stack effect depends on the
+ * constant pool entry they reference.
+ * @return Number of words consumed from stack by this instruction
+ */
+ public int consumeStack( ConstantPoolGen cpg ) {
+ return dimensions;
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION;
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
+ return cs;
+ }
+
+
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ Type t = getType(cpg);
+ if (t instanceof ArrayType) {
+ t = ((ArrayType) t).getBasicType();
+ }
+ return (t instanceof ObjectType) ? (ObjectType) t : null;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLoadClass(this);
+ v.visitAllocationInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitMULTIANEWARRAY(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.AnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.Annotations;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Code;
+import org.apache.tomcat.util.bcel.classfile.CodeException;
+import org.apache.tomcat.util.bcel.classfile.ExceptionTable;
+import org.apache.tomcat.util.bcel.classfile.LineNumber;
+import org.apache.tomcat.util.bcel.classfile.LineNumberTable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariableTable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariableTypeTable;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.ParameterAnnotationEntry;
+import org.apache.tomcat.util.bcel.classfile.ParameterAnnotations;
+import org.apache.tomcat.util.bcel.classfile.RuntimeVisibleParameterAnnotations;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+import org.apache.tomcat.util.bcel.util.BCELComparator;
+
+/**
+ * Template class for building up a method. This is done by defining exception
+ * handlers, adding thrown exceptions, local variables and attributes, whereas
+ * the `LocalVariableTable' and `LineNumberTable' attributes will be set
+ * automatically for the code. Use stripAttributes() if you don't like this.
+ *
+ * While generating code it may be necessary to insert NOP operations. You can
+ * use the `removeNOPs' method to get rid off them.
+ * The resulting method object can be obtained via the `getMethod()' method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @author <A HREF="http://www.vmeng.com/beard">Patrick C. Beard</A> [setMaxStack()]
+ * @see InstructionList
+ * @see Method
+ */
+public class MethodGen extends FieldGenOrMethodGen {
+
+ private String class_name;
+ private Type[] arg_types;
+ private String[] arg_names;
+ private int max_locals;
+ private int max_stack;
+ private InstructionList il;
+ private boolean strip_attributes;
+ private List variable_vec = new ArrayList();
+ private List line_number_vec = new ArrayList();
+ private List exception_vec = new ArrayList();
+ private List throws_vec = new ArrayList();
+ private List code_attrs_vec = new ArrayList();
+
+ private List[] param_annotations; // Array of lists containing AnnotationGen objects
+ private boolean hasParameterAnnotations = false;
+ private boolean haveUnpackedParameterAnnotations = false;
+
+ private static BCELComparator _cmp = new BCELComparator() {
+
+ public boolean equals( Object o1, Object o2 ) {
+ MethodGen THIS = (MethodGen) o1;
+ MethodGen THAT = (MethodGen) o2;
+ return THIS.getName().equals(THAT.getName())
+ && THIS.getSignature().equals(THAT.getSignature());
+ }
+
+
+ public int hashCode( Object o ) {
+ MethodGen THIS = (MethodGen) o;
+ return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ }
+ };
+
+
+ /**
+ * Declare method. If the method is non-static the constructor
+ * automatically declares a local variable `$this' in slot 0. The
+ * actual code is contained in the `il' parameter, which may further
+ * manipulated by the user. But he must take care not to remove any
+ * instruction (handles) that are still referenced from this object.
+ *
+ * For example one may not add a local variable and later remove the
+ * instructions it refers to without causing havoc. It is safe
+ * however if you remove that local variable, too.
+ *
+ * @param access_flags access qualifiers
+ * @param return_type method type
+ * @param arg_types argument types
+ * @param arg_names argument names (if this is null, default names will be provided
+ * for them)
+ * @param method_name name of method
+ * @param class_name class name containing this method (may be null, if you don't care)
+ * @param il instruction list associated with this method, may be null only for
+ * abstract or native methods
+ * @param cp constant pool
+ */
+ public MethodGen(int access_flags, Type return_type, Type[] arg_types, String[] arg_names,
+ String method_name, String class_name, InstructionList il, ConstantPoolGen cp) {
+ setAccessFlags(access_flags);
+ setType(return_type);
+ setArgumentTypes(arg_types);
+ setArgumentNames(arg_names);
+ setName(method_name);
+ setClassName(class_name);
+ setInstructionList(il);
+ setConstantPool(cp);
+ boolean abstract_ = isAbstract() || isNative();
+ InstructionHandle start = null;
+ InstructionHandle end = null;
+ if (!abstract_) {
+ start = il.getStart();
+ end = il.getEnd();
+ /* Add local variables, namely the implicit `this' and the arguments
+ */
+ if (!isStatic() && (class_name != null)) { // Instance method -> `this' is local var 0
+ addLocalVariable("this", new ObjectType(class_name), start, end);
+ }
+ }
+ if (arg_types != null) {
+ int size = arg_types.length;
+ for (int i = 0; i < size; i++) {
+ if (Type.VOID == arg_types[i]) {
+ throw new ClassGenException("'void' is an illegal argument type for a method");
+ }
+ }
+ if (arg_names != null) { // Names for variables provided?
+ if (size != arg_names.length) {
+ throw new ClassGenException("Mismatch in argument array lengths: " + size
+ + " vs. " + arg_names.length);
+ }
+ } else { // Give them dummy names
+ arg_names = new String[size];
+ for (int i = 0; i < size; i++) {
+ arg_names[i] = "arg" + i;
+ }
+ setArgumentNames(arg_names);
+ }
+ if (!abstract_) {
+ for (int i = 0; i < size; i++) {
+ addLocalVariable(arg_names[i], arg_types[i], start, end);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Instantiate from existing method.
+ *
+ * @param m method
+ * @param class_name class name containing this method
+ * @param cp constant pool
+ */
+ public MethodGen(Method m, String class_name, ConstantPoolGen cp) {
+ this(m.getAccessFlags(), Type.getReturnType(m.getSignature()), Type.getArgumentTypes(m
+ .getSignature()), null /* may be overridden anyway */
+ , m.getName(), class_name,
+ ((m.getAccessFlags() & (Constants.ACC_ABSTRACT | Constants.ACC_NATIVE)) == 0)
+ ? new InstructionList(m.getCode().getCode())
+ : null, cp);
+ Attribute[] attributes = m.getAttributes();
+ for (int i = 0; i < attributes.length; i++) {
+ Attribute a = attributes[i];
+ if (a instanceof Code) {
+ Code c = (Code) a;
+ setMaxStack(c.getMaxStack());
+ setMaxLocals(c.getMaxLocals());
+ CodeException[] ces = c.getExceptionTable();
+ if (ces != null) {
+ for (int j = 0; j < ces.length; j++) {
+ CodeException ce = ces[j];
+ int type = ce.getCatchType();
+ ObjectType c_type = null;
+ if (type > 0) {
+ String cen = m.getConstantPool().getConstantString(type,
+ Constants.CONSTANT_Class);
+ c_type = new ObjectType(cen);
+ }
+ int end_pc = ce.getEndPC();
+ int length = m.getCode().getCode().length;
+ InstructionHandle end;
+ if (length == end_pc) { // May happen, because end_pc is exclusive
+ end = il.getEnd();
+ } else {
+ end = il.findHandle(end_pc);
+ end = end.getPrev(); // Make it inclusive
+ }
+ addExceptionHandler(il.findHandle(ce.getStartPC()), end, il.findHandle(ce
+ .getHandlerPC()), c_type);
+ }
+ }
+ Attribute[] c_attributes = c.getAttributes();
+ for (int j = 0; j < c_attributes.length; j++) {
+ a = c_attributes[j];
+ if (a instanceof LineNumberTable) {
+ LineNumber[] ln = ((LineNumberTable) a).getLineNumberTable();
+ for (int k = 0; k < ln.length; k++) {
+ LineNumber l = ln[k];
+ InstructionHandle ih = il.findHandle(l.getStartPC());
+ if (ih != null) {
+ addLineNumber(ih, l.getLineNumber());
+ }
+ }
+ } else if (a instanceof LocalVariableTable) {
+ LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable();
+ removeLocalVariables();
+ for (int k = 0; k < lv.length; k++) {
+ LocalVariable l = lv[k];
+ InstructionHandle start = il.findHandle(l.getStartPC());
+ InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
+ // Repair malformed handles
+ if (null == start) {
+ start = il.getStart();
+ }
+ if (null == end) {
+ end = il.getEnd();
+ }
+ addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
+ .getIndex(), start, end);
+ }
+ } else if (a instanceof LocalVariableTypeTable) {
+ LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
+ removeLocalVariables();
+ for (int k = 0; k < lv.length; k++) {
+ LocalVariable l = lv[k];
+ InstructionHandle start = il.findHandle(l.getStartPC());
+ InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
+ // Repair malformed handles
+ if (null == start) {
+ start = il.getStart();
+ }
+ if (null == end) {
+ end = il.getEnd();
+ }
+ addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
+ .getIndex(), start, end);
+ }
+ } else {
+ addCodeAttribute(a);
+ }
+ }
+ } else if (a instanceof ExceptionTable) {
+ String[] names = ((ExceptionTable) a).getExceptionNames();
+ for (int j = 0; j < names.length; j++) {
+ addException(names[j]);
+ }
+ } else if (a instanceof Annotations) {
+ Annotations runtimeAnnotations = (Annotations) a;
+ AnnotationEntry[] aes = runtimeAnnotations.getAnnotationEntries();
+ for (int k = 0; k < aes.length; k++) {
+ AnnotationEntry element = aes[k];
+ addAnnotationEntry(new AnnotationEntryGen(element, cp, false));
+ }
+ } else {
+ addAttribute(a);
+ }
+ }
+ }
+
+
+ /**
+ * Adds a local variable to this method.
+ *
+ * @param name variable name
+ * @param type variable type
+ * @param slot the index of the local variable, if type is long or double, the next available
+ * index is slot+2
+ * @param start from where the variable is valid
+ * @param end until where the variable is valid
+ * @return new local variable object
+ * @see LocalVariable
+ */
+ public LocalVariableGen addLocalVariable( String name, Type type, int slot,
+ InstructionHandle start, InstructionHandle end ) {
+ byte t = type.getType();
+ if (t != Constants.T_ADDRESS) {
+ int add = type.getSize();
+ if (slot + add > max_locals) {
+ max_locals = slot + add;
+ }
+ LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end);
+ int i;
+ if ((i = variable_vec.indexOf(l)) >= 0) {
+ variable_vec.set(i, l);
+ } else {
+ variable_vec.add(l);
+ }
+ return l;
+ } else {
+ throw new IllegalArgumentException("Can not use " + type
+ + " as type for local variable");
+ }
+ }
+
+
+ /**
+ * Adds a local variable to this method and assigns an index automatically.
+ *
+ * @param name variable name
+ * @param type variable type
+ * @param start from where the variable is valid, if this is null,
+ * it is valid from the start
+ * @param end until where the variable is valid, if this is null,
+ * it is valid to the end
+ * @return new local variable object
+ * @see LocalVariable
+ */
+ public LocalVariableGen addLocalVariable( String name, Type type, InstructionHandle start,
+ InstructionHandle end ) {
+ return addLocalVariable(name, type, max_locals, start, end);
+ }
+
+
+ /**
+ * Remove a local variable, its slot will not be reused, if you do not use addLocalVariable
+ * with an explicit index argument.
+ */
+ public void removeLocalVariable( LocalVariableGen l ) {
+ variable_vec.remove(l);
+ }
+
+
+ /**
+ * Remove all local variables.
+ */
+ public void removeLocalVariables() {
+ variable_vec.clear();
+ }
+
+
+ /**
+ * Sort local variables by index
+ */
+ private static final void sort( LocalVariableGen[] vars, int l, int r ) {
+ int i = l, j = r;
+ int m = vars[(l + r) / 2].getIndex();
+ LocalVariableGen h;
+ do {
+ while (vars[i].getIndex() < m) {
+ i++;
+ }
+ while (m < vars[j].getIndex()) {
+ j--;
+ }
+ if (i <= j) {
+ h = vars[i];
+ vars[i] = vars[j];
+ vars[j] = h; // Swap elements
+ i++;
+ j--;
+ }
+ } while (i <= j);
+ if (l < j) {
+ sort(vars, l, j);
+ }
+ if (i < r) {
+ sort(vars, i, r);
+ }
+ }
+
+
+ /*
+ * If the range of the variable has not been set yet, it will be set to be valid from
+ * the start to the end of the instruction list.
+ *
+ * @return array of declared local variables sorted by index
+ */
+ public LocalVariableGen[] getLocalVariables() {
+ int size = variable_vec.size();
+ LocalVariableGen[] lg = new LocalVariableGen[size];
+ variable_vec.toArray(lg);
+ for (int i = 0; i < size; i++) {
+ if (lg[i].getStart() == null) {
+ lg[i].setStart(il.getStart());
+ }
+ if (lg[i].getEnd() == null) {
+ lg[i].setEnd(il.getEnd());
+ }
+ }
+ if (size > 1) {
+ sort(lg, 0, size - 1);
+ }
+ return lg;
+ }
+
+
+ /**
+ * @return `LocalVariableTable' attribute of all the local variables of this method.
+ */
+ public LocalVariableTable getLocalVariableTable( ConstantPoolGen cp ) {
+ LocalVariableGen[] lg = getLocalVariables();
+ int size = lg.length;
+ LocalVariable[] lv = new LocalVariable[size];
+ for (int i = 0; i < size; i++) {
+ lv[i] = lg[i].getLocalVariable(cp);
+ }
+ return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp
+ .getConstantPool());
+ }
+
+
+ /**
+ * Give an instruction a line number corresponding to the source code line.
+ *
+ * @param ih instruction to tag
+ * @return new line number object
+ * @see LineNumber
+ */
+ public LineNumberGen addLineNumber( InstructionHandle ih, int src_line ) {
+ LineNumberGen l = new LineNumberGen(ih, src_line);
+ line_number_vec.add(l);
+ return l;
+ }
+
+
+ /**
+ * Remove a line number.
+ */
+ public void removeLineNumber( LineNumberGen l ) {
+ line_number_vec.remove(l);
+ }
+
+
+ /**
+ * Remove all line numbers.
+ */
+ public void removeLineNumbers() {
+ line_number_vec.clear();
+ }
+
+
+ /*
+ * @return array of line numbers
+ */
+ public LineNumberGen[] getLineNumbers() {
+ LineNumberGen[] lg = new LineNumberGen[line_number_vec.size()];
+ line_number_vec.toArray(lg);
+ return lg;
+ }
+
+
+ /**
+ * @return `LineNumberTable' attribute of all the local variables of this method.
+ */
+ public LineNumberTable getLineNumberTable( ConstantPoolGen cp ) {
+ int size = line_number_vec.size();
+ LineNumber[] ln = new LineNumber[size];
+ try {
+ for (int i = 0; i < size; i++) {
+ ln[i] = ((LineNumberGen) line_number_vec.get(i)).getLineNumber();
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ } // Never occurs
+ return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp
+ .getConstantPool());
+ }
+
+
+ /**
+ * Add an exception handler, i.e., specify region where a handler is active and an
+ * instruction where the actual handling is done.
+ *
+ * @param start_pc Start of region (inclusive)
+ * @param end_pc End of region (inclusive)
+ * @param handler_pc Where handling is done
+ * @param catch_type class type of handled exception or null if any
+ * exception is handled
+ * @return new exception handler object
+ */
+ public CodeExceptionGen addExceptionHandler( InstructionHandle start_pc,
+ InstructionHandle end_pc, InstructionHandle handler_pc, ObjectType catch_type ) {
+ if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) {
+ throw new ClassGenException("Exception handler target is null instruction");
+ }
+ CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc, catch_type);
+ exception_vec.add(c);
+ return c;
+ }
+
+
+ /**
+ * Remove an exception handler.
+ */
+ public void removeExceptionHandler( CodeExceptionGen c ) {
+ exception_vec.remove(c);
+ }
+
+
+ /**
+ * Remove all line numbers.
+ */
+ public void removeExceptionHandlers() {
+ exception_vec.clear();
+ }
+
+
+ /*
+ * @return array of declared exception handlers
+ */
+ public CodeExceptionGen[] getExceptionHandlers() {
+ CodeExceptionGen[] cg = new CodeExceptionGen[exception_vec.size()];
+ exception_vec.toArray(cg);
+ return cg;
+ }
+
+
+ /**
+ * @return code exceptions for `Code' attribute
+ */
+ private CodeException[] getCodeExceptions() {
+ int size = exception_vec.size();
+ CodeException[] c_exc = new CodeException[size];
+ try {
+ for (int i = 0; i < size; i++) {
+ CodeExceptionGen c = (CodeExceptionGen) exception_vec.get(i);
+ c_exc[i] = c.getCodeException(cp);
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ }
+ return c_exc;
+ }
+
+
+ /**
+ * Add an exception possibly thrown by this method.
+ *
+ * @param class_name (fully qualified) name of exception
+ */
+ public void addException( String class_name ) {
+ throws_vec.add(class_name);
+ }
+
+
+ /**
+ * Remove an exception.
+ */
+ public void removeException( String c ) {
+ throws_vec.remove(c);
+ }
+
+
+ /**
+ * Remove all exceptions.
+ */
+ public void removeExceptions() {
+ throws_vec.clear();
+ }
+
+
+ /*
+ * @return array of thrown exceptions
+ */
+ public String[] getExceptions() {
+ String[] e = new String[throws_vec.size()];
+ throws_vec.toArray(e);
+ return e;
+ }
+
+
+ /**
+ * @return `Exceptions' attribute of all the exceptions thrown by this method.
+ */
+ private ExceptionTable getExceptionTable( ConstantPoolGen cp ) {
+ int size = throws_vec.size();
+ int[] ex = new int[size];
+ try {
+ for (int i = 0; i < size; i++) {
+ ex[i] = cp.addClass((String) throws_vec.get(i));
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ }
+ return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex, cp.getConstantPool());
+ }
+
+
+ /**
+ * Add an attribute to the code. Currently, the JVM knows about the
+ * LineNumberTable, LocalVariableTable and StackMap attributes,
+ * where the former two will be generated automatically and the
+ * latter is used for the MIDP only. Other attributes will be
+ * ignored by the JVM but do no harm.
+ *
+ * @param a attribute to be added
+ */
+ public void addCodeAttribute( Attribute a ) {
+ code_attrs_vec.add(a);
+ }
+
+
+ /**
+ * Remove a code attribute.
+ */
+ public void removeCodeAttribute( Attribute a ) {
+ code_attrs_vec.remove(a);
+ }
+
+
+ /**
+ * Remove all code attributes.
+ */
+ public void removeCodeAttributes() {
+ code_attrs_vec.clear();
+ }
+
+
+ /**
+ * @return all attributes of this method.
+ */
+ public Attribute[] getCodeAttributes() {
+ Attribute[] attributes = new Attribute[code_attrs_vec.size()];
+ code_attrs_vec.toArray(attributes);
+ return attributes;
+ }
+
+ public void addAnnotationsAsAttribute(ConstantPoolGen cp) {
+ Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotation_vec);
+ for (int i = 0; i < attrs.length; i++) {
+ addAttribute(attrs[i]);
+ }
+ }
+
+ public void addParameterAnnotationsAsAttribute(ConstantPoolGen cp) {
+ if (!hasParameterAnnotations) return;
+ Attribute[] attrs = Utility.getParameterAnnotationAttributes(cp,param_annotations);
+ if (attrs!=null) {
+ for (int i = 0; i < attrs.length; i++) {
+ addAttribute(attrs[i]);
+ }
+ }
+ }
+
+
+ /**
+ * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively,
+ * before calling this method (the same applies for max locals).
+ *
+ * @return method object
+ */
+ public Method getMethod() {
+ String signature = getSignature();
+ int name_index = cp.addUtf8(name);
+ int signature_index = cp.addUtf8(signature);
+ /* Also updates positions of instructions, i.e., their indices
+ */
+ byte[] byte_code = null;
+ if (il != null) {
+ byte_code = il.getByteCode();
+ }
+ LineNumberTable lnt = null;
+ LocalVariableTable lvt = null;
+ /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.)
+ */
+ if ((variable_vec.size() > 0) && !strip_attributes) {
+ addCodeAttribute(lvt = getLocalVariableTable(cp));
+ }
+ if ((line_number_vec.size() > 0) && !strip_attributes) {
+ addCodeAttribute(lnt = getLineNumberTable(cp));
+ }
+ Attribute[] code_attrs = getCodeAttributes();
+ /* Each attribute causes 6 additional header bytes
+ */
+ int attrs_len = 0;
+ for (int i = 0; i < code_attrs.length; i++) {
+ attrs_len += (code_attrs[i].getLength() + 6);
+ }
+ CodeException[] c_exc = getCodeExceptions();
+ int exc_len = c_exc.length * 8; // Every entry takes 8 bytes
+ Code code = null;
+ if ((il != null) && !isAbstract() && !isNative()) {
+ // Remove any stale code attribute
+ Attribute[] attributes = getAttributes();
+ for (int i = 0; i < attributes.length; i++) {
+ Attribute a = attributes[i];
+ if (a instanceof Code) {
+ removeAttribute(a);
+ }
+ }
+ code = new Code(cp.addUtf8("Code"), 8 + byte_code.length + // prologue byte code
+ 2 + exc_len + // exceptions
+ 2 + attrs_len, // attributes
+ max_stack, max_locals, byte_code, c_exc, code_attrs, cp.getConstantPool());
+ addAttribute(code);
+ }
+ addAnnotationsAsAttribute(cp);
+ addParameterAnnotationsAsAttribute(cp);
+ ExceptionTable et = null;
+ if (throws_vec.size() > 0) {
+ addAttribute(et = getExceptionTable(cp));
+ // Add `Exceptions' if there are "throws" clauses
+ }
+ Method m = new Method(access_flags, name_index, signature_index, getAttributes(), cp
+ .getConstantPool());
+ // Undo effects of adding attributes
+ if (lvt != null) {
+ removeCodeAttribute(lvt);
+ }
+ if (lnt != null) {
+ removeCodeAttribute(lnt);
+ }
+ if (code != null) {
+ removeAttribute(code);
+ }
+ if (et != null) {
+ removeAttribute(et);
+ }
+ return m;
+ }
+
+
+ /**
+ * Remove all NOPs from the instruction list (if possible) and update every
+ * object refering to them, i.e., branch instructions, local variables and
+ * exception handlers.
+ */
+ public void removeNOPs() {
+ if (il != null) {
+ InstructionHandle next;
+ /* Check branch instructions.
+ */
+ for (InstructionHandle ih = il.getStart(); ih != null; ih = next) {
+ next = ih.next;
+ if ((next != null) && (ih.getInstruction() instanceof NOP)) {
+ try {
+ il.delete(ih);
+ } catch (TargetLostException e) {
+ InstructionHandle[] targets = e.getTargets();
+ for (int i = 0; i < targets.length; i++) {
+ InstructionTargeter[] targeters = targets[i].getTargeters();
+ for (int j = 0; j < targeters.length; j++) {
+ targeters[j].updateTarget(targets[i], next);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Set maximum number of local variables.
+ */
+ public void setMaxLocals( int m ) {
+ max_locals = m;
+ }
+
+
+ public int getMaxLocals() {
+ return max_locals;
+ }
+
+
+ /**
+ * Set maximum stack size for this method.
+ */
+ public void setMaxStack( int m ) {
+ max_stack = m;
+ }
+
+
+ public int getMaxStack() {
+ return max_stack;
+ }
+
+
+ /** @return class that contains this method
+ */
+ public String getClassName() {
+ return class_name;
+ }
+
+
+ public void setClassName( String class_name ) {
+ this.class_name = class_name;
+ }
+
+
+ public void setReturnType( Type return_type ) {
+ setType(return_type);
+ }
+
+
+ public Type getReturnType() {
+ return getType();
+ }
+
+
+ public void setArgumentTypes( Type[] arg_types ) {
+ this.arg_types = arg_types;
+ }
+
+
+ public Type[] getArgumentTypes() {
+ return (Type[]) arg_types.clone();
+ }
+
+
+ public void setArgumentType( int i, Type type ) {
+ arg_types[i] = type;
+ }
+
+
+ public Type getArgumentType( int i ) {
+ return arg_types[i];
+ }
+
+
+ public void setArgumentNames( String[] arg_names ) {
+ this.arg_names = arg_names;
+ }
+
+
+ public String[] getArgumentNames() {
+ return (String[]) arg_names.clone();
+ }
+
+
+ public void setArgumentName( int i, String name ) {
+ arg_names[i] = name;
+ }
+
+
+ public String getArgumentName( int i ) {
+ return arg_names[i];
+ }
+
+
+ public InstructionList getInstructionList() {
+ return il;
+ }
+
+
+ public void setInstructionList( InstructionList il ) {
+ this.il = il;
+ }
+
+
+ public String getSignature() {
+ return Type.getMethodSignature(type, arg_types);
+ }
+
+
+ /**
+ * Computes max. stack size by performing control flow analysis.
+ */
+ public void setMaxStack() {
+ if (il != null) {
+ max_stack = getMaxStack(cp, il, getExceptionHandlers());
+ } else {
+ max_stack = 0;
+ }
+ }
+
+
+ /**
+ * Compute maximum number of local variables.
+ */
+ public void setMaxLocals() {
+ if (il != null) {
+ int max = isStatic() ? 0 : 1;
+ if (arg_types != null) {
+ for (int i = 0; i < arg_types.length; i++) {
+ max += arg_types[i].getSize();
+ }
+ }
+ for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
+ Instruction ins = ih.getInstruction();
+ if ((ins instanceof LocalVariableInstruction) || (ins instanceof RET)
+ || (ins instanceof IINC)) {
+ int index = ((IndexedInstruction) ins).getIndex()
+ + ((TypedInstruction) ins).getType(cp).getSize();
+ if (index > max) {
+ max = index;
+ }
+ }
+ }
+ max_locals = max;
+ } else {
+ max_locals = 0;
+ }
+ }
+
+
+ /** Do not/Do produce attributes code attributesLineNumberTable and
+ * LocalVariableTable, like javac -O
+ */
+ public void stripAttributes( boolean flag ) {
+ strip_attributes = flag;
+ }
+
+ static final class BranchTarget {
+
+ InstructionHandle target;
+ int stackDepth;
+
+
+ BranchTarget(InstructionHandle target, int stackDepth) {
+ this.target = target;
+ this.stackDepth = stackDepth;
+ }
+ }
+
+ static final class BranchStack {
+
+ Stack branchTargets = new Stack();
+ Hashtable visitedTargets = new Hashtable();
+
+
+ public void push( InstructionHandle target, int stackDepth ) {
+ if (visited(target)) {
+ return;
+ }
+ branchTargets.push(visit(target, stackDepth));
+ }
+
+
+ public BranchTarget pop() {
+ if (!branchTargets.empty()) {
+ BranchTarget bt = (BranchTarget) branchTargets.pop();
+ return bt;
+ }
+ return null;
+ }
+
+
+ private final BranchTarget visit( InstructionHandle target, int stackDepth ) {
+ BranchTarget bt = new BranchTarget(target, stackDepth);
+ visitedTargets.put(target, bt);
+ return bt;
+ }
+
+
+ private final boolean visited( InstructionHandle target ) {
+ return (visitedTargets.get(target) != null);
+ }
+ }
+
+
+ /**
+ * Computes stack usage of an instruction list by performing control flow analysis.
+ *
+ * @return maximum stack depth used by method
+ */
+ public static int getMaxStack( ConstantPoolGen cp, InstructionList il, CodeExceptionGen[] et ) {
+ BranchStack branchTargets = new BranchStack();
+ /* Initially, populate the branch stack with the exception
+ * handlers, because these aren't (necessarily) branched to
+ * explicitly. in each case, the stack will have depth 1,
+ * containing the exception object.
+ */
+ for (int i = 0; i < et.length; i++) {
+ InstructionHandle handler_pc = et[i].getHandlerPC();
+ if (handler_pc != null) {
+ branchTargets.push(handler_pc, 1);
+ }
+ }
+ int stackDepth = 0, maxStackDepth = 0;
+ InstructionHandle ih = il.getStart();
+ while (ih != null) {
+ Instruction instruction = ih.getInstruction();
+ short opcode = instruction.getOpcode();
+ int delta = instruction.produceStack(cp) - instruction.consumeStack(cp);
+ stackDepth += delta;
+ if (stackDepth > maxStackDepth) {
+ maxStackDepth = stackDepth;
+ }
+ // choose the next instruction based on whether current is a branch.
+ if (instruction instanceof BranchInstruction) {
+ BranchInstruction branch = (BranchInstruction) instruction;
+ if (instruction instanceof Select) {
+ // explore all of the select's targets. the default target is handled below.
+ Select select = (Select) branch;
+ InstructionHandle[] targets = select.getTargets();
+ for (int i = 0; i < targets.length; i++) {
+ branchTargets.push(targets[i], stackDepth);
+ }
+ // nothing to fall through to.
+ ih = null;
+ } else if (!(branch instanceof IfInstruction)) {
+ // if an instruction that comes back to following PC,
+ // push next instruction, with stack depth reduced by 1.
+ if (opcode == Constants.JSR || opcode == Constants.JSR_W) {
+ branchTargets.push(ih.getNext(), stackDepth - 1);
+ }
+ ih = null;
+ }
+ // for all branches, the target of the branch is pushed on the branch stack.
+ // conditional branches have a fall through case, selects don't, and
+ // jsr/jsr_w return to the next instruction.
+ branchTargets.push(branch.getTarget(), stackDepth);
+ } else {
+ // check for instructions that terminate the method.
+ if (opcode == Constants.ATHROW || opcode == Constants.RET
+ || (opcode >= Constants.IRETURN && opcode <= Constants.RETURN)) {
+ ih = null;
+ }
+ }
+ // normal case, go to the next instruction.
+ if (ih != null) {
+ ih = ih.getNext();
+ }
+ // if we have no more instructions, see if there are any deferred branches to explore.
+ if (ih == null) {
+ BranchTarget bt = branchTargets.pop();
+ if (bt != null) {
+ ih = bt.target;
+ stackDepth = bt.stackDepth;
+ }
+ }
+ }
+ return maxStackDepth;
+ }
+
+ private List observers;
+
+
+ /** Add observer for this object.
+ */
+ public void addObserver( MethodObserver o ) {
+ if (observers == null) {
+ observers = new ArrayList();
+ }
+ observers.add(o);
+ }
+
+
+ /** Remove observer for this object.
+ */
+ public void removeObserver( MethodObserver o ) {
+ if (observers != null) {
+ observers.remove(o);
+ }
+ }
+
+
+ /** Call notify() method on all observers. This method is not called
+ * automatically whenever the state has changed, but has to be
+ * called by the user after he has finished editing the object.
+ */
+ public void update() {
+ if (observers != null) {
+ for (Iterator e = observers.iterator(); e.hasNext();) {
+ ((MethodObserver) e.next()).notify(this);
+ }
+ }
+ }
+
+
+ /**
+ * Return string representation close to declaration format,
+ * `public static void main(String[]) throws IOException', e.g.
+ *
+ * @return String representation of the method.
+ */
+ public final String toString() {
+ String access = Utility.accessToString(access_flags);
+ String signature = Type.getMethodSignature(type, arg_types);
+ signature = Utility.methodSignatureToString(signature, name, access, true,
+ getLocalVariableTable(cp));
+ StringBuffer buf = new StringBuffer(signature);
+ for (int i = 0; i < getAttributes().length; i++) {
+ Attribute a = getAttributes()[i];
+ if (!((a instanceof Code) || (a instanceof ExceptionTable))) {
+ buf.append(" [").append(a.toString()).append("]");
+ }
+ }
+
+ if (throws_vec.size() > 0) {
+ for (Iterator e = throws_vec.iterator(); e.hasNext();) {
+ buf.append("\n\t\tthrows ").append(e.next());
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /** @return deep copy of this method
+ */
+ public MethodGen copy( String class_name, ConstantPoolGen cp ) {
+ Method m = ((MethodGen) clone()).getMethod();
+ MethodGen mg = new MethodGen(m, class_name, this.cp);
+ if (this.cp != cp) {
+ mg.setConstantPool(cp);
+ mg.getInstructionList().replaceConstantPool(this.cp, cp);
+ }
+ return mg;
+ }
+
+ //J5TODO: Should param_annotations be an array of arrays? Rather than an array of lists, this
+ // is more likely to suggest to the caller it is readonly (which a List does not).
+ /**
+ * Return a list of AnnotationGen objects representing parameter annotations
+ */
+ public List getAnnotationsOnParameter(int i) {
+ ensureExistingParameterAnnotationsUnpacked();
+ if (!hasParameterAnnotations || i>arg_types.length) return null;
+ return param_annotations[i];
+ }
+
+ /**
+ * Goes through the attributes on the method and identifies any that are
+ * RuntimeParameterAnnotations, extracting their contents and storing them
+ * as parameter annotations. There are two kinds of parameter annotation -
+ * visible and invisible. Once they have been unpacked, these attributes are
+ * deleted. (The annotations will be rebuilt as attributes when someone
+ * builds a Method object out of this MethodGen object).
+ */
+ private void ensureExistingParameterAnnotationsUnpacked()
+ {
+ if (haveUnpackedParameterAnnotations)
+ return;
+ // Find attributes that contain parameter annotation data
+ Attribute[] attrs = getAttributes();
+ ParameterAnnotations paramAnnVisAttr = null;
+ ParameterAnnotations paramAnnInvisAttr = null;
+ for (int i = 0; i < attrs.length; i++)
+ {
+ Attribute attribute = attrs[i];
+ if (attribute instanceof ParameterAnnotations)
+ {
+ // Initialize param_annotations
+ if (!hasParameterAnnotations)
+ {
+ param_annotations = new List[arg_types.length];
+ for (int j = 0; j < arg_types.length; j++)
+ param_annotations[j] = new ArrayList();
+ }
+ hasParameterAnnotations = true;
+ ParameterAnnotations rpa = (ParameterAnnotations) attribute;
+ if (rpa instanceof RuntimeVisibleParameterAnnotations)
+ paramAnnVisAttr = rpa;
+ else
+ paramAnnInvisAttr = rpa;
+ for (int j = 0; j < arg_types.length; j++)
+ {
+ // This returns Annotation[] ...
+ ParameterAnnotationEntry immutableArray = rpa
+ .getParameterAnnotationEntries()[j];
+ // ... which needs transforming into an AnnotationGen[] ...
+ List mutable = makeMutableVersion(immutableArray.getAnnotationEntries());
+ // ... then add these to any we already know about
+ param_annotations[j].addAll(mutable);
+ }
+ }
+ }
+ if (paramAnnVisAttr != null)
+ removeAttribute(paramAnnVisAttr);
+ if (paramAnnInvisAttr != null)
+ removeAttribute(paramAnnInvisAttr);
+ haveUnpackedParameterAnnotations = true;
+ }
+
+ private List /* AnnotationGen */makeMutableVersion(AnnotationEntry[] mutableArray)
+ {
+ List result = new ArrayList();
+ for (int i = 0; i < mutableArray.length; i++)
+ {
+ result.add(new AnnotationEntryGen(mutableArray[i], getConstantPool(),
+ false));
+ }
+ return result;
+ }
+
+ public void addParameterAnnotation(int parameterIndex,
+ AnnotationEntryGen annotation)
+ {
+ ensureExistingParameterAnnotationsUnpacked();
+ if (!hasParameterAnnotations)
+ {
+ param_annotations = new List[arg_types.length];
+ hasParameterAnnotations = true;
+ }
+ List existingAnnotations = param_annotations[parameterIndex];
+ if (existingAnnotations != null)
+ {
+ existingAnnotations.add(annotation);
+ }
+ else
+ {
+ List l = new ArrayList();
+ l.add(annotation);
+ param_annotations[parameterIndex] = l;
+ }
+ }
+
+
+
+
+ /**
+ * @return Comparison strategy object
+ */
+ public static BCELComparator getComparator() {
+ return _cmp;
+ }
+
+
+ /**
+ * @param comparator Comparison strategy object
+ */
+ public static void setComparator( BCELComparator comparator ) {
+ _cmp = comparator;
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default two MethodGen objects are said to be equal when
+ * their names and signatures are equal.
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals( Object obj ) {
+ return _cmp.equals(this, obj);
+ }
+
+
+ /**
+ * Return value as defined by given BCELComparator strategy.
+ * By default return the hashcode of the method's name XOR signature.
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return _cmp.hashCode(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Implement this interface if you're interested in changes to a MethodGen object
+ * and register yourself with addObserver().
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface MethodObserver {
+
+ public void notify( MethodGen method );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * NEW - Create new object
+ * <PRE>Stack: ... -> ..., objectref</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class NEW extends CPInstruction implements LoadClass, AllocationInstruction,
+ ExceptionThrower, StackProducer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ NEW() {
+ }
+
+
+ public NEW(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.NEW, index);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.INSTANTIATION_ERROR;
+ cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR;
+ return cs;
+ }
+
+
+ public ObjectType getLoadClassType( ConstantPoolGen cpg ) {
+ return (ObjectType) getType(cpg);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitLoadClass(this);
+ v.visitAllocationInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitCPInstruction(this);
+ v.visitNEW(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * NEWARRAY - Create new array of basic type (int, short, ...)
+ * <PRE>Stack: ..., count -> ..., arrayref</PRE>
+ * type must be one of T_INT, T_SHORT, ...
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class NEWARRAY extends Instruction implements AllocationInstruction, ExceptionThrower,
+ StackProducer {
+
+ private byte type;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ NEWARRAY() {
+ }
+
+
+ public NEWARRAY(byte type) {
+ super(org.apache.tomcat.util.bcel.Constants.NEWARRAY, (short) 2);
+ this.type = type;
+ }
+
+
+ public NEWARRAY(BasicType type) {
+ this(type.getType());
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ out.writeByte(type);
+ }
+
+
+ /**
+ * @return numeric code for basic element type
+ */
+ public final byte getTypecode() {
+ return type;
+ }
+
+
+ /**
+ * @return type of constructed array
+ */
+ public final Type getType() {
+ return new ArrayType(BasicType.getType(type), 1);
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + org.apache.tomcat.util.bcel.Constants.TYPE_NAMES[type];
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ type = bytes.readByte();
+ length = 2;
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ org.apache.tomcat.util.bcel.ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION
+ };
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitAllocationInstruction(this);
+ v.visitExceptionThrower(this);
+ v.visitStackProducer(this);
+ v.visitNEWARRAY(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * NOP - Do nothing
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class NOP extends Instruction {
+
+ public NOP() {
+ super(org.apache.tomcat.util.bcel.Constants.NOP, (short) 1);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitNOP(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote entity that has both name and type. This is true for local variables,
+ * methods and fields.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface NamedAndTyped {
+
+ public String getName();
+
+
+ public Type getType();
+
+
+ public void setName( String name );
+
+
+ public void setType( Type type );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.Repository;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Denotes reference such as java.lang.String.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ObjectType extends ReferenceType {
+
+ private String class_name; // Class name of type
+
+
+ /**
+ * @param class_name fully qualified class name, e.g. java.lang.String
+ */
+ public ObjectType(String class_name) {
+ super(Constants.T_REFERENCE, "L" + class_name.replace('.', '/') + ";");
+ this.class_name = class_name.replace('/', '.');
+ }
+
+
+ /** @return name of referenced class
+ */
+ public String getClassName() {
+ return class_name;
+ }
+
+
+ /** @return a hash code value for the object.
+ */
+ public int hashCode() {
+ return class_name.hashCode();
+ }
+
+
+ /** @return true if both type objects refer to the same class.
+ */
+ public boolean equals( Object type ) {
+ return (type instanceof ObjectType)
+ ? ((ObjectType) type).class_name.equals(class_name)
+ : false;
+ }
+
+
+ /**
+ * If "this" doesn't reference a class, it references an interface
+ * or a non-existant entity.
+ * @deprecated this method returns an inaccurate result
+ * if the class or interface referenced cannot
+ * be found: use referencesClassExact() instead
+ */
+ public boolean referencesClass() {
+ try {
+ JavaClass jc = Repository.lookupClass(class_name);
+ return jc.isClass();
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+
+ /**
+ * If "this" doesn't reference an interface, it references a class
+ * or a non-existant entity.
+ * @deprecated this method returns an inaccurate result
+ * if the class or interface referenced cannot
+ * be found: use referencesInterfaceExact() instead
+ */
+ public boolean referencesInterface() {
+ try {
+ JavaClass jc = Repository.lookupClass(class_name);
+ return !jc.isClass();
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+
+ /**
+ * Return true if this type references a class,
+ * false if it references an interface.
+ * @return true if the type references a class, false if
+ * it references an interface
+ * @throws ClassNotFoundException if the class or interface
+ * referenced by this type can't be found
+ */
+ public boolean referencesClassExact() throws ClassNotFoundException {
+ JavaClass jc = Repository.lookupClass(class_name);
+ return jc.isClass();
+ }
+
+
+ /**
+ * Return true if this type references an interface,
+ * false if it references a class.
+ * @return true if the type references an interface, false if
+ * it references a class
+ * @throws ClassNotFoundException if the class or interface
+ * referenced by this type can't be found
+ */
+ public boolean referencesInterfaceExact() throws ClassNotFoundException {
+ JavaClass jc = Repository.lookupClass(class_name);
+ return !jc.isClass();
+ }
+
+
+ /**
+ * Return true if this type is a subclass of given ObjectType.
+ * @throws ClassNotFoundException if any of this class's superclasses
+ * can't be found
+ */
+ public boolean subclassOf( ObjectType superclass ) throws ClassNotFoundException {
+ if (this.referencesInterface() || superclass.referencesInterface()) {
+ return false;
+ }
+ return Repository.instanceOf(this.class_name, superclass.class_name);
+ }
+
+
+ /**
+ * Java Virtual Machine Specification edition 2, � 5.4.4 Access Control
+ * @throws ClassNotFoundException if the class referenced by this type
+ * can't be found
+ */
+ public boolean accessibleTo( ObjectType accessor ) throws ClassNotFoundException {
+ JavaClass jc = Repository.lookupClass(class_name);
+ if (jc.isPublic()) {
+ return true;
+ } else {
+ JavaClass acc = Repository.lookupClass(accessor.class_name);
+ return acc.getPackageName().equals(jc.getPackageName());
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * POP - Pop top operand stack word
+ *
+ * <PRE>Stack: ..., word -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class POP extends StackInstruction implements PopInstruction {
+
+ public POP() {
+ super(org.apache.tomcat.util.bcel.Constants.POP);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitPopInstruction(this);
+ v.visitStackInstruction(this);
+ v.visitPOP(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * POP2 - Pop two top operand stack words
+ *
+ * <PRE>Stack: ..., word2, word1 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class POP2 extends StackInstruction implements PopInstruction {
+
+ public POP2() {
+ super(org.apache.tomcat.util.bcel.Constants.POP2);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitPopInstruction(this);
+ v.visitStackInstruction(this);
+ v.visitPOP2(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Wrapper class for push operations, which are implemented either as BIPUSH,
+ * LDC or xCONST_n instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class PUSH implements CompoundInstruction, VariableLengthInstruction,
+ InstructionConstants {
+
+ private Instruction instruction;
+
+
+ /**
+ * This constructor also applies for values of type short, char, byte
+ *
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, int value) {
+ if ((value >= -1) && (value <= 5)) {
+ instruction = INSTRUCTIONS[Constants.ICONST_0 + value];
+ } else if ((value >= -128) && (value <= 127)) {
+ instruction = new BIPUSH((byte) value);
+ } else if ((value >= -32768) && (value <= 32767)) {
+ instruction = new SIPUSH((short) value);
+ } else {
+ instruction = new LDC(cp.addInteger(value));
+ }
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, boolean value) {
+ instruction = INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)];
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, float value) {
+ if (value == 0.0) {
+ instruction = FCONST_0;
+ } else if (value == 1.0) {
+ instruction = FCONST_1;
+ } else if (value == 2.0) {
+ instruction = FCONST_2;
+ } else {
+ instruction = new LDC(cp.addFloat(value));
+ }
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, long value) {
+ if (value == 0) {
+ instruction = LCONST_0;
+ } else if (value == 1) {
+ instruction = LCONST_1;
+ } else {
+ instruction = new LDC2_W(cp.addLong(value));
+ }
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, double value) {
+ if (value == 0.0) {
+ instruction = DCONST_0;
+ } else if (value == 1.0) {
+ instruction = DCONST_1;
+ } else {
+ instruction = new LDC2_W(cp.addDouble(value));
+ }
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, String value) {
+ if (value == null) {
+ instruction = ACONST_NULL;
+ } else {
+ instruction = new LDC(cp.addString(value));
+ }
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, Number value) {
+ if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
+ instruction = new PUSH(cp, value.intValue()).instruction;
+ } else if (value instanceof Double) {
+ instruction = new PUSH(cp, value.doubleValue()).instruction;
+ } else if (value instanceof Float) {
+ instruction = new PUSH(cp, value.floatValue()).instruction;
+ } else if (value instanceof Long) {
+ instruction = new PUSH(cp, value.longValue()).instruction;
+ } else {
+ throw new ClassGenException("What's this: " + value);
+ }
+ }
+
+
+ /**
+ * creates a push object from a Character value. Warning: Make sure not to attempt to allow
+ * autoboxing to create this value parameter, as an alternative constructor will be called
+ *
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, Character value) {
+ this(cp, value.charValue());
+ }
+
+
+ /**
+ * @param cp Constant pool
+ * @param value to be pushed
+ */
+ public PUSH(ConstantPoolGen cp, Boolean value) {
+ this(cp, value.booleanValue());
+ }
+
+
+ public final InstructionList getInstructionList() {
+ return new InstructionList(instruction);
+ }
+
+
+ public final Instruction getInstruction() {
+ return instruction;
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString() {
+ return instruction.toString() + " (PUSH)";
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * PUTFIELD - Put field in object
+ * <PRE>Stack: ..., objectref, value -> ...</PRE>
+ * OR
+ * <PRE>Stack: ..., objectref, value.word1, value.word2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class PUTFIELD extends FieldInstruction implements PopInstruction, ExceptionThrower {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ PUTFIELD() {
+ }
+
+
+ public PUTFIELD(int index) {
+ super(Constants.PUTFIELD, index);
+ }
+
+
+ public int consumeStack( ConstantPoolGen cpg ) {
+ return getFieldSize(cpg) + 1;
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
+ v.visitPopInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitFieldInstruction(this);
+ v.visitPUTFIELD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * PUTSTATIC - Put static field in class
+ * <PRE>Stack: ..., value -> ...</PRE>
+ * OR
+ * <PRE>Stack: ..., value.word1, value.word2 -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class PUTSTATIC extends FieldInstruction implements ExceptionThrower, PopInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ PUTSTATIC() {
+ }
+
+
+ public PUTSTATIC(int index) {
+ super(Constants.PUTSTATIC, index);
+ }
+
+
+ public int consumeStack( ConstantPoolGen cpg ) {
+ return getFieldSize(cpg);
+ }
+
+
+ public Class[] getExceptions() {
+ Class[] cs = new Class[1 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length];
+ System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0,
+ ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length);
+ cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR;
+ return cs;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
+ v.visitPopInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitLoadClass(this);
+ v.visitCPInstruction(this);
+ v.visitFieldOrMethod(this);
+ v.visitFieldInstruction(this);
+ v.visitPUTSTATIC(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an unparameterized instruction to pop a value on top from the stack,
+ * such as ISTORE, POP, PUTSTATIC.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see ISTORE
+ * @see POP
+ */
+public interface PopInstruction extends StackConsumer {
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an unparameterized instruction to produce a value on top of the stack,
+ * such as ILOAD, LDC, SIPUSH, DUP, ICONST, etc.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+
+ * @see ILOAD
+ * @see ICONST
+ * @see LDC
+ * @see DUP
+ * @see SIPUSH
+ * @see GETSTATIC
+ */
+public interface PushInstruction extends StackProducer {
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * RET - Return from subroutine
+ *
+ * <PRE>Stack: ... -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class RET extends Instruction implements IndexedInstruction, TypedInstruction {
+
+ private boolean wide;
+ private int index; // index to local variable containg the return address
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ RET() {
+ }
+
+
+ public RET(int index) {
+ super(org.apache.tomcat.util.bcel.Constants.RET, (short) 2);
+ setIndex(index); // May set wide as side effect
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ if (wide) {
+ out.writeByte(org.apache.tomcat.util.bcel.Constants.WIDE);
+ }
+ out.writeByte(opcode);
+ if (wide) {
+ out.writeShort(index);
+ } else {
+ out.writeByte(index);
+ }
+ }
+
+
+ private final void setWide() {
+ wide = index > org.apache.tomcat.util.bcel.Constants.MAX_BYTE;
+ if (wide) {
+ length = 4; // Including the wide byte
+ } else {
+ length = 2;
+ }
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ this.wide = wide;
+ if (wide) {
+ index = bytes.readUnsignedShort();
+ length = 4;
+ } else {
+ index = bytes.readUnsignedByte();
+ length = 2;
+ }
+ }
+
+
+ /**
+ * @return index of local variable containg the return address
+ */
+ public final int getIndex() {
+ return index;
+ }
+
+
+ /**
+ * Set index of local variable containg the return address
+ */
+ public final void setIndex( int n ) {
+ if (n < 0) {
+ throw new ClassGenException("Negative index value: " + n);
+ }
+ index = n;
+ setWide();
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + index;
+ }
+
+
+ /** @return return address type
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return ReturnaddressType.NO_TARGET;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitRET(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * RETURN - Return from void method
+ * <PRE>Stack: ... -> <empty></PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class RETURN extends ReturnInstruction {
+
+ public RETURN() {
+ super(org.apache.tomcat.util.bcel.Constants.RETURN);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitStackConsumer(this);
+ v.visitReturnInstruction(this);
+ v.visitRETURN(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.Repository;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Super class for object and array types.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class ReferenceType extends Type {
+
+ protected ReferenceType(byte t, String s) {
+ super(t, s);
+ }
+
+
+ /** Class is non-abstract but not instantiable from the outside
+ */
+ ReferenceType() {
+ super(Constants.T_OBJECT, "<null object>");
+ }
+
+
+ /**
+ * Return true iff this type is castable to another type t as defined in
+ * the JVM specification. The case where this is Type.NULL is not
+ * defined (see the CHECKCAST definition in the JVM specification).
+ * However, because e.g. CHECKCAST doesn't throw a
+ * ClassCastException when casting a null reference to any Object,
+ * true is returned in this case.
+ *
+ * @throws ClassNotFoundException if any classes or interfaces required
+ * to determine assignment compatibility can't be found
+ */
+ public boolean isCastableTo( Type t ) throws ClassNotFoundException {
+ if (this.equals(Type.NULL)) {
+ return true; // If this is ever changed in isAssignmentCompatible()
+ }
+ return isAssignmentCompatibleWith(t);
+ /* Yes, it's true: It's the same definition.
+ * See vmspec2 AASTORE / CHECKCAST definitions.
+ */
+ }
+
+
+ /**
+ * Return true iff this is assignment compatible with another type t
+ * as defined in the JVM specification; see the AASTORE definition
+ * there.
+ * @throws ClassNotFoundException if any classes or interfaces required
+ * to determine assignment compatibility can't be found
+ */
+ public boolean isAssignmentCompatibleWith( Type t ) throws ClassNotFoundException {
+ if (!(t instanceof ReferenceType)) {
+ return false;
+ }
+ ReferenceType T = (ReferenceType) t;
+ if (this.equals(Type.NULL)) {
+ return true; // This is not explicitely stated, but clear. Isn't it?
+ }
+ /* If this is a class type then
+ */
+ if ((this instanceof ObjectType) && (((ObjectType) this).referencesClassExact())) {
+ /* If T is a class type, then this must be the same class as T,
+ or this must be a subclass of T;
+ */
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
+ if (this.equals(T)) {
+ return true;
+ }
+ if (Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T)
+ .getClassName())) {
+ return true;
+ }
+ }
+ /* If T is an interface type, this must implement interface T.
+ */
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
+ if (Repository.implementationOf(((ObjectType) this).getClassName(),
+ ((ObjectType) T).getClassName())) {
+ return true;
+ }
+ }
+ }
+ /* If this is an interface type, then:
+ */
+ if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterfaceExact())) {
+ /* If T is a class type, then T must be Object (�2.4.7).
+ */
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
+ if (T.equals(Type.OBJECT)) {
+ return true;
+ }
+ }
+ /* If T is an interface type, then T must be the same interface
+ * as this or a superinterface of this (�2.13.2).
+ */
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
+ if (this.equals(T)) {
+ return true;
+ }
+ if (Repository.implementationOf(((ObjectType) this).getClassName(),
+ ((ObjectType) T).getClassName())) {
+ return true;
+ }
+ }
+ }
+ /* If this is an array type, namely, the type SC[], that is, an
+ * array of components of type SC, then:
+ */
+ if (this instanceof ArrayType) {
+ /* If T is a class type, then T must be Object (�2.4.7).
+ */
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) {
+ if (T.equals(Type.OBJECT)) {
+ return true;
+ }
+ }
+ /* If T is an array type TC[], that is, an array of components
+ * of type TC, then one of the following must be true:
+ */
+ if (T instanceof ArrayType) {
+ /* TC and SC are the same primitive type (�2.4.1).
+ */
+ Type sc = ((ArrayType) this).getElementType();
+ Type tc = ((ArrayType) T).getElementType();
+ if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) {
+ return true;
+ }
+ /* TC and SC are reference types (�2.4.6), and type SC is
+ * assignable to TC by these runtime rules.
+ */
+ if (tc instanceof ReferenceType && sc instanceof ReferenceType
+ && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) {
+ return true;
+ }
+ }
+ /* If T is an interface type, T must be one of the interfaces implemented by arrays (�2.15). */
+ // TODO: Check if this is still valid or find a way to dynamically find out which
+ // interfaces arrays implement. However, as of the JVM specification edition 2, there
+ // are at least two different pages where assignment compatibility is defined and
+ // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
+ // 'java.io.Serializable'"
+ if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) {
+ for (int ii = 0; ii < Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++) {
+ if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) {
+ return true;
+ }
+ }
+ }
+ }
+ return false; // default.
+ }
+
+
+ /**
+ * This commutative operation returns the first common superclass (narrowest ReferenceType
+ * referencing a class, not an interface).
+ * If one of the types is a superclass of the other, the former is returned.
+ * If "this" is Type.NULL, then t is returned.
+ * If t is Type.NULL, then "this" is returned.
+ * If "this" equals t ['this.equals(t)'] "this" is returned.
+ * If "this" or t is an ArrayType, then Type.OBJECT is returned;
+ * unless their dimensions match. Then an ArrayType of the same
+ * number of dimensions is returned, with its basic type being the
+ * first common super class of the basic types of "this" and t.
+ * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
+ * If not all of the two classes' superclasses cannot be found, "null" is returned.
+ * See the JVM specification edition 2, "�4.9.2 The Bytecode Verifier".
+ *
+ * @throws ClassNotFoundException on failure to find superclasses of this
+ * type, or the type passed as a parameter
+ */
+ public ReferenceType getFirstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException {
+ if (this.equals(Type.NULL)) {
+ return t;
+ }
+ if (t.equals(Type.NULL)) {
+ return this;
+ }
+ if (this.equals(t)) {
+ return this;
+ /*
+ * TODO: Above sounds a little arbitrary. On the other hand, there is
+ * no object referenced by Type.NULL so we can also say all the objects
+ * referenced by Type.NULL were derived from java.lang.Object.
+ * However, the Java Language's "instanceof" operator proves us wrong:
+ * "null" is not referring to an instance of java.lang.Object :)
+ */
+ }
+ /* This code is from a bug report by Konstantin Shagin <konst@cs.technion.ac.il> */
+ if ((this instanceof ArrayType) && (t instanceof ArrayType)) {
+ ArrayType arrType1 = (ArrayType) this;
+ ArrayType arrType2 = (ArrayType) t;
+ if ((arrType1.getDimensions() == arrType2.getDimensions())
+ && arrType1.getBasicType() instanceof ObjectType
+ && arrType2.getBasicType() instanceof ObjectType) {
+ return new ArrayType(((ObjectType) arrType1.getBasicType())
+ .getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), arrType1
+ .getDimensions());
+ }
+ }
+ if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
+ return Type.OBJECT;
+ // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ }
+ if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface())
+ || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) {
+ return Type.OBJECT;
+ // TODO: The above line is correct comparing to the vmspec2. But one could
+ // make class file verification a bit stronger here by using the notion of
+ // superinterfaces or even castability or assignment compatibility.
+ }
+ // this and t are ObjectTypes, see above.
+ ObjectType thiz = (ObjectType) this;
+ ObjectType other = (ObjectType) t;
+ JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
+ JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
+ if ((thiz_sups == null) || (other_sups == null)) {
+ return null;
+ }
+ // Waaahh...
+ JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
+ JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
+ System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
+ System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
+ this_sups[0] = Repository.lookupClass(thiz.getClassName());
+ t_sups[0] = Repository.lookupClass(other.getClassName());
+ for (int i = 0; i < t_sups.length; i++) {
+ for (int j = 0; j < this_sups.length; j++) {
+ if (this_sups[j].equals(t_sups[i])) {
+ return new ObjectType(this_sups[j].getClassName());
+ }
+ }
+ }
+ // Huh? Did you ask for Type.OBJECT's superclass??
+ return null;
+ }
+
+
+ /**
+ * This commutative operation returns the first common superclass (narrowest ReferenceType
+ * referencing a class, not an interface).
+ * If one of the types is a superclass of the other, the former is returned.
+ * If "this" is Type.NULL, then t is returned.
+ * If t is Type.NULL, then "this" is returned.
+ * If "this" equals t ['this.equals(t)'] "this" is returned.
+ * If "this" or t is an ArrayType, then Type.OBJECT is returned.
+ * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
+ * If not all of the two classes' superclasses cannot be found, "null" is returned.
+ * See the JVM specification edition 2, "�4.9.2 The Bytecode Verifier".
+ *
+ * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has
+ * slightly changed semantics.
+ * @throws ClassNotFoundException on failure to find superclasses of this
+ * type, or the type passed as a parameter
+ */
+ public ReferenceType firstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException {
+ if (this.equals(Type.NULL)) {
+ return t;
+ }
+ if (t.equals(Type.NULL)) {
+ return this;
+ }
+ if (this.equals(t)) {
+ return this;
+ /*
+ * TODO: Above sounds a little arbitrary. On the other hand, there is
+ * no object referenced by Type.NULL so we can also say all the objects
+ * referenced by Type.NULL were derived from java.lang.Object.
+ * However, the Java Language's "instanceof" operator proves us wrong:
+ * "null" is not referring to an instance of java.lang.Object :)
+ */
+ }
+ if ((this instanceof ArrayType) || (t instanceof ArrayType)) {
+ return Type.OBJECT;
+ // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ }
+ if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface())
+ || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) {
+ return Type.OBJECT;
+ // TODO: The above line is correct comparing to the vmspec2. But one could
+ // make class file verification a bit stronger here by using the notion of
+ // superinterfaces or even castability or assignment compatibility.
+ }
+ // this and t are ObjectTypes, see above.
+ ObjectType thiz = (ObjectType) this;
+ ObjectType other = (ObjectType) t;
+ JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
+ JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
+ if ((thiz_sups == null) || (other_sups == null)) {
+ return null;
+ }
+ // Waaahh...
+ JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
+ JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
+ System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
+ System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
+ this_sups[0] = Repository.lookupClass(thiz.getClassName());
+ t_sups[0] = Repository.lookupClass(other.getClassName());
+ for (int i = 0; i < t_sups.length; i++) {
+ for (int j = 0; j < this_sups.length; j++) {
+ if (this_sups[j].equals(t_sups[i])) {
+ return new ObjectType(this_sups[j].getClassName());
+ }
+ }
+ }
+ // Huh? Did you ask for Type.OBJECT's superclass??
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.ExceptionConstants;
+
+/**
+ * Super class for the xRETURN family of instructions.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class ReturnInstruction extends Instruction implements ExceptionThrower,
+ TypedInstruction, StackConsumer {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ ReturnInstruction() {
+ }
+
+
+ /**
+ * @param opcode of instruction
+ */
+ protected ReturnInstruction(short opcode) {
+ super(opcode, (short) 1);
+ }
+
+
+ public Type getType() {
+ switch (opcode) {
+ case Constants.IRETURN:
+ return Type.INT;
+ case Constants.LRETURN:
+ return Type.LONG;
+ case Constants.FRETURN:
+ return Type.FLOAT;
+ case Constants.DRETURN:
+ return Type.DOUBLE;
+ case Constants.ARETURN:
+ return Type.OBJECT;
+ case Constants.RETURN:
+ return Type.VOID;
+ default: // Never reached
+ throw new ClassGenException("Unknown type " + opcode);
+ }
+ }
+
+
+ public Class[] getExceptions() {
+ return new Class[] {
+ ExceptionConstants.ILLEGAL_MONITOR_STATE
+ };
+ }
+
+
+ /** @return type associated with the instruction
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return getType();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import org.apache.tomcat.util.bcel.Constants;
+
+/**
+ * Returnaddress, the type JSR or JSR_W instructions push upon the stack.
+ *
+ * see vmspec2 �3.3.3
+ * @version $Id$
+ * @author Enver Haase
+ */
+public class ReturnaddressType extends Type {
+
+ public static final ReturnaddressType NO_TARGET = new ReturnaddressType();
+ private InstructionHandle returnTarget;
+
+
+ /**
+ * A Returnaddress [that doesn't know where to return to].
+ */
+ private ReturnaddressType() {
+ super(Constants.T_ADDRESS, "<return address>");
+ }
+
+
+ /**
+ * Creates a ReturnaddressType object with a target.
+ */
+ public ReturnaddressType(InstructionHandle returnTarget) {
+ super(Constants.T_ADDRESS, "<return address targeting " + returnTarget + ">");
+ this.returnTarget = returnTarget;
+ }
+
+
+ /** @return a hash code value for the object.
+ */
+ public int hashCode() {
+ if (returnTarget == null) {
+ return 0;
+ }
+ return returnTarget.hashCode();
+ }
+
+
+ /**
+ * Returns if the two Returnaddresses refer to the same target.
+ */
+ public boolean equals( Object rat ) {
+ if (!(rat instanceof ReturnaddressType)) {
+ return false;
+ }
+ ReturnaddressType that = (ReturnaddressType) rat;
+ if (this.returnTarget == null || that.returnTarget == null) {
+ return that.returnTarget == this.returnTarget;
+ }
+ return that.returnTarget.equals(this.returnTarget);
+ }
+
+
+ /**
+ * @return the target of this ReturnaddressType
+ */
+ public InstructionHandle getTarget() {
+ return returnTarget;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * SALOAD - Load short from array
+ * <PRE>Stack: ..., arrayref, index -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class SALOAD extends ArrayInstruction implements StackProducer {
+
+ public SALOAD() {
+ super(org.apache.tomcat.util.bcel.Constants.SALOAD);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackProducer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitSALOAD(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * SASTORE - Store into short array
+ * <PRE>Stack: ..., arrayref, index, value -> ...</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class SASTORE extends ArrayInstruction implements StackConsumer {
+
+ public SASTORE() {
+ super(org.apache.tomcat.util.bcel.Constants.SASTORE);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitExceptionThrower(this);
+ v.visitTypedInstruction(this);
+ v.visitArrayInstruction(this);
+ v.visitSASTORE(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * SIPUSH - Push short
+ *
+ * <PRE>Stack: ... -> ..., value</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class SIPUSH extends Instruction implements ConstantPushInstruction {
+
+ private short b;
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ SIPUSH() {
+ }
+
+
+ public SIPUSH(short b) {
+ super(org.apache.tomcat.util.bcel.Constants.SIPUSH, (short) 3);
+ this.b = b;
+ }
+
+
+ /**
+ * Dump instruction as short code to stream out.
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ super.dump(out);
+ out.writeShort(b);
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ return super.toString(verbose) + " " + b;
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ length = 3;
+ b = bytes.readShort();
+ }
+
+
+ public Number getValue() {
+ return new Integer(b);
+ }
+
+
+ /** @return Type.SHORT
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.SHORT;
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitPushInstruction(this);
+ v.visitStackProducer(this);
+ v.visitTypedInstruction(this);
+ v.visitConstantPushInstruction(this);
+ v.visitSIPUSH(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * SWAP - Swa top operand stack word
+ * <PRE>Stack: ..., word2, word1 -> ..., word1, word2</PRE>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class SWAP extends StackInstruction implements StackConsumer, StackProducer {
+
+ public SWAP() {
+ super(org.apache.tomcat.util.bcel.Constants.SWAP);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitStackProducer(this);
+ v.visitStackInstruction(this);
+ v.visitSWAP(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or
+ * TABLESWITCH instruction, depending on whether the match values (int[]) can be
+ * sorted with no gaps between the numbers.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class SWITCH implements CompoundInstruction {
+
+ private int[] match;
+ private InstructionHandle[] targets;
+ private Select instruction;
+ private int match_length;
+
+
+ /**
+ * Template for switch() constructs. If the match array can be
+ * sorted in ascending order with gaps no larger than max_gap
+ * between the numbers, a TABLESWITCH instruction is generated, and
+ * a LOOKUPSWITCH otherwise. The former may be more efficient, but
+ * needs more space.
+ *
+ * Note, that the key array always will be sorted, though we leave
+ * the original arrays unaltered.
+ *
+ * @param match array of match values (case 2: ... case 7: ..., etc.)
+ * @param targets the instructions to be branched to for each case
+ * @param target the default target
+ * @param max_gap maximum gap that may between case branches
+ */
+ public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target, int max_gap) {
+ this.match = (int[]) match.clone();
+ this.targets = (InstructionHandle[]) targets.clone();
+ if ((match_length = match.length) < 2) {
+ instruction = new TABLESWITCH(match, targets, target);
+ } else {
+ sort(0, match_length - 1);
+ if (matchIsOrdered(max_gap)) {
+ fillup(max_gap, target);
+ instruction = new TABLESWITCH(this.match, this.targets, target);
+ } else {
+ instruction = new LOOKUPSWITCH(this.match, this.targets, target);
+ }
+ }
+ }
+
+
+ public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target) {
+ this(match, targets, target, 1);
+ }
+
+
+ private final void fillup( int max_gap, InstructionHandle target ) {
+ int max_size = match_length + match_length * max_gap;
+ int[] m_vec = new int[max_size];
+ InstructionHandle[] t_vec = new InstructionHandle[max_size];
+ int count = 1;
+ m_vec[0] = match[0];
+ t_vec[0] = targets[0];
+ for (int i = 1; i < match_length; i++) {
+ int prev = match[i - 1];
+ int gap = match[i] - prev;
+ for (int j = 1; j < gap; j++) {
+ m_vec[count] = prev + j;
+ t_vec[count] = target;
+ count++;
+ }
+ m_vec[count] = match[i];
+ t_vec[count] = targets[i];
+ count++;
+ }
+ match = new int[count];
+ targets = new InstructionHandle[count];
+ System.arraycopy(m_vec, 0, match, 0, count);
+ System.arraycopy(t_vec, 0, targets, 0, count);
+ }
+
+
+ /**
+ * Sort match and targets array with QuickSort.
+ */
+ private final void sort( int l, int r ) {
+ int i = l, j = r;
+ int h, m = match[(l + r) / 2];
+ InstructionHandle h2;
+ do {
+ while (match[i] < m) {
+ i++;
+ }
+ while (m < match[j]) {
+ j--;
+ }
+ if (i <= j) {
+ h = match[i];
+ match[i] = match[j];
+ match[j] = h; // Swap elements
+ h2 = targets[i];
+ targets[i] = targets[j];
+ targets[j] = h2; // Swap instructions, too
+ i++;
+ j--;
+ }
+ } while (i <= j);
+ if (l < j) {
+ sort(l, j);
+ }
+ if (i < r) {
+ sort(i, r);
+ }
+ }
+
+
+ /**
+ * @return match is sorted in ascending order with no gap bigger than max_gap?
+ */
+ private final boolean matchIsOrdered( int max_gap ) {
+ for (int i = 1; i < match_length; i++) {
+ if (match[i] - match[i - 1] > max_gap) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public final InstructionList getInstructionList() {
+ return new InstructionList(instruction);
+ }
+
+
+ public final Instruction getInstruction() {
+ return instruction;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
+ *
+ * <p>We use our super's <code>target</code> property as the default target.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see LOOKUPSWITCH
+ * @see TABLESWITCH
+ * @see InstructionList
+ */
+public abstract class Select extends BranchInstruction implements VariableLengthInstruction,
+ StackProducer {
+
+ protected int[] match; // matches, i.e., case 1: ...
+ protected int[] indices; // target offsets
+ protected InstructionHandle[] targets; // target objects in instruction list
+ protected int fixed_length; // fixed length defined by subclasses
+ protected int match_length; // number of cases
+ protected int padding = 0; // number of pad bytes for alignment
+
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ Select() {
+ }
+
+
+ /**
+ * (Match, target) pairs for switch.
+ * `Match' and `targets' must have the same length of course.
+ *
+ * @param match array of matching values
+ * @param targets instruction targets
+ * @param defaultTarget default instruction target
+ */
+ Select(short opcode, int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) {
+ super(opcode, defaultTarget);
+ this.targets = targets;
+ for (int i = 0; i < targets.length; i++) {
+ notifyTarget(null, targets[i], this);
+ }
+ this.match = match;
+ if ((match_length = match.length) != targets.length) {
+ throw new ClassGenException("Match and target array have not the same length: Match length: " + match.length + " Target length: " + targets.length);
+ }
+ indices = new int[match_length];
+ }
+
+
+ /**
+ * Since this is a variable length instruction, it may shift the following
+ * instructions which then need to update their position.
+ *
+ * Called by InstructionList.setPositions when setting the position for every
+ * instruction. In the presence of variable length instructions `setPositions'
+ * performs multiple passes over the instruction list to calculate the
+ * correct (byte) positions and offsets by calling this function.
+ *
+ * @param offset additional offset caused by preceding (variable length) instructions
+ * @param max_offset the maximum offset that may be caused by these instructions
+ * @return additional offset caused by possible change of this instruction's length
+ */
+ protected int updatePosition( int offset, int max_offset ) {
+ position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc.
+ short old_length = length;
+ /* Alignment on 4-byte-boundary, + 1, because of tag byte.
+ */
+ padding = (4 - ((position + 1) % 4)) % 4;
+ length = (short) (fixed_length + padding); // Update length
+ return length - old_length;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ out.writeByte(opcode);
+ for (int i = 0; i < padding; i++) {
+ out.writeByte(0);
+ }
+ index = getTargetOffset(); // Write default target offset
+ out.writeInt(index);
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
+ for (int i = 0; i < padding; i++) {
+ bytes.readByte();
+ }
+ // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
+ index = bytes.readInt();
+ }
+
+
+ /**
+ * @return mnemonic for instruction
+ */
+ public String toString( boolean verbose ) {
+ StringBuffer buf = new StringBuffer(super.toString(verbose));
+ if (verbose) {
+ for (int i = 0; i < match_length; i++) {
+ String s = "null";
+ if (targets[i] != null) {
+ s = targets[i].getInstruction().toString();
+ }
+ buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(
+ indices[i]).append("})");
+ }
+ } else {
+ buf.append(" ...");
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * Set branch target for `i'th case
+ */
+ public void setTarget( int i, InstructionHandle target ) {
+ notifyTarget(targets[i], target, this);
+ targets[i] = target;
+ }
+
+
+ /**
+ * @param old_ih old target
+ * @param new_ih new target
+ */
+ public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
+ boolean targeted = false;
+ if (target == old_ih) {
+ targeted = true;
+ setTarget(new_ih);
+ }
+ for (int i = 0; i < targets.length; i++) {
+ if (targets[i] == old_ih) {
+ targeted = true;
+ setTarget(i, new_ih);
+ }
+ }
+ if (!targeted) {
+ throw new ClassGenException("Not targeting " + old_ih);
+ }
+ }
+
+
+ /**
+ * @return true, if ih is target of this instruction
+ */
+ public boolean containsTarget( InstructionHandle ih ) {
+ if (target == ih) {
+ return true;
+ }
+ for (int i = 0; i < targets.length; i++) {
+ if (targets[i] == ih) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ protected Object clone() throws CloneNotSupportedException {
+ Select copy = (Select) super.clone();
+ copy.match = (int[]) match.clone();
+ copy.indices = (int[]) indices.clone();
+ copy.targets = (InstructionHandle[]) targets.clone();
+ return copy;
+ }
+
+
+ /**
+ * Inform targets that they're not targeted anymore.
+ */
+ void dispose() {
+ super.dispose();
+ for (int i = 0; i < targets.length; i++) {
+ targets[i].removeTargeter(this);
+ }
+ }
+
+
+ /**
+ * @return array of match indices
+ */
+ public int[] getMatchs() {
+ return match;
+ }
+
+
+ /**
+ * @return array of match target offsets
+ */
+ public int[] getIndices() {
+ return indices;
+ }
+
+
+ /**
+ * @return array of match targets
+ */
+ public InstructionHandle[] getTargets() {
+ return targets;
+ }
+}
--- /dev/null
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.classfile.ConstantDouble;
+import org.apache.tomcat.util.bcel.classfile.ConstantFloat;
+import org.apache.tomcat.util.bcel.classfile.ConstantInteger;
+import org.apache.tomcat.util.bcel.classfile.ConstantLong;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ElementValue;
+import org.apache.tomcat.util.bcel.classfile.SimpleElementValue;
+
+public class SimpleElementValueGen extends ElementValueGen
+{
+ // For primitive types and string type, this points to the value entry in
+ // the cpGen
+ // For 'class' this points to the class entry in the cpGen
+ private int idx;
+
+ // ctors for each supported type... type could be inferred but for now lets
+ // force it to be passed
+ /**
+ * Protected ctor used for deserialization, doesn't *put* an entry in the
+ * constant pool, assumes the one at the supplied index is correct.
+ */
+ protected SimpleElementValueGen(int type, int idx, ConstantPoolGen cpGen)
+ {
+ super(type, cpGen);
+ this.idx = idx;
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, int value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addInteger(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, long value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addLong(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, double value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addDouble(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, float value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addFloat(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, short value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addInteger(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, byte value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addInteger(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, char value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addInteger(value);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, boolean value)
+ {
+ super(type, cpGen);
+ if (value)
+ idx = cpGen.addInteger(1);
+ else
+ idx = cpGen.addInteger(0);
+ }
+
+ public SimpleElementValueGen(int type, ConstantPoolGen cpGen, String value)
+ {
+ super(type, cpGen);
+ idx = cpGen.addUtf8(value);
+ }
+
+ /**
+ * The boolean controls whether we copy info from the 'old' constant pool to
+ * the 'new'. You need to use this ctor if the annotation is being copied
+ * from one file to another.
+ */
+ public SimpleElementValueGen(SimpleElementValue value,
+ ConstantPoolGen cpool, boolean copyPoolEntries)
+ {
+ super(value.getElementValueType(), cpool);
+ if (!copyPoolEntries)
+ {
+ // J5ASSERT: Could assert value.stringifyValue() is the same as
+ // cpool.getConstant(SimpleElementValuevalue.getIndex())
+ idx = value.getIndex();
+ }
+ else
+ {
+ switch (value.getElementValueType())
+ {
+ case STRING:
+ idx = cpool.addUtf8(value.getValueString());
+ break;
+ case PRIMITIVE_INT:
+ idx = cpool.addInteger(value.getValueInt());
+ break;
+ case PRIMITIVE_BYTE:
+ idx = cpool.addInteger(value.getValueByte());
+ break;
+ case PRIMITIVE_CHAR:
+ idx = cpool.addInteger(value.getValueChar());
+ break;
+ case PRIMITIVE_LONG:
+ idx = cpool.addLong(value.getValueLong());
+ break;
+ case PRIMITIVE_FLOAT:
+ idx = cpool.addFloat(value.getValueFloat());
+ break;
+ case PRIMITIVE_DOUBLE:
+ idx = cpool.addDouble(value.getValueDouble());
+ break;
+ case PRIMITIVE_BOOLEAN:
+ if (value.getValueBoolean())
+ {
+ idx = cpool.addInteger(1);
+ }
+ else
+ {
+ idx = cpool.addInteger(0);
+ }
+ break;
+ case PRIMITIVE_SHORT:
+ idx = cpool.addInteger(value.getValueShort());
+ break;
+ default:
+ throw new RuntimeException(
+ "SimpleElementValueGen class does not know how "
+ + "to copy this type " + type);
+ }
+ }
+ }
+
+ /**
+ * Return immutable variant
+ */
+ public ElementValue getElementValue()
+ {
+ return new SimpleElementValue(type, idx, cpGen.getConstantPool());
+ }
+
+ public int getIndex()
+ {
+ return idx;
+ }
+
+ public String getValueString()
+ {
+ if (type != STRING)
+ throw new RuntimeException(
+ "Dont call getValueString() on a non STRING ElementValue");
+ ConstantUtf8 c = (ConstantUtf8) cpGen.getConstant(idx);
+ return c.getBytes();
+ }
+
+ public int getValueInt()
+ {
+ if (type != PRIMITIVE_INT)
+ throw new RuntimeException(
+ "Dont call getValueString() on a non STRING ElementValue");
+ ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx);
+ return c.getBytes();
+ }
+
+ // Whatever kind of value it is, return it as a string
+ public String stringifyValue()
+ {
+ switch (type)
+ {
+ case PRIMITIVE_INT:
+ ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx);
+ return Integer.toString(c.getBytes());
+ case PRIMITIVE_LONG:
+ ConstantLong j = (ConstantLong) cpGen.getConstant(idx);
+ return Long.toString(j.getBytes());
+ case PRIMITIVE_DOUBLE:
+ ConstantDouble d = (ConstantDouble) cpGen.getConstant(idx);
+ return Double.toString(d.getBytes());
+ case PRIMITIVE_FLOAT:
+ ConstantFloat f = (ConstantFloat) cpGen.getConstant(idx);
+ return Float.toString(f.getBytes());
+ case PRIMITIVE_SHORT:
+ ConstantInteger s = (ConstantInteger) cpGen.getConstant(idx);
+ return Integer.toString(s.getBytes());
+ case PRIMITIVE_BYTE:
+ ConstantInteger b = (ConstantInteger) cpGen.getConstant(idx);
+ return Integer.toString(b.getBytes());
+ case PRIMITIVE_CHAR:
+ ConstantInteger ch = (ConstantInteger) cpGen.getConstant(idx);
+ return Integer.toString(ch.getBytes());
+ case PRIMITIVE_BOOLEAN:
+ ConstantInteger bo = (ConstantInteger) cpGen.getConstant(idx);
+ if (bo.getBytes() == 0)
+ return "false";
+ if (bo.getBytes() != 0)
+ return "true";
+ case STRING:
+ ConstantUtf8 cu8 = (ConstantUtf8) cpGen.getConstant(idx);
+ return cu8.getBytes();
+ default:
+ throw new RuntimeException(
+ "SimpleElementValueGen class does not know how to stringify type "
+ + type);
+ }
+ }
+
+ public void dump(DataOutputStream dos) throws IOException
+ {
+ dos.writeByte(type); // u1 kind of value
+ switch (type)
+ {
+ case PRIMITIVE_INT:
+ case PRIMITIVE_BYTE:
+ case PRIMITIVE_CHAR:
+ case PRIMITIVE_FLOAT:
+ case PRIMITIVE_LONG:
+ case PRIMITIVE_BOOLEAN:
+ case PRIMITIVE_SHORT:
+ case PRIMITIVE_DOUBLE:
+ case STRING:
+ dos.writeShort(idx);
+ break;
+ default:
+ throw new RuntimeException(
+ "SimpleElementValueGen doesnt know how to write out type "
+ + type);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote an instruction that may consume a value from the stack.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface StackConsumer {
+
+ /** @return how many words are consumed from stack
+ */
+ public int consumeStack( ConstantPoolGen cpg );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Super class for stack operations like DUP and POP.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class StackInstruction extends Instruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ StackInstruction() {
+ }
+
+
+ /**
+ * @param opcode instruction opcode
+ */
+ protected StackInstruction(short opcode) {
+ super(opcode, (short) 1);
+ }
+
+
+ /** @return Type.UNKNOWN
+ */
+ public Type getType( ConstantPoolGen cp ) {
+ return Type.UNKNOWN;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denote an instruction that may produce a value on top of the stack
+ * (this excludes DUP_X1, e.g.)
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface StackProducer {
+
+ /** @return how many words are produced on stack
+ */
+ public int produceStack( ConstantPoolGen cpg );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an unparameterized instruction to store a value into a local variable,
+ * e.g. ISTORE.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class StoreInstruction extends LocalVariableInstruction implements PopInstruction {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ * tag and length are defined in readInstruction and initFromFile, respectively.
+ */
+ StoreInstruction(short canon_tag, short c_tag) {
+ super(canon_tag, c_tag);
+ }
+
+
+ /**
+ * @param opcode Instruction opcode
+ * @param c_tag Instruction number for compact version, ASTORE_0, e.g.
+ * @param n local variable index (unsigned short)
+ */
+ protected StoreInstruction(short opcode, short c_tag, int n) {
+ super(opcode, c_tag, n);
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitStackConsumer(this);
+ v.visitPopInstruction(this);
+ v.visitTypedInstruction(this);
+ v.visitLocalVariableInstruction(this);
+ v.visitStoreInstruction(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import org.apache.tomcat.util.bcel.util.ByteSequence;
+
+/**
+ * TABLESWITCH - Switch within given range of values, i.e., low..high
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see SWITCH
+ */
+public class TABLESWITCH extends Select {
+
+ /**
+ * Empty constructor needed for the Class.newInstance() statement in
+ * Instruction.readInstruction(). Not to be used otherwise.
+ */
+ TABLESWITCH() {
+ }
+
+
+ /**
+ * @param match sorted array of match values, match[0] must be low value,
+ * match[match_length - 1] high value
+ * @param targets where to branch for matched values
+ * @param defaultTarget default branch
+ */
+ public TABLESWITCH(int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) {
+ super(org.apache.tomcat.util.bcel.Constants.TABLESWITCH, match, targets, defaultTarget);
+ length = (short) (13 + match_length * 4); /* Alignment remainder assumed
+ * 0 here, until dump time */
+ fixed_length = length;
+ }
+
+
+ /**
+ * Dump instruction as byte code to stream out.
+ * @param out Output stream
+ */
+ public void dump( DataOutputStream out ) throws IOException {
+ super.dump(out);
+ int low = (match_length > 0) ? match[0] : 0;
+ out.writeInt(low);
+ int high = (match_length > 0) ? match[match_length - 1] : 0;
+ out.writeInt(high);
+ for (int i = 0; i < match_length; i++) {
+ out.writeInt(indices[i] = getTargetOffset(targets[i]));
+ }
+ }
+
+
+ /**
+ * Read needed data (e.g. index) from file.
+ */
+ protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException {
+ super.initFromFile(bytes, wide);
+ int low = bytes.readInt();
+ int high = bytes.readInt();
+ match_length = high - low + 1;
+ fixed_length = (short) (13 + match_length * 4);
+ length = (short) (fixed_length + padding);
+ match = new int[match_length];
+ indices = new int[match_length];
+ targets = new InstructionHandle[match_length];
+ for (int i = low; i <= high; i++) {
+ match[i - low] = i;
+ }
+ for (int i = 0; i < match_length; i++) {
+ indices[i] = bytes.readInt();
+ }
+ }
+
+
+ /**
+ * Call corresponding visitor method(s). The order is:
+ * Call visitor methods of implemented interfaces first, then
+ * call methods according to the class hierarchy in descending order,
+ * i.e., the most specific visitXXX() call comes last.
+ *
+ * @param v Visitor object
+ */
+ public void accept( Visitor v ) {
+ v.visitVariableLengthInstruction(this);
+ v.visitStackProducer(this);
+ v.visitBranchInstruction(this);
+ v.visitSelect(this);
+ v.visitTABLESWITCH(this);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Thrown by InstructionList.remove() when one or multiple disposed instruction
+ * are still being referenced by a InstructionTargeter object. I.e. the
+ * InstructionTargeter has to be notified that (one of) the InstructionHandle it
+ * is referencing is being removed from the InstructionList and thus not valid anymore.
+ *
+ * Making this an exception instead of a return value forces the user to handle
+ * these case explicitely in a try { ... } catch. The following code illustrates
+ * how this may be done:
+ *
+ * <PRE>
+ * ...
+ * try {
+ * il.delete(start_ih, end_ih);
+ * } catch(TargetLostException e) {
+ * InstructionHandle[] targets = e.getTargets();
+ * for(int i=0; i < targets.length; i++) {
+ * InstructionTargeter[] targeters = targets[i].getTargeters();
+ *
+ * for(int j=0; j < targeters.length; j++)
+ * targeters[j].updateTarget(targets[i], new_target);
+ * }
+ * }
+ * </PRE>
+ *
+ * @see InstructionHandle
+ * @see InstructionList
+ * @see InstructionTargeter
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class TargetLostException extends Exception {
+
+ private InstructionHandle[] targets;
+
+
+ TargetLostException(InstructionHandle[] t, String mesg) {
+ super(mesg);
+ targets = t;
+ }
+
+
+ /**
+ * @return list of instructions still being targeted.
+ */
+ public InstructionHandle[] getTargets() {
+ return targets;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.ClassFormatException;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Abstract super class for all possible java types, namely basic types
+ * such as int, object types like String and array types, e.g. int[]
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public abstract class Type implements java.io.Serializable {
+
+ protected byte type;
+ protected String signature; // signature for the type
+ /** Predefined constants
+ */
+ public static final BasicType VOID = new BasicType(Constants.T_VOID);
+ public static final BasicType BOOLEAN = new BasicType(Constants.T_BOOLEAN);
+ public static final BasicType INT = new BasicType(Constants.T_INT);
+ public static final BasicType SHORT = new BasicType(Constants.T_SHORT);
+ public static final BasicType BYTE = new BasicType(Constants.T_BYTE);
+ public static final BasicType LONG = new BasicType(Constants.T_LONG);
+ public static final BasicType DOUBLE = new BasicType(Constants.T_DOUBLE);
+ public static final BasicType FLOAT = new BasicType(Constants.T_FLOAT);
+ public static final BasicType CHAR = new BasicType(Constants.T_CHAR);
+ public static final ObjectType OBJECT = new ObjectType("java.lang.Object");
+ public static final ObjectType CLASS = new ObjectType("java.lang.Class");
+ public static final ObjectType STRING = new ObjectType("java.lang.String");
+ public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer");
+ public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable");
+ public static final Type[] NO_ARGS = new Type[0];
+ public static final ReferenceType NULL = new ReferenceType() {
+ };
+ public static final Type UNKNOWN = new Type(Constants.T_UNKNOWN, "<unknown object>") {
+ };
+
+
+ protected Type(byte t, String s) {
+ type = t;
+ signature = s;
+ }
+
+
+ /**
+ * @return hashcode of Type
+ */
+ public int hashCode() {
+ return type ^ signature.hashCode();
+ }
+
+
+ /**
+ * @return whether the Types are equal
+ */
+ public boolean equals(Object o) {
+ if (o instanceof Type) {
+ Type t = (Type)o;
+ return (type == t.type) && signature.equals(t.signature);
+ }
+ return false;
+ }
+
+
+ /**
+ * @return signature for given type.
+ */
+ public String getSignature() {
+ return signature;
+ }
+
+
+ /**
+ * @return type as defined in Constants
+ */
+ public byte getType() {
+ return type;
+ }
+
+
+ /**
+ * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise)
+ */
+ public int getSize() {
+ switch (type) {
+ case Constants.T_DOUBLE:
+ case Constants.T_LONG:
+ return 2;
+ case Constants.T_VOID:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+
+
+ /**
+ * @return Type string, e.g. `int[]'
+ */
+ public String toString() {
+ return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility
+ .signatureToString(signature, false);
+ }
+
+
+ /**
+ * Convert type to Java method signature, e.g. int[] f(java.lang.String x)
+ * becomes (Ljava/lang/String;)[I
+ *
+ * @param return_type what the method returns
+ * @param arg_types what are the argument types
+ * @return method signature for given type(s).
+ */
+ public static String getMethodSignature( Type return_type, Type[] arg_types ) {
+ StringBuffer buf = new StringBuffer("(");
+ int length = (arg_types == null) ? 0 : arg_types.length;
+ for (int i = 0; i < length; i++) {
+ buf.append(arg_types[i].getSignature());
+ }
+ buf.append(')');
+ buf.append(return_type.getSignature());
+ return buf.toString();
+ }
+
+ private static ThreadLocal consumed_chars = new ThreadLocal() {
+
+ protected Object initialValue() {
+ return new Integer(0);
+ }
+ };//int consumed_chars=0; // Remember position in string, see getArgumentTypes
+
+
+ private static int unwrap( ThreadLocal tl ) {
+ return ((Integer) tl.get()).intValue();
+ }
+
+
+ private static void wrap( ThreadLocal tl, int value ) {
+ tl.set(new Integer(value));
+ }
+
+
+ /**
+ * Convert signature to a Type object.
+ * @param signature signature string such as Ljava/lang/String;
+ * @return type object
+ */
+ public static final Type getType( String signature ) throws StringIndexOutOfBoundsException {
+ byte type = Utility.typeOfSignature(signature);
+ if (type <= Constants.T_VOID) {
+ //corrected concurrent private static field acess
+ wrap(consumed_chars, 1);
+ return BasicType.getType(type);
+ } else if (type == Constants.T_ARRAY) {
+ int dim = 0;
+ do { // Count dimensions
+ dim++;
+ } while (signature.charAt(dim) == '[');
+ // Recurse, but just once, if the signature is ok
+ Type t = getType(signature.substring(dim));
+ //corrected concurrent private static field acess
+ // consumed_chars += dim; // update counter - is replaced by
+ int _temp = unwrap(consumed_chars) + dim;
+ wrap(consumed_chars, _temp);
+ return new ArrayType(t, dim);
+ } else { // type == T_REFERENCE
+ int index = signature.indexOf(';'); // Look for closing `;'
+ if (index < 0) {
+ throw new ClassFormatException("Invalid signature: " + signature);
+ }
+ //corrected concurrent private static field acess
+ wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed
+ return new ObjectType(signature.substring(1, index).replace('/', '.'));
+ }
+ }
+
+
+ /**
+ * Convert return value of a method (signature) to a Type object.
+ *
+ * @param signature signature string such as (Ljava/lang/String;)V
+ * @return return type
+ */
+ public static Type getReturnType( String signature ) {
+ try {
+ // Read return type after `)'
+ int index = signature.lastIndexOf(')') + 1;
+ return getType(signature.substring(index));
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ }
+
+
+ /**
+ * Convert arguments of a method (signature) to an array of Type objects.
+ * @param signature signature string such as (Ljava/lang/String;)V
+ * @return array of argument types
+ */
+ public static Type[] getArgumentTypes( String signature ) {
+ List vec = new ArrayList();
+ int index;
+ Type[] types;
+ try { // Read all declarations between for `(' and `)'
+ if (signature.charAt(0) != '(') {
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ index = 1; // current string position
+ while (signature.charAt(index) != ')') {
+ vec.add(getType(signature.substring(index)));
+ //corrected concurrent private static field acess
+ index += unwrap(consumed_chars); // update position
+ }
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ types = new Type[vec.size()];
+ vec.toArray(types);
+ return types;
+ }
+
+
+ /** Convert runtime java.lang.Class to BCEL Type object.
+ * @param cl Java class
+ * @return corresponding Type object
+ */
+ public static Type getType( java.lang.Class cl ) {
+ if (cl == null) {
+ throw new IllegalArgumentException("Class must not be null");
+ }
+ /* That's an amzingly easy case, because getName() returns
+ * the signature. That's what we would have liked anyway.
+ */
+ if (cl.isArray()) {
+ return getType(cl.getName());
+ } else if (cl.isPrimitive()) {
+ if (cl == Integer.TYPE) {
+ return INT;
+ } else if (cl == Void.TYPE) {
+ return VOID;
+ } else if (cl == Double.TYPE) {
+ return DOUBLE;
+ } else if (cl == Float.TYPE) {
+ return FLOAT;
+ } else if (cl == Boolean.TYPE) {
+ return BOOLEAN;
+ } else if (cl == Byte.TYPE) {
+ return BYTE;
+ } else if (cl == Short.TYPE) {
+ return SHORT;
+ } else if (cl == Byte.TYPE) {
+ return BYTE;
+ } else if (cl == Long.TYPE) {
+ return LONG;
+ } else if (cl == Character.TYPE) {
+ return CHAR;
+ } else {
+ throw new IllegalStateException("Ooops, what primitive type is " + cl);
+ }
+ } else { // "Real" class
+ return new ObjectType(cl.getName());
+ }
+ }
+
+
+ /**
+ * Convert runtime java.lang.Class[] to BCEL Type objects.
+ * @param classes an array of runtime class objects
+ * @return array of corresponding Type objects
+ */
+ public static Type[] getTypes( java.lang.Class[] classes ) {
+ Type[] ret = new Type[classes.length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = getType(classes[i]);
+ }
+ return ret;
+ }
+
+
+ public static String getSignature( java.lang.reflect.Method meth ) {
+ StringBuffer sb = new StringBuffer("(");
+ Class[] params = meth.getParameterTypes(); // avoid clone
+ for (int j = 0; j < params.length; j++) {
+ sb.append(getType(params[j]).getSignature());
+ }
+ sb.append(")");
+ sb.append(getType(meth.getReturnType()).getSignature());
+ return sb.toString();
+ }
+
+ private static int size(int coded) {
+ return coded & 3;
+ }
+
+ private static int consumed(int coded) {
+ return coded >> 2;
+ }
+
+ private static int encode(int size, int consumed) {
+ return consumed << 2 | size;
+ }
+
+ static int getArgumentTypesSize( String signature ) {
+ int res = 0;
+ int index;
+ Type[] types;
+ try { // Read all declarations between for `(' and `)'
+ if (signature.charAt(0) != '(') {
+ throw new ClassFormatException("Invalid method signature: " + signature);
+ }
+ index = 1; // current string position
+ while (signature.charAt(index) != ')') {
+ int coded = getTypeSize(signature.substring(index));
+ res += size(coded);
+ index += consumed(coded);
+ }
+ } catch (StringIndexOutOfBoundsException e) { // Should never occur
+ throw new ClassFormatException("Invalid method signature: " + signature, e);
+ }
+ return res;
+ }
+
+ static final int getTypeSize( String signature ) throws StringIndexOutOfBoundsException {
+ byte type = Utility.typeOfSignature(signature);
+ if (type <= Constants.T_VOID) {
+ return encode(BasicType.getType(type).getSize(), 1);
+ } else if (type == Constants.T_ARRAY) {
+ int dim = 0;
+ do { // Count dimensions
+ dim++;
+ } while (signature.charAt(dim) == '[');
+ // Recurse, but just once, if the signature is ok
+ int consumed = consumed(getTypeSize(signature.substring(dim)));
+ return encode(1, dim + consumed);
+ } else { // type == T_REFERENCE
+ int index = signature.indexOf(';'); // Look for closing `;'
+ if (index < 0) {
+ throw new ClassFormatException("Invalid signature: " + signature);
+ }
+ return encode(1, index + 1);
+ }
+ }
+
+
+ static int getReturnTypeSize(String signature) {
+ int index = signature.lastIndexOf(')') + 1;
+ return getTypeSize(signature.substring(index));
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Get the type associated with an instruction, int for ILOAD, or the type
+ * of the field of a PUTFIELD instruction, e.g..
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface TypedInstruction {
+
+ public Type getType( ConstantPoolGen cpg );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an instruction to perform an unconditional branch, i.e., GOTO, JSR.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+
+ * @see GOTO
+ * @see JSR
+ */
+public interface UnconditionalBranch {
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Denotes an instruction to be a variable length instruction, such as
+ * GOTO, JSR, LOOKUPSWITCH and TABLESWITCH.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+
+ * @see GOTO
+ * @see JSR
+ * @see LOOKUPSWITCH
+ * @see TABLESWITCH
+ */
+public interface VariableLengthInstruction {
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.generic;
+
+/**
+ * Interface implementing the Visitor pattern programming style.
+ * I.e., a class that implements this interface can handle all types of
+ * instructions with the properly typed methods just by calling the accept()
+ * method.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public interface Visitor {
+
+ public void visitStackInstruction( StackInstruction obj );
+
+
+ public void visitLocalVariableInstruction( LocalVariableInstruction obj );
+
+
+ public void visitBranchInstruction( BranchInstruction obj );
+
+
+ public void visitLoadClass( LoadClass obj );
+
+
+ public void visitFieldInstruction( FieldInstruction obj );
+
+
+ public void visitIfInstruction( IfInstruction obj );
+
+
+ public void visitConversionInstruction( ConversionInstruction obj );
+
+
+ public void visitPopInstruction( PopInstruction obj );
+
+
+ public void visitStoreInstruction( StoreInstruction obj );
+
+
+ public void visitTypedInstruction( TypedInstruction obj );
+
+
+ public void visitSelect( Select obj );
+
+
+ public void visitJsrInstruction( JsrInstruction obj );
+
+
+ public void visitGotoInstruction( GotoInstruction obj );
+
+
+ public void visitUnconditionalBranch( UnconditionalBranch obj );
+
+
+ public void visitPushInstruction( PushInstruction obj );
+
+
+ public void visitArithmeticInstruction( ArithmeticInstruction obj );
+
+
+ public void visitCPInstruction( CPInstruction obj );
+
+
+ public void visitInvokeInstruction( InvokeInstruction obj );
+
+
+ public void visitArrayInstruction( ArrayInstruction obj );
+
+
+ public void visitAllocationInstruction( AllocationInstruction obj );
+
+
+ public void visitReturnInstruction( ReturnInstruction obj );
+
+
+ public void visitFieldOrMethod( FieldOrMethod obj );
+
+
+ public void visitConstantPushInstruction( ConstantPushInstruction obj );
+
+
+ public void visitExceptionThrower( ExceptionThrower obj );
+
+
+ public void visitLoadInstruction( LoadInstruction obj );
+
+
+ public void visitVariableLengthInstruction( VariableLengthInstruction obj );
+
+
+ public void visitStackProducer( StackProducer obj );
+
+
+ public void visitStackConsumer( StackConsumer obj );
+
+
+ public void visitACONST_NULL( ACONST_NULL obj );
+
+
+ public void visitGETSTATIC( GETSTATIC obj );
+
+
+ public void visitIF_ICMPLT( IF_ICMPLT obj );
+
+
+ public void visitMONITOREXIT( MONITOREXIT obj );
+
+
+ public void visitIFLT( IFLT obj );
+
+
+ public void visitLSTORE( LSTORE obj );
+
+
+ public void visitPOP2( POP2 obj );
+
+
+ public void visitBASTORE( BASTORE obj );
+
+
+ public void visitISTORE( ISTORE obj );
+
+
+ public void visitCHECKCAST( CHECKCAST obj );
+
+
+ public void visitFCMPG( FCMPG obj );
+
+
+ public void visitI2F( I2F obj );
+
+
+ public void visitATHROW( ATHROW obj );
+
+
+ public void visitDCMPL( DCMPL obj );
+
+
+ public void visitARRAYLENGTH( ARRAYLENGTH obj );
+
+
+ public void visitDUP( DUP obj );
+
+
+ public void visitINVOKESTATIC( INVOKESTATIC obj );
+
+
+ public void visitLCONST( LCONST obj );
+
+
+ public void visitDREM( DREM obj );
+
+
+ public void visitIFGE( IFGE obj );
+
+
+ public void visitCALOAD( CALOAD obj );
+
+
+ public void visitLASTORE( LASTORE obj );
+
+
+ public void visitI2D( I2D obj );
+
+
+ public void visitDADD( DADD obj );
+
+
+ public void visitINVOKESPECIAL( INVOKESPECIAL obj );
+
+
+ public void visitIAND( IAND obj );
+
+
+ public void visitPUTFIELD( PUTFIELD obj );
+
+
+ public void visitILOAD( ILOAD obj );
+
+
+ public void visitDLOAD( DLOAD obj );
+
+
+ public void visitDCONST( DCONST obj );
+
+
+ public void visitNEW( NEW obj );
+
+
+ public void visitIFNULL( IFNULL obj );
+
+
+ public void visitLSUB( LSUB obj );
+
+
+ public void visitL2I( L2I obj );
+
+
+ public void visitISHR( ISHR obj );
+
+
+ public void visitTABLESWITCH( TABLESWITCH obj );
+
+
+ public void visitIINC( IINC obj );
+
+
+ public void visitDRETURN( DRETURN obj );
+
+
+ public void visitFSTORE( FSTORE obj );
+
+
+ public void visitDASTORE( DASTORE obj );
+
+
+ public void visitIALOAD( IALOAD obj );
+
+
+ public void visitDDIV( DDIV obj );
+
+
+ public void visitIF_ICMPGE( IF_ICMPGE obj );
+
+
+ public void visitLAND( LAND obj );
+
+
+ public void visitIDIV( IDIV obj );
+
+
+ public void visitLOR( LOR obj );
+
+
+ public void visitCASTORE( CASTORE obj );
+
+
+ public void visitFREM( FREM obj );
+
+
+ public void visitLDC( LDC obj );
+
+
+ public void visitBIPUSH( BIPUSH obj );
+
+
+ public void visitDSTORE( DSTORE obj );
+
+
+ public void visitF2L( F2L obj );
+
+
+ public void visitFMUL( FMUL obj );
+
+
+ public void visitLLOAD( LLOAD obj );
+
+
+ public void visitJSR( JSR obj );
+
+
+ public void visitFSUB( FSUB obj );
+
+
+ public void visitSASTORE( SASTORE obj );
+
+
+ public void visitALOAD( ALOAD obj );
+
+
+ public void visitDUP2_X2( DUP2_X2 obj );
+
+
+ public void visitRETURN( RETURN obj );
+
+
+ public void visitDALOAD( DALOAD obj );
+
+
+ public void visitSIPUSH( SIPUSH obj );
+
+
+ public void visitDSUB( DSUB obj );
+
+
+ public void visitL2F( L2F obj );
+
+
+ public void visitIF_ICMPGT( IF_ICMPGT obj );
+
+
+ public void visitF2D( F2D obj );
+
+
+ public void visitI2L( I2L obj );
+
+
+ public void visitIF_ACMPNE( IF_ACMPNE obj );
+
+
+ public void visitPOP( POP obj );
+
+
+ public void visitI2S( I2S obj );
+
+
+ public void visitIFEQ( IFEQ obj );
+
+
+ public void visitSWAP( SWAP obj );
+
+
+ public void visitIOR( IOR obj );
+
+
+ public void visitIREM( IREM obj );
+
+
+ public void visitIASTORE( IASTORE obj );
+
+
+ public void visitNEWARRAY( NEWARRAY obj );
+
+
+ public void visitINVOKEINTERFACE( INVOKEINTERFACE obj );
+
+
+ public void visitINEG( INEG obj );
+
+
+ public void visitLCMP( LCMP obj );
+
+
+ public void visitJSR_W( JSR_W obj );
+
+
+ public void visitMULTIANEWARRAY( MULTIANEWARRAY obj );
+
+
+ public void visitDUP_X2( DUP_X2 obj );
+
+
+ public void visitSALOAD( SALOAD obj );
+
+
+ public void visitIFNONNULL( IFNONNULL obj );
+
+
+ public void visitDMUL( DMUL obj );
+
+
+ public void visitIFNE( IFNE obj );
+
+
+ public void visitIF_ICMPLE( IF_ICMPLE obj );
+
+
+ public void visitLDC2_W( LDC2_W obj );
+
+
+ public void visitGETFIELD( GETFIELD obj );
+
+
+ public void visitLADD( LADD obj );
+
+
+ public void visitNOP( NOP obj );
+
+
+ public void visitFALOAD( FALOAD obj );
+
+
+ public void visitINSTANCEOF( INSTANCEOF obj );
+
+
+ public void visitIFLE( IFLE obj );
+
+
+ public void visitLXOR( LXOR obj );
+
+
+ public void visitLRETURN( LRETURN obj );
+
+
+ public void visitFCONST( FCONST obj );
+
+
+ public void visitIUSHR( IUSHR obj );
+
+
+ public void visitBALOAD( BALOAD obj );
+
+
+ public void visitDUP2( DUP2 obj );
+
+
+ public void visitIF_ACMPEQ( IF_ACMPEQ obj );
+
+
+ public void visitIMPDEP1( IMPDEP1 obj );
+
+
+ public void visitMONITORENTER( MONITORENTER obj );
+
+
+ public void visitLSHL( LSHL obj );
+
+
+ public void visitDCMPG( DCMPG obj );
+
+
+ public void visitD2L( D2L obj );
+
+
+ public void visitIMPDEP2( IMPDEP2 obj );
+
+
+ public void visitL2D( L2D obj );
+
+
+ public void visitRET( RET obj );
+
+
+ public void visitIFGT( IFGT obj );
+
+
+ public void visitIXOR( IXOR obj );
+
+
+ public void visitINVOKEVIRTUAL( INVOKEVIRTUAL obj );
+
+
+ public void visitFASTORE( FASTORE obj );
+
+
+ public void visitIRETURN( IRETURN obj );
+
+
+ public void visitIF_ICMPNE( IF_ICMPNE obj );
+
+
+ public void visitFLOAD( FLOAD obj );
+
+
+ public void visitLDIV( LDIV obj );
+
+
+ public void visitPUTSTATIC( PUTSTATIC obj );
+
+
+ public void visitAALOAD( AALOAD obj );
+
+
+ public void visitD2I( D2I obj );
+
+
+ public void visitIF_ICMPEQ( IF_ICMPEQ obj );
+
+
+ public void visitAASTORE( AASTORE obj );
+
+
+ public void visitARETURN( ARETURN obj );
+
+
+ public void visitDUP2_X1( DUP2_X1 obj );
+
+
+ public void visitFNEG( FNEG obj );
+
+
+ public void visitGOTO_W( GOTO_W obj );
+
+
+ public void visitD2F( D2F obj );
+
+
+ public void visitGOTO( GOTO obj );
+
+
+ public void visitISUB( ISUB obj );
+
+
+ public void visitF2I( F2I obj );
+
+
+ public void visitDNEG( DNEG obj );
+
+
+ public void visitICONST( ICONST obj );
+
+
+ public void visitFDIV( FDIV obj );
+
+
+ public void visitI2B( I2B obj );
+
+
+ public void visitLNEG( LNEG obj );
+
+
+ public void visitLREM( LREM obj );
+
+
+ public void visitIMUL( IMUL obj );
+
+
+ public void visitIADD( IADD obj );
+
+
+ public void visitLSHR( LSHR obj );
+
+
+ public void visitLOOKUPSWITCH( LOOKUPSWITCH obj );
+
+
+ public void visitDUP_X1( DUP_X1 obj );
+
+
+ public void visitFCMPL( FCMPL obj );
+
+
+ public void visitI2C( I2C obj );
+
+
+ public void visitLMUL( LMUL obj );
+
+
+ public void visitLUSHR( LUSHR obj );
+
+
+ public void visitISHL( ISHL obj );
+
+
+ public void visitLALOAD( LALOAD obj );
+
+
+ public void visitASTORE( ASTORE obj );
+
+
+ public void visitANEWARRAY( ANEWARRAY obj );
+
+
+ public void visitFRETURN( FRETURN obj );
+
+
+ public void visitFADD( FADD obj );
+
+
+ public void visitBREAKPOINT( BREAKPOINT obj );
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+$Id$
+-->
+</head>
+<body bgcolor="white">
+<p>
+This package contains the "generic" part of the
+<a href="http://jakarta.apache.org/bcel/">Byte Code Engineering
+Library</a>, i.e., classes to dynamically modify class objects and
+byte code instructions.
+</p>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+$Id$
+-->
+</head>
+<body bgcolor="white">
+<p>
+This package contains basic classes for the
+<a href="http://jakarta.apache.org/bcel/">Byte Code Engineering Library</a>
+ and constants defined by the
+<a href="http://java.sun.com/docs/books/vmspec/html/VMSpecTOC.doc.html">
+ JVM specification</a>.
+</p>
+</body>
+</html>
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Code;
+import org.apache.tomcat.util.bcel.classfile.CodeException;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.ConstantValue;
+import org.apache.tomcat.util.bcel.classfile.ExceptionTable;
+import org.apache.tomcat.util.bcel.classfile.InnerClass;
+import org.apache.tomcat.util.bcel.classfile.InnerClasses;
+import org.apache.tomcat.util.bcel.classfile.LineNumber;
+import org.apache.tomcat.util.bcel.classfile.LineNumberTable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariableTable;
+import org.apache.tomcat.util.bcel.classfile.SourceFile;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Convert found attributes into HTML file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ *
+ */
+final class AttributeHTML implements org.apache.tomcat.util.bcel.Constants {
+
+ private String class_name; // name of current class
+ private PrintWriter file; // file to write to
+ private int attr_count = 0;
+ private ConstantHTML constant_html;
+ private ConstantPool constant_pool;
+
+
+ AttributeHTML(String dir, String class_name, ConstantPool constant_pool,
+ ConstantHTML constant_html) throws IOException {
+ this.class_name = class_name;
+ this.constant_pool = constant_pool;
+ this.constant_html = constant_html;
+ file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
+ file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
+ }
+
+
+ private final String codeLink( int link, int method_number ) {
+ return "<A HREF=\"" + class_name + "_code.html#code" + method_number + "@" + link
+ + "\" TARGET=Code>" + link + "</A>";
+ }
+
+
+ final void close() {
+ file.println("</TABLE></BODY></HTML>");
+ file.close();
+ }
+
+
+ final void writeAttribute( Attribute attribute, String anchor ) throws IOException {
+ writeAttribute(attribute, anchor, 0);
+ }
+
+
+ final void writeAttribute( Attribute attribute, String anchor, int method_number )
+ throws IOException {
+ byte tag = attribute.getTag();
+ int index;
+ if (tag == ATTR_UNKNOWN) {
+ return;
+ }
+ attr_count++; // Increment number of attributes found so far
+ if (attr_count % 2 == 0) {
+ file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
+ } else {
+ file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
+ }
+ file.println("<H4><A NAME=\"" + anchor + "\">" + attr_count + " " + ATTRIBUTE_NAMES[tag]
+ + "</A></H4>");
+ /* Handle different attributes
+ */
+ switch (tag) {
+ case ATTR_CODE:
+ Code c = (Code) attribute;
+ // Some directly printable values
+ file.print("<UL><LI>Maximum stack size = " + c.getMaxStack()
+ + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
+ + "</LI>\n<LI><A HREF=\"" + class_name + "_code.html#method"
+ + method_number + "\" TARGET=Code>Byte code</A></LI></UL>\n");
+ // Get handled exceptions and list them
+ CodeException[] ce = c.getExceptionTable();
+ int len = ce.length;
+ if (len > 0) {
+ file.print("<P><B>Exceptions handled</B><UL>");
+ for (int i = 0; i < len; i++) {
+ int catch_type = ce[i].getCatchType(); // Index in constant pool
+ file.print("<LI>");
+ if (catch_type != 0) {
+ file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html
+ } else {
+ file.print("Any Exception");
+ }
+ file.print("<BR>(Ranging from lines "
+ + codeLink(ce[i].getStartPC(), method_number) + " to "
+ + codeLink(ce[i].getEndPC(), method_number) + ", handled at line "
+ + codeLink(ce[i].getHandlerPC(), method_number) + ")</LI>");
+ }
+ file.print("</UL>");
+ }
+ break;
+ case ATTR_CONSTANT_VALUE:
+ index = ((ConstantValue) attribute).getConstantValueIndex();
+ // Reference _cp.html
+ file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
+ + "\" TARGET=\"ConstantPool\">Constant value index(" + index
+ + ")</A></UL>\n");
+ break;
+ case ATTR_SOURCE_FILE:
+ index = ((SourceFile) attribute).getSourceFileIndex();
+ // Reference _cp.html
+ file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
+ + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
+ break;
+ case ATTR_EXCEPTIONS:
+ // List thrown exceptions
+ int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
+ file.print("<UL>");
+ for (int i = 0; i < indices.length; i++) {
+ file.print("<LI><A HREF=\"" + class_name + "_cp.html#cp" + indices[i]
+ + "\" TARGET=\"ConstantPool\">Exception class index(" + indices[i]
+ + ")</A>\n");
+ }
+ file.print("</UL>\n");
+ break;
+ case ATTR_LINE_NUMBER_TABLE:
+ LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable();
+ // List line number pairs
+ file.print("<P>");
+ for (int i = 0; i < line_numbers.length; i++) {
+ file.print("(" + line_numbers[i].getStartPC() + ", "
+ + line_numbers[i].getLineNumber() + ")");
+ if (i < line_numbers.length - 1) {
+ file.print(", "); // breakable
+ }
+ }
+ break;
+ case ATTR_LOCAL_VARIABLE_TABLE:
+ LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable();
+ // List name, range and type
+ file.print("<UL>");
+ for (int i = 0; i < vars.length; i++) {
+ index = vars[i].getSignatureIndex();
+ String signature = ((ConstantUtf8) constant_pool.getConstant(index,
+ CONSTANT_Utf8)).getBytes();
+ signature = Utility.signatureToString(signature, false);
+ int start = vars[i].getStartPC();
+ int end = (start + vars[i].getLength());
+ file.println("<LI>" + Class2HTML.referenceType(signature) + " <B>"
+ + vars[i].getName() + "</B> in slot %" + vars[i].getIndex()
+ + "<BR>Valid from lines " + "<A HREF=\"" + class_name
+ + "_code.html#code" + method_number + "@" + start + "\" TARGET=Code>"
+ + start + "</A> to " + "<A HREF=\"" + class_name + "_code.html#code"
+ + method_number + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
+ }
+ file.print("</UL>\n");
+ break;
+ case ATTR_INNER_CLASSES:
+ InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses();
+ // List inner classes
+ file.print("<UL>");
+ for (int i = 0; i < classes.length; i++) {
+ String name, access;
+ index = classes[i].getInnerNameIndex();
+ if (index > 0) {
+ name = ((ConstantUtf8) constant_pool.getConstant(index, CONSTANT_Utf8))
+ .getBytes();
+ } else {
+ name = "<anonymous>";
+ }
+ access = Utility.accessToString(classes[i].getInnerAccessFlags());
+ file.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> "
+ + constant_html.referenceConstant(classes[i].getInnerClassIndex())
+ + " in class "
+ + constant_html.referenceConstant(classes[i].getOuterClassIndex())
+ + " named " + name + "</LI>\n");
+ }
+ file.print("</UL>\n");
+ break;
+ default: // Such as Unknown attribute or Deprecated
+ file.print("<P>" + attribute.toString());
+ }
+ file.println("</TD></TR>");
+ file.flush();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+/**
+ * Used for BCEL comparison strategy
+ *
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @version $Id$
+ * @since 5.2
+ */
+public interface BCELComparator {
+
+ /**
+ * Compare two objects and return what THIS.equals(THAT) should return
+ *
+ * @param THIS
+ * @param THAT
+ * @return true if and only if THIS equals THAT
+ */
+ public boolean equals( Object THIS, Object THAT );
+
+
+ /**
+ * Return hashcode for THIS.hashCode()
+ *
+ * @param THIS
+ * @return hashcode for THIS.hashCode()
+ */
+ public int hashCode( Object THIS );
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+import org.apache.tomcat.util.bcel.generic.AllocationInstruction;
+import org.apache.tomcat.util.bcel.generic.ArrayInstruction;
+import org.apache.tomcat.util.bcel.generic.ArrayType;
+import org.apache.tomcat.util.bcel.generic.BranchHandle;
+import org.apache.tomcat.util.bcel.generic.BranchInstruction;
+import org.apache.tomcat.util.bcel.generic.CHECKCAST;
+import org.apache.tomcat.util.bcel.generic.CPInstruction;
+import org.apache.tomcat.util.bcel.generic.CodeExceptionGen;
+import org.apache.tomcat.util.bcel.generic.ConstantPoolGen;
+import org.apache.tomcat.util.bcel.generic.ConstantPushInstruction;
+import org.apache.tomcat.util.bcel.generic.EmptyVisitor;
+import org.apache.tomcat.util.bcel.generic.FieldInstruction;
+import org.apache.tomcat.util.bcel.generic.IINC;
+import org.apache.tomcat.util.bcel.generic.INSTANCEOF;
+import org.apache.tomcat.util.bcel.generic.Instruction;
+import org.apache.tomcat.util.bcel.generic.InstructionConstants;
+import org.apache.tomcat.util.bcel.generic.InstructionHandle;
+import org.apache.tomcat.util.bcel.generic.InvokeInstruction;
+import org.apache.tomcat.util.bcel.generic.LDC;
+import org.apache.tomcat.util.bcel.generic.LDC2_W;
+import org.apache.tomcat.util.bcel.generic.LocalVariableInstruction;
+import org.apache.tomcat.util.bcel.generic.MULTIANEWARRAY;
+import org.apache.tomcat.util.bcel.generic.MethodGen;
+import org.apache.tomcat.util.bcel.generic.NEWARRAY;
+import org.apache.tomcat.util.bcel.generic.ObjectType;
+import org.apache.tomcat.util.bcel.generic.RET;
+import org.apache.tomcat.util.bcel.generic.ReturnInstruction;
+import org.apache.tomcat.util.bcel.generic.Select;
+import org.apache.tomcat.util.bcel.generic.Type;
+
+/**
+ * Factory creates il.append() statements, and sets instruction targets.
+ * A helper class for BCELifier.
+ *
+ * @see BCELifier
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+class BCELFactory extends EmptyVisitor {
+
+ private MethodGen _mg;
+ private PrintWriter _out;
+ private ConstantPoolGen _cp;
+
+
+ BCELFactory(MethodGen mg, PrintWriter out) {
+ _mg = mg;
+ _cp = mg.getConstantPool();
+ _out = out;
+ }
+
+ private Map branch_map = new HashMap(); // Map<Instruction, InstructionHandle>
+
+
+ public void start() {
+ if (!_mg.isAbstract() && !_mg.isNative()) {
+ for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih
+ .getNext()) {
+ Instruction i = ih.getInstruction();
+ if (i instanceof BranchInstruction) {
+ branch_map.put(i, ih); // memorize container
+ }
+ if (ih.hasTargeters()) {
+ if (i instanceof BranchInstruction) {
+ _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
+ } else {
+ _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
+ }
+ } else {
+ _out.print(" ");
+ }
+ if (!visitInstruction(i)) {
+ i.accept(this);
+ }
+ }
+ updateBranchTargets();
+ updateExceptionHandlers();
+ }
+ }
+
+
+ private boolean visitInstruction( Instruction i ) {
+ short opcode = i.getOpcode();
+ if ((InstructionConstants.INSTRUCTIONS[opcode] != null)
+ && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction)) { // Handled below
+ _out.println("il.append(InstructionConstants."
+ + i.getName().toUpperCase(Locale.ENGLISH) + ");");
+ return true;
+ }
+ return false;
+ }
+
+
+ public void visitLocalVariableInstruction( LocalVariableInstruction i ) {
+ short opcode = i.getOpcode();
+ Type type = i.getType(_cp);
+ if (opcode == Constants.IINC) {
+ _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement()
+ + "));");
+ } else {
+ String kind = (opcode < Constants.ISTORE) ? "Load" : "Store";
+ _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type)
+ + ", " + i.getIndex() + "));");
+ }
+ }
+
+
+ public void visitArrayInstruction( ArrayInstruction i ) {
+ short opcode = i.getOpcode();
+ Type type = i.getType(_cp);
+ String kind = (opcode < Constants.IASTORE) ? "Load" : "Store";
+ _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type)
+ + "));");
+ }
+
+
+ public void visitFieldInstruction( FieldInstruction i ) {
+ short opcode = i.getOpcode();
+ String class_name = i.getClassName(_cp);
+ String field_name = i.getFieldName(_cp);
+ Type type = i.getFieldType(_cp);
+ _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name
+ + "\", " + BCELifier.printType(type) + ", " + "Constants."
+ + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));");
+ }
+
+
+ public void visitInvokeInstruction( InvokeInstruction i ) {
+ short opcode = i.getOpcode();
+ String class_name = i.getClassName(_cp);
+ String method_name = i.getMethodName(_cp);
+ Type type = i.getReturnType(_cp);
+ Type[] arg_types = i.getArgumentTypes(_cp);
+ _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name
+ + "\", " + BCELifier.printType(type) + ", "
+ + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants."
+ + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));");
+ }
+
+
+ public void visitAllocationInstruction( AllocationInstruction i ) {
+ Type type;
+ if (i instanceof CPInstruction) {
+ type = ((CPInstruction) i).getType(_cp);
+ } else {
+ type = ((NEWARRAY) i).getType();
+ }
+ short opcode = ((Instruction) i).getOpcode();
+ int dim = 1;
+ switch (opcode) {
+ case Constants.NEW:
+ _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName()
+ + "\"));");
+ break;
+ case Constants.MULTIANEWARRAY:
+ dim = ((MULTIANEWARRAY) i).getDimensions();
+ /* FALL THRU */
+ case Constants.ANEWARRAY:
+ case Constants.NEWARRAY:
+ if (type instanceof ArrayType) {
+ type = ((ArrayType) type).getBasicType();
+ }
+ _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type)
+ + ", (short) " + dim + "));");
+ break;
+ default:
+ throw new RuntimeException("Oops: " + opcode);
+ }
+ }
+
+
+ private void createConstant( Object value ) {
+ String embed = value.toString();
+ if (value instanceof String) {
+ embed = '"' + Utility.convertString(embed) + '"';
+ } else if (value instanceof Character) {
+ embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
+ } else if (value instanceof Float) {
+ embed += "f";
+ } else if (value instanceof Long) {
+ embed += "L";
+ }
+ _out.println("il.append(new PUSH(_cp, " + embed + "));");
+ }
+
+
+ public void visitLDC( LDC i ) {
+ createConstant(i.getValue(_cp));
+ }
+
+
+ public void visitLDC2_W( LDC2_W i ) {
+ createConstant(i.getValue(_cp));
+ }
+
+
+ public void visitConstantPushInstruction( ConstantPushInstruction i ) {
+ createConstant(i.getValue());
+ }
+
+
+ public void visitINSTANCEOF( INSTANCEOF i ) {
+ Type type = i.getType(_cp);
+ _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));");
+ }
+
+
+ public void visitCHECKCAST( CHECKCAST i ) {
+ Type type = i.getType(_cp);
+ _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));");
+ }
+
+
+ public void visitReturnInstruction( ReturnInstruction i ) {
+ Type type = i.getType(_cp);
+ _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));");
+ }
+
+ // Memorize BranchInstructions that need an update
+ private List branches = new ArrayList();
+
+
+ public void visitBranchInstruction( BranchInstruction bi ) {
+ BranchHandle bh = (BranchHandle) branch_map.get(bi);
+ int pos = bh.getPosition();
+ String name = bi.getName() + "_" + pos;
+ if (bi instanceof Select) {
+ Select s = (Select) bi;
+ branches.add(bi);
+ StringBuffer args = new StringBuffer("new int[] { ");
+ int[] matchs = s.getMatchs();
+ for (int i = 0; i < matchs.length; i++) {
+ args.append(matchs[i]);
+ if (i < matchs.length - 1) {
+ args.append(", ");
+ }
+ }
+ args.append(" }");
+ _out.print("Select " + name + " = new " + bi.getName().toUpperCase(Locale.ENGLISH)
+ + "(" + args + ", new InstructionHandle[] { ");
+ for (int i = 0; i < matchs.length; i++) {
+ _out.print("null");
+ if (i < matchs.length - 1) {
+ _out.print(", ");
+ }
+ }
+ _out.println(" }, null);");
+ } else {
+ int t_pos = bh.getTarget().getPosition();
+ String target;
+ if (pos > t_pos) {
+ target = "ih_" + t_pos;
+ } else {
+ branches.add(bi);
+ target = "null";
+ }
+ _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction("
+ + "Constants." + bi.getName().toUpperCase(Locale.ENGLISH) + ", " + target
+ + ");");
+ }
+ if (bh.hasTargeters()) {
+ _out.println(" ih_" + pos + " = il.append(" + name + ");");
+ } else {
+ _out.println(" il.append(" + name + ");");
+ }
+ }
+
+
+ public void visitRET( RET i ) {
+ _out.println("il.append(new RET(" + i.getIndex() + ")));");
+ }
+
+
+ private void updateBranchTargets() {
+ for (Iterator i = branches.iterator(); i.hasNext();) {
+ BranchInstruction bi = (BranchInstruction) i.next();
+ BranchHandle bh = (BranchHandle) branch_map.get(bi);
+ int pos = bh.getPosition();
+ String name = bi.getName() + "_" + pos;
+ int t_pos = bh.getTarget().getPosition();
+ _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
+ if (bi instanceof Select) {
+ InstructionHandle[] ihs = ((Select) bi).getTargets();
+ for (int j = 0; j < ihs.length; j++) {
+ t_pos = ihs[j].getPosition();
+ _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");");
+ }
+ }
+ }
+ }
+
+
+ private void updateExceptionHandlers() {
+ CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
+ for (int i = 0; i < handlers.length; i++) {
+ CodeExceptionGen h = handlers[i];
+ String type = (h.getCatchType() == null) ? "null" : BCELifier.printType(h
+ .getCatchType());
+ _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition()
+ + ", " + "ih_" + h.getEndPC().getPosition() + ", " + "ih_"
+ + h.getHandlerPC().getPosition() + ", " + type + ");");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Locale;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.Repository;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.ConstantValue;
+import org.apache.tomcat.util.bcel.classfile.Field;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+import org.apache.tomcat.util.bcel.generic.ArrayType;
+import org.apache.tomcat.util.bcel.generic.ConstantPoolGen;
+import org.apache.tomcat.util.bcel.generic.MethodGen;
+import org.apache.tomcat.util.bcel.generic.Type;
+
+/**
+ * This class takes a given JavaClass object and converts it to a
+ * Java program that creates that very class using BCEL. This
+ * gives new users of BCEL a useful example showing how things
+ * are done with BCEL. It does not cover all features of BCEL,
+ * but tries to mimic hand-written code as close as possible.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class BCELifier extends org.apache.tomcat.util.bcel.classfile.EmptyVisitor {
+
+ private static final int FLAG_FOR_UNKNOWN = -1;
+ private static final int FLAG_FOR_CLASS = 0;
+ private static final int FLAG_FOR_METHOD = 1;
+ private JavaClass _clazz;
+ private PrintWriter _out;
+ private ConstantPoolGen _cp;
+
+
+ /** @param clazz Java class to "decompile"
+ * @param out where to output Java program
+ */
+ public BCELifier(JavaClass clazz, OutputStream out) {
+ _clazz = clazz;
+ _out = new PrintWriter(out);
+ _cp = new ConstantPoolGen(_clazz.getConstantPool());
+ }
+
+
+ /** Start Java code generation
+ */
+ public void start() {
+ visitJavaClass(_clazz);
+ _out.flush();
+ }
+
+
+ public void visitJavaClass( JavaClass clazz ) {
+ String class_name = clazz.getClassName();
+ String super_name = clazz.getSuperclassName();
+ String package_name = clazz.getPackageName();
+ String inter = Utility.printArray(clazz.getInterfaceNames(), false, true);
+ if (!"".equals(package_name)) {
+ class_name = class_name.substring(package_name.length() + 1);
+ _out.println("package " + package_name + ";");
+ _out.println();
+ }
+ _out.println("import org.apache.tomcat.util.bcel.generic.*;");
+ _out.println("import org.apache.tomcat.util.bcel.classfile.*;");
+ _out.println("import org.apache.tomcat.util.bcel.*;");
+ _out.println("import java.io.*;");
+ _out.println();
+ _out.println("public class " + class_name + "Creator implements Constants {");
+ _out.println(" private InstructionFactory _factory;");
+ _out.println(" private ConstantPoolGen _cp;");
+ _out.println(" private ClassGen _cg;");
+ _out.println();
+ _out.println(" public " + class_name + "Creator() {");
+ _out.println(" _cg = new ClassGen(\""
+ + (("".equals(package_name)) ? class_name : package_name + "." + class_name)
+ + "\", \"" + super_name + "\", " + "\"" + clazz.getSourceFileName() + "\", "
+ + printFlags(clazz.getAccessFlags(), FLAG_FOR_CLASS) + ", " + "new String[] { "
+ + inter + " });");
+ _out.println();
+ _out.println(" _cp = _cg.getConstantPool();");
+ _out.println(" _factory = new InstructionFactory(_cg, _cp);");
+ _out.println(" }");
+ _out.println();
+ printCreate();
+ Field[] fields = clazz.getFields();
+ if (fields.length > 0) {
+ _out.println(" private void createFields() {");
+ _out.println(" FieldGen field;");
+ for (int i = 0; i < fields.length; i++) {
+ fields[i].accept(this);
+ }
+ _out.println(" }");
+ _out.println();
+ }
+ Method[] methods = clazz.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ _out.println(" private void createMethod_" + i + "() {");
+ methods[i].accept(this);
+ _out.println(" }");
+ _out.println();
+ }
+ printMain();
+ _out.println("}");
+ }
+
+
+ private void printCreate() {
+ _out.println(" public void create(OutputStream out) throws IOException {");
+ Field[] fields = _clazz.getFields();
+ if (fields.length > 0) {
+ _out.println(" createFields();");
+ }
+ Method[] methods = _clazz.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ _out.println(" createMethod_" + i + "();");
+ }
+ _out.println(" _cg.getJavaClass().dump(out);");
+ _out.println(" }");
+ _out.println();
+ }
+
+
+ private void printMain() {
+ String class_name = _clazz.getClassName();
+ _out.println(" public static void main(String[] args) throws Exception {");
+ _out.println(" " + class_name + "Creator creator = new " + class_name + "Creator();");
+ _out.println(" creator.create(new FileOutputStream(\"" + class_name + ".class\"));");
+ _out.println(" }");
+ }
+
+
+ public void visitField( Field field ) {
+ _out.println();
+ _out.println(" field = new FieldGen(" + printFlags(field.getAccessFlags()) + ", "
+ + printType(field.getSignature()) + ", \"" + field.getName() + "\", _cp);");
+ ConstantValue cv = field.getConstantValue();
+ if (cv != null) {
+ String value = cv.toString();
+ _out.println(" field.setInitValue(" + value + ")");
+ }
+ _out.println(" _cg.addField(field.getField());");
+ }
+
+
+ public void visitMethod( Method method ) {
+ MethodGen mg = new MethodGen(method, _clazz.getClassName(), _cp);
+ Type result_type = mg.getReturnType();
+ Type[] arg_types = mg.getArgumentTypes();
+ _out.println(" InstructionList il = new InstructionList();");
+ _out.println(" MethodGen method = new MethodGen("
+ + printFlags(method.getAccessFlags(), FLAG_FOR_METHOD) + ", "
+ + printType(result_type) + ", " + printArgumentTypes(arg_types) + ", "
+ + "new String[] { " + Utility.printArray(mg.getArgumentNames(), false, true)
+ + " }, \"" + method.getName() + "\", \"" + _clazz.getClassName() + "\", il, _cp);");
+ _out.println();
+ BCELFactory factory = new BCELFactory(mg, _out);
+ factory.start();
+ _out.println(" method.setMaxStack();");
+ _out.println(" method.setMaxLocals();");
+ _out.println(" _cg.addMethod(method.getMethod());");
+ _out.println(" il.dispose();");
+ }
+
+
+ static String printFlags( int flags ) {
+ return printFlags(flags, FLAG_FOR_UNKNOWN);
+ }
+
+
+ static String printFlags( int flags, int reason ) {
+ if (flags == 0) {
+ return "0";
+ }
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0, pow = 1; pow <= Constants.MAX_ACC_FLAG; i++) {
+ if ((flags & pow) != 0) {
+ if ((pow == Constants.ACC_SYNCHRONIZED) && (reason == FLAG_FOR_CLASS)) {
+ buf.append("ACC_SUPER | ");
+ } else if ((pow == Constants.ACC_VOLATILE) && (reason == FLAG_FOR_METHOD)) {
+ buf.append("ACC_BRIDGE | ");
+ } else if ((pow == Constants.ACC_TRANSIENT) && (reason == FLAG_FOR_METHOD)) {
+ buf.append("ACC_VARARGS | ");
+ } else {
+ buf.append("ACC_")
+ .append(Constants.ACCESS_NAMES[i].toUpperCase(Locale.ENGLISH)).append(
+ " | ");
+ }
+ }
+ pow <<= 1;
+ }
+ String str = buf.toString();
+ return str.substring(0, str.length() - 3);
+ }
+
+
+ static String printArgumentTypes( Type[] arg_types ) {
+ if (arg_types.length == 0) {
+ return "Type.NO_ARGS";
+ }
+ StringBuffer args = new StringBuffer();
+ for (int i = 0; i < arg_types.length; i++) {
+ args.append(printType(arg_types[i]));
+ if (i < arg_types.length - 1) {
+ args.append(", ");
+ }
+ }
+ return "new Type[] { " + args.toString() + " }";
+ }
+
+
+ static String printType( Type type ) {
+ return printType(type.getSignature());
+ }
+
+
+ static String printType( String signature ) {
+ Type type = Type.getType(signature);
+ byte t = type.getType();
+ if (t <= Constants.T_VOID) {
+ return "Type." + Constants.TYPE_NAMES[t].toUpperCase(Locale.ENGLISH);
+ } else if (type.toString().equals("java.lang.String")) {
+ return "Type.STRING";
+ } else if (type.toString().equals("java.lang.Object")) {
+ return "Type.OBJECT";
+ } else if (type.toString().equals("java.lang.StringBuffer")) {
+ return "Type.STRINGBUFFER";
+ } else if (type instanceof ArrayType) {
+ ArrayType at = (ArrayType) type;
+ return "new ArrayType(" + printType(at.getBasicType()) + ", " + at.getDimensions()
+ + ")";
+ } else {
+ return "new ObjectType(\"" + Utility.signatureToString(signature, false) + "\")";
+ }
+ }
+
+
+ /** Default main method
+ */
+ public static void main( String[] argv ) throws Exception {
+ JavaClass java_class;
+ String name = argv[0];
+ if ((java_class = Repository.lookupClass(name)) == null) {
+ java_class = new ClassParser(name).parse(); // May throw IOException
+ }
+ BCELifier bcelifier = new BCELifier(java_class, System.out);
+ bcelifier.start();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+
+/**
+ * Utility class that implements a sequence of bytes which can be read
+ * via the `readByte()' method. This is used to implement a wrapper for the
+ * Java byte code stream to gain some more readability.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public final class ByteSequence extends DataInputStream {
+
+ private ByteArrayStream byte_stream;
+
+
+ public ByteSequence(byte[] bytes) {
+ super(new ByteArrayStream(bytes));
+ byte_stream = (ByteArrayStream) in;
+ }
+
+
+ public final int getIndex() {
+ return byte_stream.getPosition();
+ }
+
+
+ final void unreadByte() {
+ byte_stream.unreadByte();
+ }
+
+ private static final class ByteArrayStream extends ByteArrayInputStream {
+
+ ByteArrayStream(byte[] bytes) {
+ super(bytes);
+ }
+
+
+ final int getPosition() {
+ return pos;
+ } // is protected in ByteArrayInputStream
+
+
+ final void unreadByte() {
+ if (pos > 0) {
+ pos--;
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Read class file(s) and convert them into HTML files.
+ *
+ * Given a JavaClass object "class" that is in package "package" five files
+ * will be created in the specified directory.
+ *
+ * <OL>
+ * <LI> "package"."class".html as the main file which defines the frames for
+ * the following subfiles.
+ * <LI> "package"."class"_attributes.html contains all (known) attributes found in the file
+ * <LI> "package"."class"_cp.html contains the constant pool
+ * <LI> "package"."class"_code.html contains the byte code
+ * <LI> "package"."class"_methods.html contains references to all methods and fields of the class
+ * </OL>
+ *
+ * All subfiles reference each other appropiately, e.g. clicking on a
+ * method in the Method's frame will jump to the appropiate method in
+ * the Code frame.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class Class2HTML implements Constants {
+
+ private JavaClass java_class; // current class object
+ private String dir;
+ private static String class_package; // name of package, unclean to make it static, but ...
+ private static String class_name; // name of current class, dito
+ private static ConstantPool constant_pool;
+
+
+ /**
+ * Write contents of the given JavaClass into HTML files.
+ *
+ * @param java_class The class to write
+ * @param dir The directory to put the files in
+ */
+ public Class2HTML(JavaClass java_class, String dir) throws IOException {
+ Method[] methods = java_class.getMethods();
+ this.java_class = java_class;
+ this.dir = dir;
+ class_name = java_class.getClassName(); // Remember full name
+ constant_pool = java_class.getConstantPool();
+ // Get package name by tacking off everything after the last `.'
+ int index = class_name.lastIndexOf('.');
+ if (index > -1) {
+ class_package = class_name.substring(0, index);
+ } else {
+ class_package = ""; // default package
+ }
+ ConstantHTML constant_html = new ConstantHTML(dir, class_name, class_package, methods,
+ constant_pool);
+ /* Attributes can't be written in one step, so we just open a file
+ * which will be written consequently.
+ */
+ AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool,
+ constant_html);
+// MethodHTML method_html = new MethodHTML(dir, class_name, methods, java_class.getFields(),
+// constant_html, attribute_html);
+ // Write main file (with frames, yuk)
+ writeMainHTML(attribute_html);
+ new CodeHTML(dir, class_name, methods, constant_pool, constant_html);
+ attribute_html.close();
+ }
+
+
+ public static void main( String argv[] ) {
+ String[] file_name = new String[argv.length];
+ int files = 0;
+ ClassParser parser = null;
+ JavaClass java_class = null;
+ String zip_file = null;
+ char sep = System.getProperty("file.separator").toCharArray()[0];
+ String dir = "." + sep; // Where to store HTML files
+ try {
+ /* Parse command line arguments.
+ */
+ for (int i = 0; i < argv.length; i++) {
+ if (argv[i].charAt(0) == '-') { // command line switch
+ if (argv[i].equals("-d")) { // Specify target directory, default `.�
+ dir = argv[++i];
+ if (!dir.endsWith("" + sep)) {
+ dir = dir + sep;
+ }
+ new File(dir).mkdirs(); // Create target directory if necessary
+ } else if (argv[i].equals("-zip")) {
+ zip_file = argv[++i];
+ } else {
+ System.out.println("Unknown option " + argv[i]);
+ }
+ } else {
+ file_name[files++] = argv[i];
+ }
+ }
+ if (files == 0) {
+ System.err.println("Class2HTML: No input files specified.");
+ } else { // Loop through files ...
+ for (int i = 0; i < files; i++) {
+ System.out.print("Processing " + file_name[i] + "...");
+ if (zip_file == null) {
+ parser = new ClassParser(file_name[i]); // Create parser object from file
+ } else {
+ parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file
+ }
+ java_class = parser.parse();
+ new Class2HTML(java_class, dir);
+ System.out.println("Done.");
+ }
+ }
+ } catch (Exception e) {
+ System.out.println(e);
+ e.printStackTrace(System.out);
+ }
+ }
+
+
+ /**
+ * Utility method that converts a class reference in the constant pool,
+ * i.e., an index to a string.
+ */
+ static String referenceClass( int index ) {
+ String str = constant_pool.getConstantString(index, CONSTANT_Class);
+ str = Utility.compactClassName(str);
+ str = Utility.compactClassName(str, class_package + ".", true);
+ return "<A HREF=\"" + class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + str
+ + "</A>";
+ }
+
+
+ static final String referenceType( String type ) {
+ String short_type = Utility.compactClassName(type);
+ short_type = Utility.compactClassName(short_type, class_package + ".", true);
+ int index = type.indexOf('['); // Type is an array?
+ String base_type = type;
+ if (index > -1) {
+ base_type = type.substring(0, index); // Tack of the `['
+ }
+ // test for basic type
+ if (base_type.equals("int") || base_type.equals("short") || base_type.equals("boolean")
+ || base_type.equals("void") || base_type.equals("char") || base_type.equals("byte")
+ || base_type.equals("long") || base_type.equals("double")
+ || base_type.equals("float")) {
+ return "<FONT COLOR=\"#00FF00\">" + type + "</FONT>";
+ } else {
+ return "<A HREF=\"" + base_type + ".html\" TARGET=_top>" + short_type + "</A>";
+ }
+ }
+
+
+ static String toHTML( String str ) {
+ StringBuffer buf = new StringBuffer();
+ try { // Filter any characters HTML doesn't like such as < and > in particular
+ for (int i = 0; i < str.length(); i++) {
+ char ch;
+ switch (ch = str.charAt(i)) {
+ case '<':
+ buf.append("<");
+ break;
+ case '>':
+ buf.append(">");
+ break;
+ case '\n':
+ buf.append("\\n");
+ break;
+ case '\r':
+ buf.append("\\r");
+ break;
+ default:
+ buf.append(ch);
+ }
+ }
+ } catch (StringIndexOutOfBoundsException e) {
+ } // Never occurs
+ return buf.toString();
+ }
+
+
+ private void writeMainHTML( AttributeHTML attribute_html ) throws IOException {
+ PrintWriter file = new PrintWriter(new FileOutputStream(dir + class_name + ".html"));
+ Attribute[] attributes = java_class.getAttributes();
+ file.println("<HTML>\n" + "<HEAD><TITLE>Documentation for " + class_name + "</TITLE>"
+ + "</HEAD>\n" + "<FRAMESET BORDER=1 cols=\"30%,*\">\n"
+ + "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"ConstantPool\" SRC=\""
+ + class_name + "_cp.html" + "\"\n MARGINWIDTH=\"0\" "
+ + "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n"
+ + "<FRAME NAME=\"Attributes\" SRC=\"" + class_name + "_attributes.html"
+ + "\"\n MARGINWIDTH=\"0\" "
+ + "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n" + "</FRAMESET>\n"
+ + "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"Code\" SRC=\""
+ + class_name + "_code.html\"\n MARGINWIDTH=0 "
+ + "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
+ + "<FRAME NAME=\"Methods\" SRC=\"" + class_name
+ + "_methods.html\"\n MARGINWIDTH=0 "
+ + "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
+ + "</FRAMESET></FRAMESET></HTML>");
+ file.close();
+ for (int i = 0; i < attributes.length; i++) {
+ attribute_html.writeAttribute(attributes[i], "class" + i);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.ByteArrayInputStream;
+import java.util.Hashtable;
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.ConstantClass;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * <p>Drop in replacement for the standard class loader of the JVM. You can use it
+ * in conjunction with the JavaWrapper to dynamically modify/create classes
+ * as they're requested.</p>
+ *
+ * <p>This class loader recognizes special requests in a distinct
+ * format, i.e., when the name of the requested class contains with
+ * "$$BCEL$$" it calls the createClass() method with that name
+ * (everything bevor the $$BCEL$$ is considered to be the package
+ * name. You can subclass the class loader and override that
+ * method. "Normal" classes class can be modified by overriding the
+ * modifyClass() method which is called just before defineClass().</p>
+ *
+ * <p>There may be a number of packages where you have to use the
+ * default class loader (which may also be faster). You can define the
+ * set of packages where to use the system class loader in the
+ * constructor. The default value contains "java.", "sun.",
+ * "javax."</p>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see JavaWrapper
+ * @see ClassPath
+ */
+public class ClassLoader extends java.lang.ClassLoader {
+
+ public static final String[] DEFAULT_IGNORED_PACKAGES = {
+ "java.", "javax.", "sun."
+ };
+ private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe
+ private String[] ignored_packages;
+ private Repository repository = SyntheticRepository.getInstance();
+
+
+ /** Ignored packages are by default ( "java.", "sun.",
+ * "javax."), i.e. loaded by system class loader
+ */
+ public ClassLoader() {
+ this(DEFAULT_IGNORED_PACKAGES);
+ }
+
+
+ /** @param deferTo delegate class loader to use for ignored packages
+ */
+ public ClassLoader(java.lang.ClassLoader deferTo) {
+ super(deferTo);
+ this.ignored_packages = DEFAULT_IGNORED_PACKAGES;
+ this.repository = new ClassLoaderRepository(deferTo);
+ }
+
+
+ /** @param ignored_packages classes contained in these packages will be loaded
+ * with the system class loader
+ */
+ public ClassLoader(String[] ignored_packages) {
+ this.ignored_packages = ignored_packages;
+ }
+
+
+ /** @param ignored_packages classes contained in these packages will be loaded
+ * with the system class loader
+ * @param deferTo delegate class loader to use for ignored packages
+ */
+ public ClassLoader(java.lang.ClassLoader deferTo, String[] ignored_packages) {
+ this(ignored_packages);
+ this.repository = new ClassLoaderRepository(deferTo);
+ }
+
+
+ protected Class loadClass( String class_name, boolean resolve ) throws ClassNotFoundException {
+ Class cl = null;
+ /* First try: lookup hash table.
+ */
+ if ((cl = (Class) classes.get(class_name)) == null) {
+ /* Second try: Load system class using system class loader. You better
+ * don't mess around with them.
+ */
+ for (int i = 0; i < ignored_packages.length; i++) {
+ if (class_name.startsWith(ignored_packages[i])) {
+ cl = getParent().loadClass(class_name);
+ break;
+ }
+ }
+ if (cl == null) {
+ JavaClass clazz = null;
+ /* Third try: Special request?
+ */
+ if (class_name.indexOf("$$BCEL$$") >= 0) {
+ clazz = createClass(class_name);
+ } else { // Fourth try: Load classes via repository
+ if ((clazz = repository.loadClass(class_name)) != null) {
+ clazz = modifyClass(clazz);
+ } else {
+ throw new ClassNotFoundException(class_name);
+ }
+ }
+ if (clazz != null) {
+ byte[] bytes = clazz.getBytes();
+ cl = defineClass(class_name, bytes, 0, bytes.length);
+ } else {
+ cl = Class.forName(class_name);
+ }
+ }
+ if (resolve) {
+ resolveClass(cl);
+ }
+ }
+ classes.put(class_name, cl);
+ return cl;
+ }
+
+
+ /** Override this method if you want to alter a class before it gets actually
+ * loaded. Does nothing by default.
+ */
+ protected JavaClass modifyClass( JavaClass clazz ) {
+ return clazz;
+ }
+
+
+ /**
+ * Override this method to create you own classes on the fly. The
+ * name contains the special token $$BCEL$$. Everything before that
+ * token is consddered to be a package name. You can encode you own
+ * arguments into the subsequent string. You must regard however not
+ * to use any "illegal" characters, i.e., characters that may not
+ * appear in a Java class name too<br>
+ *
+ * The default implementation interprets the string as a encoded compressed
+ * Java class, unpacks and decodes it with the Utility.decode() method, and
+ * parses the resulting byte array and returns the resulting JavaClass object.
+ *
+ * @param class_name compressed byte code with "$$BCEL$$" in it
+ */
+ protected JavaClass createClass( String class_name ) {
+ int index = class_name.indexOf("$$BCEL$$");
+ String real_name = class_name.substring(index + 8);
+ JavaClass clazz = null;
+ try {
+ byte[] bytes = Utility.decode(real_name, true);
+ ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
+ clazz = parser.parse();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ return null;
+ }
+ // Adapt the class name to the passed value
+ ConstantPool cp = clazz.getConstantPool();
+ ConstantClass cl = (ConstantClass) cp.getConstant(clazz.getClassNameIndex(),
+ Constants.CONSTANT_Class);
+ ConstantUtf8 name = (ConstantUtf8) cp.getConstant(cl.getNameIndex(),
+ Constants.CONSTANT_Utf8);
+ name.setBytes(class_name.replace('.', '/'));
+ return clazz;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * The repository maintains information about which classes have
+ * been loaded.
+ *
+ * It loads its data from the ClassLoader implementation
+ * passed into its constructor.
+ *
+ * @see org.apache.tomcat.util.bcel.Repository
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @author David Dixon-Peugh
+ */
+public class ClassLoaderRepository implements Repository {
+
+ private java.lang.ClassLoader loader;
+ private Map loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
+
+
+ public ClassLoaderRepository(java.lang.ClassLoader loader) {
+ this.loader = loader;
+ }
+
+
+ /**
+ * Store a new JavaClass into this Repository.
+ */
+ public void storeClass( JavaClass clazz ) {
+ loadedClasses.put(clazz.getClassName(), clazz);
+ clazz.setRepository(this);
+ }
+
+
+ /**
+ * Remove class from repository
+ */
+ public void removeClass( JavaClass clazz ) {
+ loadedClasses.remove(clazz.getClassName());
+ }
+
+
+ /**
+ * Find an already defined JavaClass.
+ */
+ public JavaClass findClass( String className ) {
+ if (loadedClasses.containsKey(className)) {
+ return (JavaClass) loadedClasses.get(className);
+ } else {
+ return null;
+ }
+ }
+
+
+ /**
+ * Lookup a JavaClass object from the Class Name provided.
+ */
+ public JavaClass loadClass( String className ) throws ClassNotFoundException {
+ String classFile = className.replace('.', '/');
+ JavaClass RC = findClass(className);
+ if (RC != null) {
+ return RC;
+ }
+ try {
+ InputStream is = loader.getResourceAsStream(classFile + ".class");
+ if (is == null) {
+ throw new ClassNotFoundException(className + " not found.");
+ }
+ ClassParser parser = new ClassParser(is, className);
+ RC = parser.parse();
+ storeClass(RC);
+ return RC;
+ } catch (IOException e) {
+ throw new ClassNotFoundException(className + " not found: " + e.toString(), e);
+ }
+ }
+
+
+ public JavaClass loadClass( Class clazz ) throws ClassNotFoundException {
+ return loadClass(clazz.getName());
+ }
+
+
+ /** Clear all entries from cache.
+ */
+ public void clear() {
+ loadedClasses.clear();
+ }
+
+
+ /*
+ * @return null
+ */
+ public ClassPath getClassPath() {
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * Responsible for loading (class) files from the CLASSPATH. Inspired by
+ * sun.tools.ClassPath.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ClassPath implements Serializable {
+
+ public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath();
+ private PathEntry[] paths;
+ private String class_path;
+
+
+ /**
+ * Search for classes in given path.
+ */
+ public ClassPath(String class_path) {
+ this.class_path = class_path;
+ List vec = new ArrayList();
+ for (StringTokenizer tok = new StringTokenizer(class_path, System
+ .getProperty("path.separator")); tok.hasMoreTokens();) {
+ String path = tok.nextToken();
+ if (!path.equals("")) {
+ File file = new File(path);
+ try {
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ vec.add(new Dir(path));
+ } else {
+ vec.add(new Zip(new ZipFile(file)));
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("CLASSPATH component " + file + ": " + e);
+ }
+ }
+ }
+ paths = new PathEntry[vec.size()];
+ vec.toArray(paths);
+ }
+
+
+ /**
+ * Search for classes in CLASSPATH.
+ * @deprecated Use SYSTEM_CLASS_PATH constant
+ */
+ public ClassPath() {
+ this(getClassPath());
+ }
+
+
+ /** @return used class path string
+ */
+ public String toString() {
+ return class_path;
+ }
+
+
+ public int hashCode() {
+ return class_path.hashCode();
+ }
+
+
+ public boolean equals( Object o ) {
+ if (o instanceof ClassPath) {
+ return class_path.equals(((ClassPath) o).class_path);
+ }
+ return false;
+ }
+
+
+ private static final void getPathComponents( String path, List list ) {
+ if (path != null) {
+ StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
+ while (tok.hasMoreTokens()) {
+ String name = tok.nextToken();
+ File file = new File(name);
+ if (file.exists()) {
+ list.add(name);
+ }
+ }
+ }
+ }
+
+
+ /** Checks for class path components in the following properties:
+ * "java.class.path", "sun.boot.class.path", "java.ext.dirs"
+ *
+ * @return class path as used by default by BCEL
+ */
+ public static final String getClassPath() {
+ String class_path = System.getProperty("java.class.path");
+ String boot_path = System.getProperty("sun.boot.class.path");
+ String ext_path = System.getProperty("java.ext.dirs");
+ List list = new ArrayList();
+ getPathComponents(class_path, list);
+ getPathComponents(boot_path, list);
+ List dirs = new ArrayList();
+ getPathComponents(ext_path, dirs);
+ for (Iterator e = dirs.iterator(); e.hasNext();) {
+ File ext_dir = new File((String) e.next());
+ String[] extensions = ext_dir.list(new FilenameFilter() {
+
+ public boolean accept( File dir, String name ) {
+ name = name.toLowerCase(Locale.ENGLISH);
+ return name.endsWith(".zip") || name.endsWith(".jar");
+ }
+ });
+ if (extensions != null) {
+ for (int i = 0; i < extensions.length; i++) {
+ list.add(ext_dir.getPath() + File.separatorChar + extensions[i]);
+ }
+ }
+ }
+ StringBuffer buf = new StringBuffer();
+ for (Iterator e = list.iterator(); e.hasNext();) {
+ buf.append((String) e.next());
+ if (e.hasNext()) {
+ buf.append(File.pathSeparatorChar);
+ }
+ }
+ return buf.toString().intern();
+ }
+
+
+ /**
+ * @param name fully qualified class name, e.g. java.lang.String
+ * @return input stream for class
+ */
+ public InputStream getInputStream( String name ) throws IOException {
+ return getInputStream(name.replace('.', '/'), ".class");
+ }
+
+
+ /**
+ * Return stream for class or resource on CLASSPATH.
+ *
+ * @param name fully qualified file name, e.g. java/lang/String
+ * @param suffix file name ends with suff, e.g. .java
+ * @return input stream for file on class path
+ */
+ public InputStream getInputStream( String name, String suffix ) throws IOException {
+ InputStream is = null;
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(name + suffix);
+ } catch (Exception e) {
+ }
+ if (is != null) {
+ return is;
+ }
+ return getClassFile(name, suffix).getInputStream();
+ }
+
+ /**
+ * @param name fully qualified resource name, e.g. java/lang/String.class
+ * @return InputStream supplying the resource, or null if no resource with that name.
+ */
+ public InputStream getResourceAsStream(String name) {
+ for (int i = 0; i < paths.length; i++) {
+ InputStream is;
+ if ((is = paths[i].getResourceAsStream(name)) != null) {
+ return is;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param name fully qualified resource name, e.g. java/lang/String.class
+ * @return URL supplying the resource, or null if no resource with that name.
+ */
+ public URL getResource(String name) {
+ for (int i = 0; i < paths.length; i++) {
+ URL url;
+ if ((url = paths[i].getResource(name)) != null) {
+ return url;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param name fully qualified resource name, e.g. java/lang/String.class
+ * @return An Enumeration of URLs supplying the resource, or an
+ * empty Enumeration if no resource with that name.
+ */
+ public Enumeration getResources(String name) {
+ Vector results = new Vector();
+ for (int i = 0; i < paths.length; i++) {
+ URL url;
+ if ((url = paths[i].getResource(name)) != null) {
+ results.add(url);
+ }
+ }
+ return results.elements();
+ }
+
+ /**
+ * @param name fully qualified file name, e.g. java/lang/String
+ * @param suffix file name ends with suff, e.g. .java
+ * @return class file for the java class
+ */
+ public ClassFile getClassFile( String name, String suffix ) throws IOException {
+ for (int i = 0; i < paths.length; i++) {
+ ClassFile cf;
+ if ((cf = paths[i].getClassFile(name, suffix)) != null) {
+ return cf;
+ }
+ }
+ throw new IOException("Couldn't find: " + name + suffix);
+ }
+
+
+ /**
+ * @param name fully qualified class name, e.g. java.lang.String
+ * @return input stream for class
+ */
+ public ClassFile getClassFile( String name ) throws IOException {
+ return getClassFile(name, ".class");
+ }
+
+
+ /**
+ * @param name fully qualified file name, e.g. java/lang/String
+ * @param suffix file name ends with suffix, e.g. .java
+ * @return byte array for file on class path
+ */
+ public byte[] getBytes( String name, String suffix ) throws IOException {
+ DataInputStream dis = null;
+ try {
+ InputStream is = getInputStream(name, suffix);
+ if (is == null) {
+ throw new IOException("Couldn't find: " + name + suffix);
+ }
+ dis = new DataInputStream(is);
+ byte[] bytes = new byte[is.available()];
+ dis.readFully(bytes);
+ return bytes;
+ } finally {
+ if (dis != null) {
+ dis.close();
+ }
+ }
+ }
+
+
+ /**
+ * @return byte array for class
+ */
+ public byte[] getBytes( String name ) throws IOException {
+ return getBytes(name, ".class");
+ }
+
+
+ /**
+ * @param name name of file to search for, e.g. java/lang/String.java
+ * @return full (canonical) path for file
+ */
+ public String getPath( String name ) throws IOException {
+ int index = name.lastIndexOf('.');
+ String suffix = "";
+ if (index > 0) {
+ suffix = name.substring(index);
+ name = name.substring(0, index);
+ }
+ return getPath(name, suffix);
+ }
+
+
+ /**
+ * @param name name of file to search for, e.g. java/lang/String
+ * @param suffix file name suffix, e.g. .java
+ * @return full (canonical) path for file, if it exists
+ */
+ public String getPath( String name, String suffix ) throws IOException {
+ return getClassFile(name, suffix).getPath();
+ }
+
+ private static abstract class PathEntry implements Serializable {
+
+ abstract ClassFile getClassFile( String name, String suffix ) throws IOException;
+ abstract URL getResource(String name);
+ abstract InputStream getResourceAsStream(String name);
+ }
+
+ /** Contains information about file/ZIP entry of the Java class.
+ */
+ public interface ClassFile {
+
+ /** @return input stream for class file.
+ */
+ public abstract InputStream getInputStream() throws IOException;
+
+
+ /** @return canonical path to class file.
+ */
+ public abstract String getPath();
+
+
+ /** @return base path of found class, i.e. class is contained relative
+ * to that path, which may either denote a directory, or zip file
+ */
+ public abstract String getBase();
+
+
+ /** @return modification time of class file.
+ */
+ public abstract long getTime();
+
+
+ /** @return size of class file.
+ */
+ public abstract long getSize();
+ }
+
+ private static class Dir extends PathEntry {
+
+ private String dir;
+
+
+ Dir(String d) {
+ dir = d;
+ }
+
+ URL getResource(String name) {
+ // Resource specification uses '/' whatever the platform
+ final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ try {
+ return file.exists() ? file.toURL() : null;
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ InputStream getResourceAsStream(String name) {
+ // Resource specification uses '/' whatever the platform
+ final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar));
+ try {
+ return file.exists() ? new FileInputStream(file) : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ ClassFile getClassFile( String name, String suffix ) throws IOException {
+ final File file = new File(dir + File.separatorChar
+ + name.replace('.', File.separatorChar) + suffix);
+ return file.exists() ? new ClassFile() {
+
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(file);
+ }
+
+
+ public String getPath() {
+ try {
+ return file.getCanonicalPath();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+
+ public long getTime() {
+ return file.lastModified();
+ }
+
+
+ public long getSize() {
+ return file.length();
+ }
+
+
+ public String getBase() {
+ return dir;
+ }
+ } : null;
+ }
+
+
+ public String toString() {
+ return dir;
+ }
+ }
+
+ private static class Zip extends PathEntry {
+
+ private ZipFile zip;
+
+
+ Zip(ZipFile z) {
+ zip = z;
+ }
+
+ URL getResource(String name) {
+ final ZipEntry entry = zip.getEntry(name);
+ try {
+ return (entry != null) ? new URL("jar:file:" + zip.getName() + "!/" + name) : null;
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ InputStream getResourceAsStream(String name) {
+ final ZipEntry entry = zip.getEntry(name);
+ try {
+ return (entry != null) ? zip.getInputStream(entry) : null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ ClassFile getClassFile( String name, String suffix ) throws IOException {
+ final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
+
+ if (entry == null)
+ return null;
+
+ return new ClassFile() {
+
+ public InputStream getInputStream() throws IOException {
+ return zip.getInputStream(entry);
+ }
+
+
+ public String getPath() {
+ return entry.toString();
+ }
+
+
+ public long getTime() {
+ return entry.getTime();
+ }
+
+
+ public long getSize() {
+ return entry.getSize();
+ }
+
+
+ public String getBase() {
+ return zip.getName();
+ }
+ };
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.util.LinkedList;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Utility class implementing a (typesafe) queue of JavaClass
+ * objects.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ */
+public class ClassQueue implements java.io.Serializable {
+
+ protected LinkedList vec = new LinkedList();
+
+
+ public void enqueue( JavaClass clazz ) {
+ vec.addLast(clazz);
+ }
+
+
+ public JavaClass dequeue() {
+ return (JavaClass) vec.removeFirst();
+ }
+
+
+ public boolean empty() {
+ return vec.isEmpty();
+ }
+
+
+ public String toString() {
+ return vec.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Utility class implementing a (typesafe) set of JavaClass objects.
+ * Since JavaClass has no equals() method, the name of the class is
+ * used for comparison.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see ClassStack
+ */
+public class ClassSet implements java.io.Serializable {
+
+ private Map _map = new HashMap();
+
+
+ public boolean add( JavaClass clazz ) {
+ boolean result = false;
+ if (!_map.containsKey(clazz.getClassName())) {
+ result = true;
+ _map.put(clazz.getClassName(), clazz);
+ }
+ return result;
+ }
+
+
+ public void remove( JavaClass clazz ) {
+ _map.remove(clazz.getClassName());
+ }
+
+
+ public boolean empty() {
+ return _map.isEmpty();
+ }
+
+
+ public JavaClass[] toArray() {
+ Collection values = _map.values();
+ JavaClass[] classes = new JavaClass[values.size()];
+ values.toArray(classes);
+ return classes;
+ }
+
+
+ public String[] getClassNames() {
+ return (String[]) _map.keySet().toArray(new String[_map.keySet().size()]);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.util.Stack;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Utility class implementing a (typesafe) stack of JavaClass objects.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Stack
+ */
+public class ClassStack implements java.io.Serializable {
+
+ private Stack stack = new Stack();
+
+
+ public void push( JavaClass clazz ) {
+ stack.push(clazz);
+ }
+
+
+ public JavaClass pop() {
+ return (JavaClass) stack.pop();
+ }
+
+
+ public JavaClass top() {
+ return (JavaClass) stack.peek();
+ }
+
+
+ public boolean empty() {
+ return stack.empty();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Utility class implementing a (typesafe) collection of JavaClass
+ * objects. Contains the most important methods of a Vector.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ *
+ * @deprecated as of 5.1.1 - 7/17/2005
+ */
+public class ClassVector implements java.io.Serializable {
+
+ protected List vec = new ArrayList();
+
+
+ public void addElement( JavaClass clazz ) {
+ vec.add(clazz);
+ }
+
+
+ public JavaClass elementAt( int index ) {
+ return (JavaClass) vec.get(index);
+ }
+
+
+ public void removeElementAt( int index ) {
+ vec.remove(index);
+ }
+
+
+ public JavaClass[] toArray() {
+ JavaClass[] classes = new JavaClass[vec.size()];
+ vec.toArray(classes);
+ return classes;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.BitSet;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Code;
+import org.apache.tomcat.util.bcel.classfile.CodeException;
+import org.apache.tomcat.util.bcel.classfile.ConstantFieldref;
+import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.LocalVariable;
+import org.apache.tomcat.util.bcel.classfile.LocalVariableTable;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Convert code into HTML file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ *
+ */
+final class CodeHTML implements org.apache.tomcat.util.bcel.Constants {
+
+ private String class_name; // name of current class
+// private Method[] methods; // Methods to print
+ private PrintWriter file; // file to write to
+ private BitSet goto_set;
+ private ConstantPool constant_pool;
+ private ConstantHTML constant_html;
+ private static boolean wide = false;
+
+
+ CodeHTML(String dir, String class_name, Method[] methods, ConstantPool constant_pool,
+ ConstantHTML constant_html) throws IOException {
+ this.class_name = class_name;
+// this.methods = methods;
+ this.constant_pool = constant_pool;
+ this.constant_html = constant_html;
+ file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html"));
+ file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\">");
+ for (int i = 0; i < methods.length; i++) {
+ writeMethod(methods[i], i);
+ }
+ file.println("</BODY></HTML>");
+ file.close();
+ }
+
+
+ /**
+ * Disassemble a stream of byte codes and return the
+ * string representation.
+ *
+ * @param stream data input stream
+ * @return String representation of byte code
+ */
+ private final String codeToHTML( ByteSequence bytes, int method_number ) throws IOException {
+ short opcode = (short) bytes.readUnsignedByte();
+ StringBuffer buf;
+ String name, signature;
+ int default_offset = 0, low, high;
+ int index, class_index, vindex, constant;
+ int[] jump_table;
+ int no_pad_bytes = 0, offset;
+ buf = new StringBuffer(256);
+ buf.append("<TT>").append(OPCODE_NAMES[opcode]).append("</TT></TD><TD>");
+ /* Special case: Skip (0-3) padding bytes, i.e., the
+ * following bytes are 4-byte-aligned
+ */
+ if ((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) {
+ int remainder = bytes.getIndex() % 4;
+ no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
+ for (int i = 0; i < no_pad_bytes; i++) {
+ bytes.readByte();
+ }
+ // Both cases have a field default_offset in common
+ default_offset = bytes.readInt();
+ }
+ switch (opcode) {
+ case TABLESWITCH:
+ low = bytes.readInt();
+ high = bytes.readInt();
+ offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
+ default_offset += offset;
+ buf.append("<TABLE BORDER=1><TR>");
+ // Print switch indices in first row (and default)
+ jump_table = new int[high - low + 1];
+ for (int i = 0; i < jump_table.length; i++) {
+ jump_table[i] = offset + bytes.readInt();
+ buf.append("<TH>").append(low + i).append("</TH>");
+ }
+ buf.append("<TH>default</TH></TR>\n<TR>");
+ // Print target and default indices in second row
+ for (int i = 0; i < jump_table.length; i++) {
+ buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
+ jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
+ }
+ buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
+ default_offset).append("\">").append(default_offset).append(
+ "</A></TD></TR>\n</TABLE>\n");
+ break;
+ /* Lookup switch has variable length arguments.
+ */
+ case LOOKUPSWITCH:
+ int npairs = bytes.readInt();
+ offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
+ jump_table = new int[npairs];
+ default_offset += offset;
+ buf.append("<TABLE BORDER=1><TR>");
+ // Print switch indices in first row (and default)
+ for (int i = 0; i < npairs; i++) {
+ int match = bytes.readInt();
+ jump_table[i] = offset + bytes.readInt();
+ buf.append("<TH>").append(match).append("</TH>");
+ }
+ buf.append("<TH>default</TH></TR>\n<TR>");
+ // Print target and default indices in second row
+ for (int i = 0; i < npairs; i++) {
+ buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
+ jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
+ }
+ buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
+ default_offset).append("\">").append(default_offset).append(
+ "</A></TD></TR>\n</TABLE>\n");
+ break;
+ /* Two address bytes + offset from start of byte stream form the
+ * jump target.
+ */
+ case GOTO:
+ case IFEQ:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case IFLT:
+ case IFNE:
+ case IFNONNULL:
+ case IFNULL:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case IF_ICMPEQ:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ICMPLT:
+ case IF_ICMPNE:
+ case JSR:
+ index = (int) (bytes.getIndex() + bytes.readShort() - 1);
+ buf.append("<A HREF=\"#code").append(method_number).append("@").append(index)
+ .append("\">").append(index).append("</A>");
+ break;
+ /* Same for 32-bit wide jumps
+ */
+ case GOTO_W:
+ case JSR_W:
+ int windex = bytes.getIndex() + bytes.readInt() - 1;
+ buf.append("<A HREF=\"#code").append(method_number).append("@").append(windex)
+ .append("\">").append(windex).append("</A>");
+ break;
+ /* Index byte references local variable (register)
+ */
+ case ALOAD:
+ case ASTORE:
+ case DLOAD:
+ case DSTORE:
+ case FLOAD:
+ case FSTORE:
+ case ILOAD:
+ case ISTORE:
+ case LLOAD:
+ case LSTORE:
+ case RET:
+ if (wide) {
+ vindex = bytes.readShort();
+ wide = false; // Clear flag
+ } else {
+ vindex = bytes.readUnsignedByte();
+ }
+ buf.append("%").append(vindex);
+ break;
+ /*
+ * Remember wide byte which is used to form a 16-bit address in the
+ * following instruction. Relies on that the method is called again with
+ * the following opcode.
+ */
+ case WIDE:
+ wide = true;
+ buf.append("(wide)");
+ break;
+ /* Array of basic type.
+ */
+ case NEWARRAY:
+ buf.append("<FONT COLOR=\"#00FF00\">").append(TYPE_NAMES[bytes.readByte()]).append(
+ "</FONT>");
+ break;
+ /* Access object/class fields.
+ */
+ case GETFIELD:
+ case GETSTATIC:
+ case PUTFIELD:
+ case PUTSTATIC:
+ index = bytes.readShort();
+ ConstantFieldref c1 = (ConstantFieldref) constant_pool.getConstant(index,
+ CONSTANT_Fieldref);
+ class_index = c1.getClassIndex();
+ name = constant_pool.getConstantString(class_index, CONSTANT_Class);
+ name = Utility.compactClassName(name, false);
+ index = c1.getNameAndTypeIndex();
+ String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType);
+ if (name.equals(class_name)) { // Local field
+ buf.append("<A HREF=\"").append(class_name).append("_methods.html#field")
+ .append(field_name).append("\" TARGET=Methods>").append(field_name)
+ .append("</A>\n");
+ } else {
+ buf.append(constant_html.referenceConstant(class_index)).append(".").append(
+ field_name);
+ }
+ break;
+ /* Operands are references to classes in constant pool
+ */
+ case CHECKCAST:
+ case INSTANCEOF:
+ case NEW:
+ index = bytes.readShort();
+ buf.append(constant_html.referenceConstant(index));
+ break;
+ /* Operands are references to methods in constant pool
+ */
+ case INVOKESPECIAL:
+ case INVOKESTATIC:
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE:
+ int m_index = bytes.readShort();
+ String str;
+ if (opcode == INVOKEINTERFACE) { // Special treatment needed
+ bytes.readUnsignedByte(); // Redundant
+ bytes.readUnsignedByte(); // Reserved
+// int nargs = bytes.readUnsignedByte(); // Redundant
+// int reserved = bytes.readUnsignedByte(); // Reserved
+ ConstantInterfaceMethodref c = (ConstantInterfaceMethodref) constant_pool
+ .getConstant(m_index, CONSTANT_InterfaceMethodref);
+ class_index = c.getClassIndex();
+ str = constant_pool.constantToString(c);
+ index = c.getNameAndTypeIndex();
+ } else {
+ ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(m_index,
+ CONSTANT_Methodref);
+ class_index = c.getClassIndex();
+ str = constant_pool.constantToString(c);
+ index = c.getNameAndTypeIndex();
+ }
+ name = Class2HTML.referenceClass(class_index);
+ str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant(
+ index, CONSTANT_NameAndType)));
+ // Get signature, i.e., types
+ ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(index,
+ CONSTANT_NameAndType);
+ signature = constant_pool.constantToString(c2.getSignatureIndex(), CONSTANT_Utf8);
+ String[] args = Utility.methodSignatureArgumentTypes(signature, false);
+ String type = Utility.methodSignatureReturnType(signature, false);
+ buf.append(name).append(".<A HREF=\"").append(class_name).append("_cp.html#cp")
+ .append(m_index).append("\" TARGET=ConstantPool>").append(str).append(
+ "</A>").append("(");
+ // List arguments
+ for (int i = 0; i < args.length; i++) {
+ buf.append(Class2HTML.referenceType(args[i]));
+ if (i < args.length - 1) {
+ buf.append(", ");
+ }
+ }
+ // Attach return type
+ buf.append("):").append(Class2HTML.referenceType(type));
+ break;
+ /* Operands are references to items in constant pool
+ */
+ case LDC_W:
+ case LDC2_W:
+ index = bytes.readShort();
+ buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
+ .append("\" TARGET=\"ConstantPool\">").append(
+ Class2HTML.toHTML(constant_pool.constantToString(index,
+ constant_pool.getConstant(index).getTag()))).append("</a>");
+ break;
+ case LDC:
+ index = bytes.readUnsignedByte();
+ buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
+ .append("\" TARGET=\"ConstantPool\">").append(
+ Class2HTML.toHTML(constant_pool.constantToString(index,
+ constant_pool.getConstant(index).getTag()))).append("</a>");
+ break;
+ /* Array of references.
+ */
+ case ANEWARRAY:
+ index = bytes.readShort();
+ buf.append(constant_html.referenceConstant(index));
+ break;
+ /* Multidimensional array of references.
+ */
+ case MULTIANEWARRAY:
+ index = bytes.readShort();
+ int dimensions = bytes.readByte();
+ buf.append(constant_html.referenceConstant(index)).append(":").append(dimensions)
+ .append("-dimensional");
+ break;
+ /* Increment local variable.
+ */
+ case IINC:
+ if (wide) {
+ vindex = bytes.readShort();
+ constant = bytes.readShort();
+ wide = false;
+ } else {
+ vindex = bytes.readUnsignedByte();
+ constant = bytes.readByte();
+ }
+ buf.append("%").append(vindex).append(" ").append(constant);
+ break;
+ default:
+ if (NO_OF_OPERANDS[opcode] > 0) {
+ for (int i = 0; i < TYPE_OF_OPERANDS[opcode].length; i++) {
+ switch (TYPE_OF_OPERANDS[opcode][i]) {
+ case T_BYTE:
+ buf.append(bytes.readUnsignedByte());
+ break;
+ case T_SHORT: // Either branch or index
+ buf.append(bytes.readShort());
+ break;
+ case T_INT:
+ buf.append(bytes.readInt());
+ break;
+ default: // Never reached
+ System.err.println("Unreachable default case reached!");
+ System.exit(-1);
+ }
+ buf.append(" ");
+ }
+ }
+ }
+ buf.append("</TD>");
+ return buf.toString();
+ }
+
+
+ /**
+ * Find all target addresses in code, so that they can be marked
+ * with <A NAME = ...>. Target addresses are kept in an BitSet object.
+ */
+ private final void findGotos( ByteSequence bytes, Method method, Code code ) throws IOException {
+ int index;
+ goto_set = new BitSet(bytes.available());
+ int opcode;
+ /* First get Code attribute from method and the exceptions handled
+ * (try .. catch) in this method. We only need the line number here.
+ */
+ if (code != null) {
+ CodeException[] ce = code.getExceptionTable();
+ int len = ce.length;
+ for (int i = 0; i < len; i++) {
+ goto_set.set(ce[i].getStartPC());
+ goto_set.set(ce[i].getEndPC());
+ goto_set.set(ce[i].getHandlerPC());
+ }
+ // Look for local variables and their range
+ Attribute[] attributes = code.getAttributes();
+ for (int i = 0; i < attributes.length; i++) {
+ if (attributes[i].getTag() == ATTR_LOCAL_VARIABLE_TABLE) {
+ LocalVariable[] vars = ((LocalVariableTable) attributes[i])
+ .getLocalVariableTable();
+ for (int j = 0; j < vars.length; j++) {
+ int start = vars[j].getStartPC();
+ int end = (int) (start + vars[j].getLength());
+ goto_set.set(start);
+ goto_set.set(end);
+ }
+ break;
+ }
+ }
+ }
+ // Get target addresses from GOTO, JSR, TABLESWITCH, etc.
+ for (int i = 0; bytes.available() > 0; i++) {
+ opcode = bytes.readUnsignedByte();
+ //System.out.println(OPCODE_NAMES[opcode]);
+ switch (opcode) {
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ //bytes.readByte(); // Skip already read byte
+ int remainder = bytes.getIndex() % 4;
+ int no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
+ int default_offset,
+ offset;
+ for (int j = 0; j < no_pad_bytes; j++) {
+ bytes.readByte();
+ }
+ // Both cases have a field default_offset in common
+ default_offset = bytes.readInt();
+ if (opcode == TABLESWITCH) {
+ int low = bytes.readInt();
+ int high = bytes.readInt();
+ offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
+ default_offset += offset;
+ goto_set.set(default_offset);
+ for (int j = 0; j < (high - low + 1); j++) {
+ index = offset + bytes.readInt();
+ goto_set.set(index);
+ }
+ } else { // LOOKUPSWITCH
+ int npairs = bytes.readInt();
+ offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
+ default_offset += offset;
+ goto_set.set(default_offset);
+ for (int j = 0; j < npairs; j++) {
+// int match = bytes.readInt();
+ bytes.readInt();
+ index = offset + bytes.readInt();
+ goto_set.set(index);
+ }
+ }
+ break;
+ case GOTO:
+ case IFEQ:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case IFLT:
+ case IFNE:
+ case IFNONNULL:
+ case IFNULL:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case IF_ICMPEQ:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ICMPLT:
+ case IF_ICMPNE:
+ case JSR:
+ //bytes.readByte(); // Skip already read byte
+ index = bytes.getIndex() + bytes.readShort() - 1;
+ goto_set.set(index);
+ break;
+ case GOTO_W:
+ case JSR_W:
+ //bytes.readByte(); // Skip already read byte
+ index = bytes.getIndex() + bytes.readInt() - 1;
+ goto_set.set(index);
+ break;
+ default:
+ bytes.unreadByte();
+ codeToHTML(bytes, 0); // Ignore output
+ }
+ }
+ }
+
+
+ /**
+ * Write a single method with the byte code associated with it.
+ */
+ private void writeMethod( Method method, int method_number ) throws IOException {
+ // Get raw signature
+ String signature = method.getSignature();
+ // Get array of strings containing the argument types
+ String[] args = Utility.methodSignatureArgumentTypes(signature, false);
+ // Get return type string
+ String type = Utility.methodSignatureReturnType(signature, false);
+ // Get method name
+ String name = method.getName();
+ String html_name = Class2HTML.toHTML(name);
+ // Get method's access flags
+ String access = Utility.accessToString(method.getAccessFlags());
+ access = Utility.replace(access, " ", " ");
+ // Get the method's attributes, the Code Attribute in particular
+ Attribute[] attributes = method.getAttributes();
+ file.print("<P><B><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + "<A NAME=method"
+ + method_number + ">" + Class2HTML.referenceType(type) + "</A> <A HREF=\""
+ + class_name + "_methods.html#method" + method_number + "\" TARGET=Methods>"
+ + html_name + "</A>(");
+ for (int i = 0; i < args.length; i++) {
+ file.print(Class2HTML.referenceType(args[i]));
+ if (i < args.length - 1) {
+ file.print(", ");
+ }
+ }
+ file.println(")</B></P>");
+ Code c = null;
+ byte[] code = null;
+ if (attributes.length > 0) {
+ file.print("<H4>Attributes</H4><UL>\n");
+ for (int i = 0; i < attributes.length; i++) {
+ byte tag = attributes[i].getTag();
+ if (tag != ATTR_UNKNOWN) {
+ file.print("<LI><A HREF=\"" + class_name + "_attributes.html#method"
+ + method_number + "@" + i + "\" TARGET=Attributes>"
+ + ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
+ } else {
+ file.print("<LI>" + attributes[i] + "</LI>");
+ }
+ if (tag == ATTR_CODE) {
+ c = (Code) attributes[i];
+ Attribute[] attributes2 = c.getAttributes();
+ code = c.getCode();
+ file.print("<UL>");
+ for (int j = 0; j < attributes2.length; j++) {
+ tag = attributes2[j].getTag();
+ file.print("<LI><A HREF=\"" + class_name + "_attributes.html#" + "method"
+ + method_number + "@" + i + "@" + j + "\" TARGET=Attributes>"
+ + ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
+ }
+ file.print("</UL>");
+ }
+ }
+ file.println("</UL>");
+ }
+ if (code != null) { // No code, an abstract method, e.g.
+ //System.out.println(name + "\n" + Utility.codeToString(code, constant_pool, 0, -1));
+ // Print the byte code
+ ByteSequence stream = new ByteSequence(code);
+ stream.mark(stream.available());
+ findGotos(stream, method, c);
+ stream.reset();
+ file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Byte<BR>offset</TH>"
+ + "<TH ALIGN=LEFT>Instruction</TH><TH ALIGN=LEFT>Argument</TH>");
+ for (int i = 0; stream.available() > 0; i++) {
+ int offset = stream.getIndex();
+ String str = codeToHTML(stream, method_number);
+ String anchor = "";
+ /* Set an anchor mark if this line is targetted by a goto, jsr, etc.
+ * Defining an anchor for every line is very inefficient!
+ */
+ if (goto_set.get(offset)) {
+ anchor = "<A NAME=code" + method_number + "@" + offset + "></A>";
+ }
+ String anchor2;
+ if (stream.getIndex() == code.length) {
+ anchor2 = "<A NAME=code" + method_number + "@" + code.length + ">" + offset
+ + "</A>";
+ } else {
+ anchor2 = "" + offset;
+ }
+ file
+ .println("<TR VALIGN=TOP><TD>" + anchor2 + "</TD><TD>" + anchor + str
+ + "</TR>");
+ }
+ // Mark last line, may be targetted from Attributes window
+ file.println("<TR><TD> </A></TD></TR>");
+ file.println("</TABLE>");
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.apache.tomcat.util.bcel.classfile.Constant;
+import org.apache.tomcat.util.bcel.classfile.ConstantClass;
+import org.apache.tomcat.util.bcel.classfile.ConstantFieldref;
+import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantMethodref;
+import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
+import org.apache.tomcat.util.bcel.classfile.ConstantPool;
+import org.apache.tomcat.util.bcel.classfile.ConstantString;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Convert constant pool into HTML file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ *
+ */
+final class ConstantHTML implements org.apache.tomcat.util.bcel.Constants {
+
+ private String class_name; // name of current class
+ private String class_package; // name of package
+ private ConstantPool constant_pool; // reference to constant pool
+ private PrintWriter file; // file to write to
+ private String[] constant_ref; // String to return for cp[i]
+ private Constant[] constants; // The constants in the cp
+ private Method[] methods;
+
+
+ ConstantHTML(String dir, String class_name, String class_package, Method[] methods,
+ ConstantPool constant_pool) throws IOException {
+ this.class_name = class_name;
+ this.class_package = class_package;
+ this.constant_pool = constant_pool;
+ this.methods = methods;
+ constants = constant_pool.getConstantPool();
+ file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html"));
+ constant_ref = new String[constants.length];
+ constant_ref[0] = "<unknown>";
+ file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
+ // Loop through constants, constants[0] is reserved
+ for (int i = 1; i < constants.length; i++) {
+ if (i % 2 == 0) {
+ file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
+ } else {
+ file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
+ }
+ if (constants[i] != null) {
+ writeConstant(i);
+ }
+ file.print("</TD></TR>\n");
+ }
+ file.println("</TABLE></BODY></HTML>");
+ file.close();
+ }
+
+
+ String referenceConstant( int index ) {
+ return constant_ref[index];
+ }
+
+
+ private void writeConstant( int index ) {
+ byte tag = constants[index].getTag();
+ int class_index, name_index;
+ String ref;
+ // The header is always the same
+ file.println("<H4> <A NAME=cp" + index + ">" + index + "</A> " + CONSTANT_NAMES[tag]
+ + "</H4>");
+ /* For every constant type get the needed parameters and print them appropiately
+ */
+ switch (tag) {
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_Methodref:
+ // Get class_index and name_and_type_index, depending on type
+ if (tag == CONSTANT_Methodref) {
+ ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(index,
+ CONSTANT_Methodref);
+ class_index = c.getClassIndex();
+ name_index = c.getNameAndTypeIndex();
+ } else {
+ ConstantInterfaceMethodref c1 = (ConstantInterfaceMethodref) constant_pool
+ .getConstant(index, CONSTANT_InterfaceMethodref);
+ class_index = c1.getClassIndex();
+ name_index = c1.getNameAndTypeIndex();
+ }
+ // Get method name and its class
+ String method_name = constant_pool.constantToString(name_index,
+ CONSTANT_NameAndType);
+ String html_method_name = Class2HTML.toHTML(method_name);
+ // Partially compacted class name, i.e., / -> .
+ String method_class = constant_pool.constantToString(class_index, CONSTANT_Class);
+ String short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang.
+ short_method_class = Utility.compactClassName(short_method_class, class_package
+ + ".", true); // Remove class package prefix
+ // Get method signature
+ ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(
+ name_index, CONSTANT_NameAndType);
+ String signature = constant_pool.constantToString(c2.getSignatureIndex(),
+ CONSTANT_Utf8);
+ // Get array of strings containing the argument types
+ String[] args = Utility.methodSignatureArgumentTypes(signature, false);
+ // Get return type string
+ String type = Utility.methodSignatureReturnType(signature, false);
+ String ret_type = Class2HTML.referenceType(type);
+ StringBuffer buf = new StringBuffer("(");
+ for (int i = 0; i < args.length; i++) {
+ buf.append(Class2HTML.referenceType(args[i]));
+ if (i < args.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ String arg_types = buf.toString();
+ if (method_class.equals(class_name)) {
+ ref = "<A HREF=\"" + class_name + "_code.html#method"
+ + getMethodNumber(method_name + signature) + "\" TARGET=Code>"
+ + html_method_name + "</A>";
+ } else {
+ ref = "<A HREF=\"" + method_class + ".html" + "\" TARGET=_top>"
+ + short_method_class + "</A>." + html_method_name;
+ }
+ constant_ref[index] = ret_type + " <A HREF=\"" + class_name + "_cp.html#cp"
+ + class_index + "\" TARGET=Constants>" + short_method_class
+ + "</A>.<A HREF=\"" + class_name + "_cp.html#cp" + index
+ + "\" TARGET=ConstantPool>" + html_method_name + "</A> " + arg_types;
+ file.println("<P><TT>" + ret_type + " " + ref + arg_types
+ + " </TT>\n<UL>" + "<LI><A HREF=\"#cp" + class_index
+ + "\">Class index(" + class_index + ")</A>\n" + "<LI><A HREF=\"#cp"
+ + name_index + "\">NameAndType index(" + name_index + ")</A></UL>");
+ break;
+ case CONSTANT_Fieldref:
+ // Get class_index and name_and_type_index
+ ConstantFieldref c3 = (ConstantFieldref) constant_pool.getConstant(index,
+ CONSTANT_Fieldref);
+ class_index = c3.getClassIndex();
+ name_index = c3.getNameAndTypeIndex();
+ // Get method name and its class (compacted)
+ String field_class = constant_pool.constantToString(class_index, CONSTANT_Class);
+ String short_field_class = Utility.compactClassName(field_class); // I.e., remove java.lang.
+ short_field_class = Utility.compactClassName(short_field_class,
+ class_package + ".", true); // Remove class package prefix
+ String field_name = constant_pool
+ .constantToString(name_index, CONSTANT_NameAndType);
+ if (field_class.equals(class_name)) {
+ ref = "<A HREF=\"" + field_class + "_methods.html#field" + field_name
+ + "\" TARGET=Methods>" + field_name + "</A>";
+ } else {
+ ref = "<A HREF=\"" + field_class + ".html\" TARGET=_top>" + short_field_class
+ + "</A>." + field_name + "\n";
+ }
+ constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + class_index
+ + "\" TARGET=Constants>" + short_field_class + "</A>.<A HREF=\""
+ + class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>"
+ + field_name + "</A>";
+ file.println("<P><TT>" + ref + "</TT><BR>\n" + "<UL>" + "<LI><A HREF=\"#cp"
+ + class_index + "\">Class(" + class_index + ")</A><BR>\n"
+ + "<LI><A HREF=\"#cp" + name_index + "\">NameAndType(" + name_index
+ + ")</A></UL>");
+ break;
+ case CONSTANT_Class:
+ ConstantClass c4 = (ConstantClass) constant_pool.getConstant(index, CONSTANT_Class);
+ name_index = c4.getNameIndex();
+ String class_name2 = constant_pool.constantToString(index, tag); // / -> .
+ String short_class_name = Utility.compactClassName(class_name2); // I.e., remove java.lang.
+ short_class_name = Utility.compactClassName(short_class_name, class_package + ".",
+ true); // Remove class package prefix
+ ref = "<A HREF=\"" + class_name2 + ".html\" TARGET=_top>" + short_class_name
+ + "</A>";
+ constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + index
+ + "\" TARGET=ConstantPool>" + short_class_name + "</A>";
+ file.println("<P><TT>" + ref + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
+ + "\">Name index(" + name_index + ")</A></UL>\n");
+ break;
+ case CONSTANT_String:
+ ConstantString c5 = (ConstantString) constant_pool.getConstant(index,
+ CONSTANT_String);
+ name_index = c5.getStringIndex();
+ String str = Class2HTML.toHTML(constant_pool.constantToString(index, tag));
+ file.println("<P><TT>" + str + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
+ + "\">Name index(" + name_index + ")</A></UL>\n");
+ break;
+ case CONSTANT_NameAndType:
+ ConstantNameAndType c6 = (ConstantNameAndType) constant_pool.getConstant(index,
+ CONSTANT_NameAndType);
+ name_index = c6.getNameIndex();
+ int signature_index = c6.getSignatureIndex();
+ file.println("<P><TT>"
+ + Class2HTML.toHTML(constant_pool.constantToString(index, tag))
+ + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index + "\">Name index("
+ + name_index + ")</A>\n" + "<LI><A HREF=\"#cp" + signature_index
+ + "\">Signature index(" + signature_index + ")</A></UL>\n");
+ break;
+ default:
+ file
+ .println("<P><TT>"
+ + Class2HTML.toHTML(constant_pool.constantToString(index, tag))
+ + "</TT>\n");
+ } // switch
+ }
+
+
+ private final int getMethodNumber( String str ) {
+ for (int i = 0; i < methods.length; i++) {
+ String cmp = methods[i].getName() + methods[i].getSignature();
+ if (cmp.equals(str)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.tomcat.util.bcel.Constants;
+import org.apache.tomcat.util.bcel.generic.ClassGenException;
+import org.apache.tomcat.util.bcel.generic.Instruction;
+import org.apache.tomcat.util.bcel.generic.InstructionHandle;
+import org.apache.tomcat.util.bcel.generic.InstructionList;
+
+/**
+ * InstructionFinder is a tool to search for given instructions patterns, i.e.,
+ * match sequences of instructions in an instruction list via regular
+ * expressions. This can be used, e.g., in order to implement a peep hole
+ * optimizer that looks for code patterns and replaces them with faster
+ * equivalents.
+ *
+ * <p>
+ * This class internally uses the java.util.regex
+ * package to search for regular expressions.
+ *
+ * A typical application would look like this:
+ *
+ * <pre>
+ *
+ *
+ * InstructionFinder f = new InstructionFinder(il);
+ * String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP (IFEQ|IFNE)";
+ *
+ * for(Iterator i = f.search(pat, constraint); i.hasNext(); ) {
+ * InstructionHandle[] match = (InstructionHandle[])i.next();
+ * ...
+ * il.delete(match[1], match[5]);
+ * ...
+ * }
+ *
+ *
+ * </pre>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see Instruction
+ * @see InstructionList
+ */
+public class InstructionFinder {
+
+ private static final int OFFSET = 32767; // char + OFFSET is
+ // outside of
+ // LATIN-1
+ private static final int NO_OPCODES = 256; // Potential number,
+ // some are not used
+ private static final Map map = new HashMap(); // Map<String,Pattern>
+ private InstructionList il;
+ private String il_string; // instruction list
+ // as string
+ private InstructionHandle[] handles; // map instruction
+
+
+ // list to array
+ /**
+ * @param il
+ * instruction list to search for given patterns
+ */
+ public InstructionFinder(InstructionList il) {
+ this.il = il;
+ reread();
+ }
+
+
+ /**
+ * Reread the instruction list, e.g., after you've altered the list upon a
+ * match.
+ */
+ public final void reread() {
+ int size = il.getLength();
+ char[] buf = new char[size]; // Create a string with length equal to il
+ // length
+ handles = il.getInstructionHandles();
+ // Map opcodes to characters
+ for (int i = 0; i < size; i++) {
+ buf[i] = makeChar(handles[i].getInstruction().getOpcode());
+ }
+ il_string = new String(buf);
+ }
+
+
+ /**
+ * Map symbolic instruction names like "getfield" to a single character.
+ *
+ * @param pattern
+ * instruction pattern in lower case
+ * @return encoded string for a pattern such as "BranchInstruction".
+ */
+ private static final String mapName( String pattern ) {
+ String result = (String) map.get(pattern);
+ if (result != null) {
+ return result;
+ }
+ for (short i = 0; i < NO_OPCODES; i++) {
+ if (pattern.equals(Constants.OPCODE_NAMES[i])) {
+ return "" + makeChar(i);
+ }
+ }
+ throw new RuntimeException("Instruction unknown: " + pattern);
+ }
+
+
+ /**
+ * Replace symbolic names of instructions with the appropiate character and
+ * remove all white space from string. Meta characters such as +, * are
+ * ignored.
+ *
+ * @param pattern
+ * The pattern to compile
+ * @return translated regular expression string
+ */
+ private static final String compilePattern( String pattern ) {
+ //Bug: 38787 - Instructions are assumed to be english, to avoid odd Locale issues
+ String lower = pattern.toLowerCase(Locale.ENGLISH);
+ StringBuffer buf = new StringBuffer();
+ int size = pattern.length();
+ for (int i = 0; i < size; i++) {
+ char ch = lower.charAt(i);
+ if (Character.isLetterOrDigit(ch)) {
+ StringBuffer name = new StringBuffer();
+ while ((Character.isLetterOrDigit(ch) || ch == '_') && i < size) {
+ name.append(ch);
+ if (++i < size) {
+ ch = lower.charAt(i);
+ } else {
+ break;
+ }
+ }
+ i--;
+ buf.append(mapName(name.toString()));
+ } else if (!Character.isWhitespace(ch)) {
+ buf.append(ch);
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return the matched piece of code as an array of instruction (handles)
+ */
+ private InstructionHandle[] getMatch( int matched_from, int match_length ) {
+ InstructionHandle[] match = new InstructionHandle[match_length];
+ System.arraycopy(handles, matched_from, match, 0, match_length);
+ return match;
+ }
+
+
+ /**
+ * Search for the given pattern in the instruction list. You can search for
+ * any valid opcode via its symbolic name, e.g. "istore". You can also use a
+ * super class or an interface name to match a whole set of instructions, e.g.
+ * "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all
+ * "istore_x" instructions. Additional aliases are "if" for "ifxx", "if_icmp"
+ * for "if_icmpxx", "if_acmp" for "if_acmpxx".
+ *
+ * Consecutive instruction names must be separated by white space which will
+ * be removed during the compilation of the pattern.
+ *
+ * For the rest the usual pattern matching rules for regular expressions
+ * apply.
+ * <P>
+ * Example pattern:
+ *
+ * <pre>
+ * search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
+ * </pre>
+ *
+ * <p>
+ * If you alter the instruction list upon a match such that other matching
+ * areas are affected, you should call reread() to update the finder and call
+ * search() again, because the matches are cached.
+ *
+ * @param pattern
+ * the instruction pattern to search for, where case is ignored
+ * @param from
+ * where to start the search in the instruction list
+ * @param constraint
+ * optional CodeConstraint to check the found code pattern for
+ * user-defined constraints
+ * @return iterator of matches where e.nextElement() returns an array of
+ * instruction handles describing the matched area
+ */
+ public final Iterator search( String pattern, InstructionHandle from, CodeConstraint constraint ) {
+ String search = compilePattern(pattern);
+ int start = -1;
+ for (int i = 0; i < handles.length; i++) {
+ if (handles[i] == from) {
+ start = i; // Where to start search from (index)
+ break;
+ }
+ }
+ if (start == -1) {
+ throw new ClassGenException("Instruction handle " + from
+ + " not found in instruction list.");
+ }
+ Pattern regex = Pattern.compile(search);
+ List matches = new ArrayList();
+ Matcher matcher = regex.matcher(il_string);
+ while (start < il_string.length() && matcher.find(start)) {
+ int startExpr = matcher.start();
+ int endExpr = matcher.end();
+ int lenExpr = (endExpr - startExpr);
+ InstructionHandle[] match = getMatch(startExpr, lenExpr);
+ if ((constraint == null) || constraint.checkCode(match)) {
+ matches.add(match);
+ }
+ start = endExpr;
+ }
+ return matches.iterator();
+ }
+
+
+ /**
+ * Start search beginning from the start of the given instruction list.
+ *
+ * @param pattern
+ * the instruction pattern to search for, where case is ignored
+ * @return iterator of matches where e.nextElement() returns an array of
+ * instruction handles describing the matched area
+ */
+ public final Iterator search( String pattern ) {
+ return search(pattern, il.getStart(), null);
+ }
+
+
+ /**
+ * Start search beginning from `from'.
+ *
+ * @param pattern
+ * the instruction pattern to search for, where case is ignored
+ * @param from
+ * where to start the search in the instruction list
+ * @return iterator of matches where e.nextElement() returns an array of
+ * instruction handles describing the matched area
+ */
+ public final Iterator search( String pattern, InstructionHandle from ) {
+ return search(pattern, from, null);
+ }
+
+
+ /**
+ * Start search beginning from the start of the given instruction list. Check
+ * found matches with the constraint object.
+ *
+ * @param pattern
+ * the instruction pattern to search for, case is ignored
+ * @param constraint
+ * constraints to be checked on matching code
+ * @return instruction handle or `null' if the match failed
+ */
+ public final Iterator search( String pattern, CodeConstraint constraint ) {
+ return search(pattern, il.getStart(), constraint);
+ }
+
+
+ /**
+ * Convert opcode number to char.
+ */
+ private static final char makeChar( short opcode ) {
+ return (char) (opcode + OFFSET);
+ }
+
+
+ /**
+ * @return the inquired instruction list
+ */
+ public final InstructionList getInstructionList() {
+ return il;
+ }
+
+ /**
+ * Code patterns found may be checked using an additional user-defined
+ * constraint object whether they really match the needed criterion. I.e.,
+ * check constraints that can not expressed with regular expressions.
+ *
+ */
+ public static interface CodeConstraint {
+
+ /**
+ * @param match
+ * array of instructions matching the requested pattern
+ * @return true if the matched area is really useful
+ */
+ public boolean checkCode( InstructionHandle[] match );
+ }
+
+ // Initialize pattern map
+ static {
+ map.put("arithmeticinstruction","(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)");
+ map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial)");
+ map.put("arrayinstruction", "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)");
+ map.put("gotoinstruction", "(goto|goto_w)");
+ map.put("conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)");
+ map.put("localvariableinstruction","(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)");
+ map.put("loadinstruction", "(fload|dload|lload|iload|aload)");
+ map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)");
+ map.put("cpinstruction", "(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)");
+ map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)");
+ map.put("branchinstruction", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
+ map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)");
+ map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)");
+ map.put("select", "(tableswitch|lookupswitch)");
+ map.put("ifinstruction", "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)");
+ map.put("jsrinstruction", "(jsr|jsr_w)");
+ map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)");
+ map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)");
+ map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)");
+ map.put("typedinstruction", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)");
+ map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)");
+ map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)");
+ map.put("indexedinstruction", "(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)");
+ map.put("pushinstruction", "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)");
+ map.put("stackproducer", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)");
+ map.put("stackconsumer", "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)");
+ map.put("exceptionthrower","(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)");
+ map.put("loadclass", "(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)");
+ map.put("instructiontargeter", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
+ // Some aliases
+ map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)");
+ map.put("if_acmp", "(if_acmpeq|if_acmpne)");
+ map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)");
+ // Precompile some aliases first
+ map.put("iconst", precompile(Constants.ICONST_0, Constants.ICONST_5, Constants.ICONST_M1));
+ map.put("lconst", new String(new char[] { '(', makeChar(Constants.LCONST_0), '|', makeChar(Constants.LCONST_1), ')' }));
+ map.put("dconst", new String(new char[] { '(', makeChar(Constants.DCONST_0), '|', makeChar(Constants.DCONST_1), ')' }));
+ map.put("fconst", new String(new char[] { '(', makeChar(Constants.FCONST_0), '|', makeChar(Constants.FCONST_1), ')' }));
+ map.put("iload", precompile(Constants.ILOAD_0, Constants.ILOAD_3, Constants.ILOAD));
+ map.put("dload", precompile(Constants.DLOAD_0, Constants.DLOAD_3, Constants.DLOAD));
+ map.put("fload", precompile(Constants.FLOAD_0, Constants.FLOAD_3, Constants.FLOAD));
+ map.put("aload", precompile(Constants.ALOAD_0, Constants.ALOAD_3, Constants.ALOAD));
+ map.put("istore", precompile(Constants.ISTORE_0, Constants.ISTORE_3, Constants.ISTORE));
+ map.put("dstore", precompile(Constants.DSTORE_0, Constants.DSTORE_3, Constants.DSTORE));
+ map.put("fstore", precompile(Constants.FSTORE_0, Constants.FSTORE_3, Constants.FSTORE));
+ map.put("astore", precompile(Constants.ASTORE_0, Constants.ASTORE_3, Constants.ASTORE));
+ // Compile strings
+ for (Iterator i = map.keySet().iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ String value = (String) map.get(key);
+ char ch = value.charAt(1); // Omit already precompiled patterns
+ if (ch < OFFSET) {
+ map.put(key, compilePattern(value)); // precompile all
+ // patterns
+ }
+ }
+ // Add instruction alias to match anything
+ StringBuffer buf = new StringBuffer("(");
+ for (short i = 0; i < NO_OPCODES; i++) {
+ if (Constants.NO_OF_OPERANDS[i] != Constants.UNDEFINED) { // Not
+ // an
+ // invalid
+ // opcode
+ buf.append(makeChar(i));
+ if (i < NO_OPCODES - 1) {
+ buf.append('|');
+ }
+ }
+ }
+ buf.append(')');
+ map.put("instruction", buf.toString());
+ }
+
+
+ private static String precompile( short from, short to, short extra ) {
+ StringBuffer buf = new StringBuffer("(");
+ for (short i = from; i <= to; i++) {
+ buf.append(makeChar(i));
+ buf.append('|');
+ }
+ buf.append(makeChar(extra));
+ buf.append(")");
+ return buf.toString();
+ }
+
+
+ /*
+ * Internal debugging routines.
+ */
+// private static final String pattern2string( String pattern ) {
+// return pattern2string(pattern, true);
+// }
+
+
+// private static final String pattern2string( String pattern, boolean make_string ) {
+// StringBuffer buf = new StringBuffer();
+// for (int i = 0; i < pattern.length(); i++) {
+// char ch = pattern.charAt(i);
+// if (ch >= OFFSET) {
+// if (make_string) {
+// buf.append(Constants.OPCODE_NAMES[ch - OFFSET]);
+// } else {
+// buf.append((ch - OFFSET));
+// }
+// } else {
+// buf.append(ch);
+// }
+// }
+// return buf.toString();
+// }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader
+ * to modify/generate classes as they're requested. You can take this as a template
+ * for your own applications.<br>
+ * Call this wrapper with
+ * <pre>java org.apache.tomcat.util.bcel.util.JavaWrapper <real.class.name> [arguments]</pre>
+ * <p>
+ * To use your own class loader you can set the "bcel.classloader" system property
+ * which defaults to "org.apache.tomcat.util.bcel.util.ClassLoader", e.g., with
+ * <pre>java org.apache.tomcat.util.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments]</pre>
+ * </p>
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @see ClassLoader
+ */
+public class JavaWrapper {
+
+ private java.lang.ClassLoader loader;
+
+
+ private static java.lang.ClassLoader getClassLoader() {
+ String s = System.getProperty("bcel.classloader");
+ if ((s == null) || "".equals(s)) {
+ s = "org.apache.tomcat.util.bcel.util.ClassLoader";
+ }
+ try {
+ return (java.lang.ClassLoader) Class.forName(s).newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString(), e);
+ }
+ }
+
+
+ public JavaWrapper(java.lang.ClassLoader loader) {
+ this.loader = loader;
+ }
+
+
+ public JavaWrapper() {
+ this(getClassLoader());
+ }
+
+
+ /** Runs the main method of the given class with the arguments passed in argv
+ *
+ * @param class_name the fully qualified class name
+ * @param argv the arguments just as you would pass them directly
+ */
+ public void runMain( String class_name, String[] argv ) throws ClassNotFoundException {
+ Class cl = loader.loadClass(class_name);
+ Method method = null;
+ try {
+ method = cl.getMethod("main", new Class[] {
+ argv.getClass()
+ });
+ /* Method main is sane ?
+ */
+ int m = method.getModifiers();
+ Class r = method.getReturnType();
+ if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m)
+ || (r != Void.TYPE)) {
+ throw new NoSuchMethodException();
+ }
+ } catch (NoSuchMethodException no) {
+ System.out.println("In class " + class_name
+ + ": public static void main(String[] argv) is not defined");
+ return;
+ }
+ try {
+ method.invoke(null, new Object[] {
+ argv
+ });
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+
+ /** Default main method used as wrapper, expects the fully qualified class name
+ * of the real class as the first argument.
+ */
+ public static void main( String[] argv ) throws Exception {
+ /* Expects class name as first argument, other arguments are by-passed.
+ */
+ if (argv.length == 0) {
+ System.out.println("Missing class name.");
+ return;
+ }
+ String class_name = argv[0];
+ String[] new_argv = new String[argv.length - 1];
+ System.arraycopy(argv, 1, new_argv, 0, new_argv.length);
+ JavaWrapper wrapper = new JavaWrapper();
+ wrapper.runMain(class_name, new_argv);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.apache.tomcat.util.bcel.classfile.Attribute;
+import org.apache.tomcat.util.bcel.classfile.Code;
+import org.apache.tomcat.util.bcel.classfile.ConstantValue;
+import org.apache.tomcat.util.bcel.classfile.ExceptionTable;
+import org.apache.tomcat.util.bcel.classfile.Field;
+import org.apache.tomcat.util.bcel.classfile.Method;
+import org.apache.tomcat.util.bcel.classfile.Utility;
+
+/**
+ * Convert methods and fields into HTML file.
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ *
+ */
+final class MethodHTML implements org.apache.tomcat.util.bcel.Constants {
+
+ private String class_name; // name of current class
+ private PrintWriter file; // file to write to
+ private ConstantHTML constant_html;
+ private AttributeHTML attribute_html;
+
+
+ MethodHTML(String dir, String class_name, Method[] methods, Field[] fields,
+ ConstantHTML constant_html, AttributeHTML attribute_html) throws IOException {
+ this.class_name = class_name;
+ this.attribute_html = attribute_html;
+ this.constant_html = constant_html;
+ file = new PrintWriter(new FileOutputStream(dir + class_name + "_methods.html"));
+ file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
+ file.println("<TR><TH ALIGN=LEFT>Access flags</TH><TH ALIGN=LEFT>Type</TH>"
+ + "<TH ALIGN=LEFT>Field name</TH></TR>");
+ for (int i = 0; i < fields.length; i++) {
+ writeField(fields[i]);
+ }
+ file.println("</TABLE>");
+ file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Access flags</TH>"
+ + "<TH ALIGN=LEFT>Return type</TH><TH ALIGN=LEFT>Method name</TH>"
+ + "<TH ALIGN=LEFT>Arguments</TH></TR>");
+ for (int i = 0; i < methods.length; i++) {
+ writeMethod(methods[i], i);
+ }
+ file.println("</TABLE></BODY></HTML>");
+ file.close();
+ }
+
+
+ /**
+ * Print field of class.
+ *
+ * @param field field to print
+ * @exception java.io.IOException
+ */
+ private void writeField( Field field ) throws IOException {
+ String type = Utility.signatureToString(field.getSignature());
+ String name = field.getName();
+ String access = Utility.accessToString(field.getAccessFlags());
+ Attribute[] attributes;
+ access = Utility.replace(access, " ", " ");
+ file.print("<TR><TD><FONT COLOR=\"#FF0000\">" + access + "</FONT></TD>\n<TD>"
+ + Class2HTML.referenceType(type) + "</TD><TD><A NAME=\"field" + name + "\">" + name
+ + "</A></TD>");
+ attributes = field.getAttributes();
+ // Write them to the Attributes.html file with anchor "<name>[<i>]"
+ for (int i = 0; i < attributes.length; i++) {
+ attribute_html.writeAttribute(attributes[i], name + "@" + i);
+ }
+ for (int i = 0; i < attributes.length; i++) {
+ if (attributes[i].getTag() == ATTR_CONSTANT_VALUE) { // Default value
+ String str = ((ConstantValue) attributes[i]).toString();
+ // Reference attribute in _attributes.html
+ file.print("<TD>= <A HREF=\"" + class_name + "_attributes.html#" + name + "@" + i
+ + "\" TARGET=\"Attributes\">" + str + "</TD>\n");
+ break;
+ }
+ }
+ file.println("</TR>");
+ }
+
+
+ private final void writeMethod( Method method, int method_number ) throws IOException {
+ // Get raw signature
+ String signature = method.getSignature();
+ // Get array of strings containing the argument types
+ String[] args = Utility.methodSignatureArgumentTypes(signature, false);
+ // Get return type string
+ String type = Utility.methodSignatureReturnType(signature, false);
+ // Get method name
+ String name = method.getName(), html_name;
+ // Get method's access flags
+ String access = Utility.accessToString(method.getAccessFlags());
+ // Get the method's attributes, the Code Attribute in particular
+ Attribute[] attributes = method.getAttributes();
+ /* HTML doesn't like names like <clinit> and spaces are places to break
+ * lines. Both we don't want...
+ */
+ access = Utility.replace(access, " ", " ");
+ html_name = Class2HTML.toHTML(name);
+ file.print("<TR VALIGN=TOP><TD><FONT COLOR=\"#FF0000\"><A NAME=method" + method_number
+ + ">" + access + "</A></FONT></TD>");
+ file.print("<TD>" + Class2HTML.referenceType(type) + "</TD><TD>" + "<A HREF=" + class_name
+ + "_code.html#method" + method_number + " TARGET=Code>" + html_name
+ + "</A></TD>\n<TD>(");
+ for (int i = 0; i < args.length; i++) {
+ file.print(Class2HTML.referenceType(args[i]));
+ if (i < args.length - 1) {
+ file.print(", ");
+ }
+ }
+ file.print(")</TD></TR>");
+ // Check for thrown exceptions
+ for (int i = 0; i < attributes.length; i++) {
+ attribute_html.writeAttribute(attributes[i], "method" + method_number + "@" + i,
+ method_number);
+ byte tag = attributes[i].getTag();
+ if (tag == ATTR_EXCEPTIONS) {
+ file.print("<TR VALIGN=TOP><TD COLSPAN=2></TD><TH ALIGN=LEFT>throws</TH><TD>");
+ int[] exceptions = ((ExceptionTable) attributes[i]).getExceptionIndexTable();
+ for (int j = 0; j < exceptions.length; j++) {
+ file.print(constant_html.referenceConstant(exceptions[j]));
+ if (j < exceptions.length - 1) {
+ file.print(", ");
+ }
+ }
+ file.println("</TD></TR>");
+ } else if (tag == ATTR_CODE) {
+ Attribute[] c_a = ((Code) attributes[i]).getAttributes();
+ for (int j = 0; j < c_a.length; j++) {
+ attribute_html.writeAttribute(c_a[j], "method" + method_number + "@" + i + "@"
+ + j, method_number);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * Abstract definition of a class repository. Instances may be used
+ * to load classes from different sources and may be used in the
+ * Repository.setRepository method.
+ *
+ * @see org.apache.tomcat.util.bcel.Repository
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @author David Dixon-Peugh
+ */
+public interface Repository extends java.io.Serializable {
+
+ /**
+ * Store the provided class under "clazz.getClassName()"
+ */
+ public void storeClass( JavaClass clazz );
+
+
+ /**
+ * Remove class from repository
+ */
+ public void removeClass( JavaClass clazz );
+
+
+ /**
+ * Find the class with the name provided, if the class
+ * isn't there, return NULL.
+ */
+ public JavaClass findClass( String className );
+
+
+ /**
+ * Find the class with the name provided, if the class
+ * isn't there, make an attempt to load it.
+ */
+ public JavaClass loadClass( String className ) throws java.lang.ClassNotFoundException;
+
+
+ /**
+ * Find the JavaClass instance for the given run-time class object
+ */
+ public JavaClass loadClass( Class clazz ) throws java.lang.ClassNotFoundException;
+
+
+ /** Clear all entries from cache.
+ */
+ public void clear();
+
+
+ /** Get the ClassPath associated with this Repository
+ */
+ public ClassPath getClassPath();
+}
--- /dev/null
+/*
+ * Copyright 2000-2009 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tomcat.util.bcel.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.tomcat.util.bcel.classfile.ClassParser;
+import org.apache.tomcat.util.bcel.classfile.JavaClass;
+
+/**
+ * This repository is used in situations where a Class is created
+ * outside the realm of a ClassLoader. Classes are loaded from
+ * the file systems using the paths specified in the given
+ * class path. By default, this is the value returned by
+ * ClassPath.getClassPath().
+ * <br>
+ * It is designed to be used as a singleton, however it
+ * can also be used with custom classpaths.
+ *
+ /**
+ * Abstract definition of a class repository. Instances may be used
+ * to load classes from different sources and may be used in the
+ * Repository.setRepository method.
+ *
+ * @see org.apache.tomcat.util.bcel.Repository
+ *
+ * @version $Id$
+ * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
+ * @author David Dixon-Peugh
+ */
+public class SyntheticRepository implements Repository {
+
+ //private static final String DEFAULT_PATH = ClassPath.getClassPath();
+ private static Map _instances = new HashMap(); // CLASSPATH X REPOSITORY
+ private ClassPath _path = null;
+ private Map _loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
+
+
+ private SyntheticRepository(ClassPath path) {
+ _path = path;
+ }
+
+
+ public static SyntheticRepository getInstance() {
+ return getInstance(ClassPath.SYSTEM_CLASS_PATH);
+ }
+
+
+ public static SyntheticRepository getInstance( ClassPath classPath ) {
+ SyntheticRepository rep = (SyntheticRepository) _instances.get(classPath);
+ if (rep == null) {
+ rep = new SyntheticRepository(classPath);
+ _instances.put(classPath, rep);
+ }
+ return rep;
+ }
+
+
+ /**
+ * Store a new JavaClass instance into this Repository.
+ */
+ public void storeClass( JavaClass clazz ) {
+ _loadedClasses.put(clazz.getClassName(), new SoftReference(clazz));
+ clazz.setRepository(this);
+ }
+
+
+ /**
+ * Remove class from repository
+ */
+ public void removeClass( JavaClass clazz ) {
+ _loadedClasses.remove(clazz.getClassName());
+ }
+
+
+ /**
+ * Find an already defined (cached) JavaClass object by name.
+ */
+ public JavaClass findClass( String className ) {
+ SoftReference ref = (SoftReference) _loadedClasses.get(className);
+ if (ref == null) {
+ return null;
+ }
+ return (JavaClass) ref.get();
+ }
+
+
+ /**
+ * Find a JavaClass object by name.
+ * If it is already in this Repository, the Repository version
+ * is returned. Otherwise, the Repository's classpath is searched for
+ * the class (and it is added to the Repository if found).
+ *
+ * @param className the name of the class
+ * @return the JavaClass object
+ * @throws ClassNotFoundException if the class is not in the
+ * Repository, and could not be found on the classpath
+ */
+ public JavaClass loadClass( String className ) throws ClassNotFoundException {
+ if (className == null || className.equals("")) {
+ throw new IllegalArgumentException("Invalid class name " + className);
+ }
+ className = className.replace('/', '.'); // Just in case, canonical form
+ JavaClass clazz = findClass(className);
+ if (clazz != null) {
+ return clazz;
+ }
+ try {
+ return loadClass(_path.getInputStream(className), className);
+ } catch (IOException e) {
+ throw new ClassNotFoundException("Exception while looking for class " + className
+ + ": " + e.toString(), e);
+ }
+ }
+
+
+ /**
+ * Find the JavaClass object for a runtime Class object.
+ * If a class with the same name is already in this Repository,
+ * the Repository version is returned. Otherwise, getResourceAsStream()
+ * is called on the Class object to find the class's representation.
+ * If the representation is found, it is added to the Repository.
+ *
+ * @see Class
+ * @param clazz the runtime Class object
+ * @return JavaClass object for given runtime class
+ * @throws ClassNotFoundException if the class is not in the
+ * Repository, and its representation could not be found
+ */
+ public JavaClass loadClass( Class clazz ) throws ClassNotFoundException {
+ InputStream clsStream = null;
+ try{
+ String className = clazz.getName();
+ JavaClass repositoryClass = findClass(className);
+ if (repositoryClass != null) {
+ return repositoryClass;
+ }
+ String name = className;
+ int i = name.lastIndexOf('.');
+ if (i > 0) {
+ name = name.substring(i + 1);
+ }
+ clsStream = clazz.getResourceAsStream(name + ".class");
+ return loadClass(clsStream, className);
+ } finally {
+ try{
+ if (clsStream != null){
+ clsStream.close();
+ }
+ } catch(IOException ioe){
+ //don't care
+ }
+ }
+ }
+
+
+ private JavaClass loadClass( InputStream is, String className ) throws ClassNotFoundException {
+ try {
+ if (is != null) {
+ ClassParser parser = new ClassParser(is, className);
+ JavaClass clazz = parser.parse();
+ storeClass(clazz);
+ return clazz;
+ }
+ } catch (IOException e) {
+ throw new ClassNotFoundException("Exception while looking for class " + className
+ + ": " + e.toString(), e);
+ }
+ throw new ClassNotFoundException("SyntheticRepository could not load " + className);
+ }
+
+
+ /** ClassPath associated with the Repository.
+ */
+ public ClassPath getClassPath() {
+ return _path;
+ }
+
+
+ /** Clear all entries from cache.
+ */
+ public void clear() {
+ _loadedClasses.clear();
+ }
+}
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+$Id$
+-->
+</head>
+<body bgcolor="white">
+<p>
+This package contains utility classes for the
+<a href="http://jakarta.apache.org/bcel/">Byte Code Engineering
+Library</a>, namely:
+</p>
+<p>
+<ul>
+<li>Collection classes for JavaClass objects</li>
+<li>A converter for class files to HTML</li>
+<li>A tool to find instructions patterns via regular expressions</li>
+<li>A class to find classes as defined in the CLASSPATH</li>
+<li>A class loader that allows to create classes at run time</li>
+</ul>
+
+</p>
+</body>
+</html>