diff options
author | Andy Clement <aclement@pivotal.io> | 2019-01-24 12:41:06 -0800 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-01-24 12:41:06 -0800 |
commit | 9659cfe976a424a20e7b840152a13d266e794226 (patch) | |
tree | 0ae99f276260be65a84660bc37bd7ebbed908e63 /bcel-builder/src/main | |
parent | 52c4cbfa1b8bcc0d2c7ac50c77203e516b335205 (diff) | |
download | aspectj-9659cfe976a424a20e7b840152a13d266e794226.tar.gz aspectj-9659cfe976a424a20e7b840152a13d266e794226.zip |
mavenizing bcel-builder - complete
Diffstat (limited to 'bcel-builder/src/main')
136 files changed, 28559 insertions, 0 deletions
diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/Constants.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/Constants.java new file mode 100644 index 000000000..c75496527 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/Constants.java @@ -0,0 +1,685 @@ +package org.aspectj.apache.bcel; + +import org.aspectj.apache.bcel.generic.Type; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * Constants for the project, mostly defined in the JVM specification. + * + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author Andy Clement + */ +public interface Constants { + // Major and minor version of the code + public final static short MAJOR_1_1 = 45; + public final static short MINOR_1_1 = 3; + public final static short MAJOR_1_2 = 46; + public final static short MINOR_1_2 = 0; + public final static short MAJOR_1_3 = 47; + public final static short MINOR_1_3 = 0; + public final static short MAJOR_1_4 = 48; + public final static short MINOR_1_4 = 0; + public final static short MAJOR_1_5 = 49; + public final static short MINOR_1_5 = 0; + public final static short MAJOR_1_6 = 50; + public final static short MINOR_1_6 = 0; + public final static short MAJOR_1_7 = 51; + public final static short MINOR_1_7 = 0; + public final static short MAJOR_1_8 = 52; + public final static short MINOR_1_8 = 0; + public final static short MAJOR_1_9 = 53; + public final static short MINOR_1_9 = 0; + public final static short MAJOR_10 = 54; + public final static short MINOR_10 = 0; + public final static short MAJOR_11 = 55; + public final static short MINOR_11 = 0; + // Defaults + public final static short MAJOR = 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 + + /** Access flags for classes, fields and methods */ + public final static short ACC_PUBLIC = 0x0001; + public final static short ACC_PRIVATE = 0x0002; + public final static short ACC_PROTECTED = 0x0004; + public final static short ACC_STATIC = 0x0008; + + public final static short ACC_FINAL = 0x0010; + public final static short ACC_SYNCHRONIZED = 0x0020; + public final static short ACC_VOLATILE = 0x0040; + public final static short ACC_TRANSIENT = 0x0080; + + public final static short ACC_NATIVE = 0x0100; + public final static short ACC_INTERFACE = 0x0200; + public final static short ACC_ABSTRACT = 0x0400; + public final static short ACC_STRICT = 0x0800; + + public final static short ACC_SYNTHETIC = 0x1000; + + public final static short ACC_ANNOTATION = 0x2000; + public final static short ACC_ENUM = 0x4000; + public final static int ACC_MODULE = 0x8000; + public final static short ACC_BRIDGE = 0x0040; + public final static short ACC_VARARGS = 0x0080; + + // Module related + // Indicates that any module which depends on the current module, + // implicitly declares a dependence on the module indicated by this entry. + public final static int MODULE_ACC_TRANSITIVE = 0x0020; + // Indicates that this dependence is mandatory in the static phase, i.e., at + // compile time, but is optional in the dynamic phase, i.e., at run time. + public final static int MODULE_ACC_STATIC_PHASE = 0x0040; + // Indicates that this dependence was not explicitly or implicitly declared + // in the source of the module declaration. + public final static int MODULE_ACC_SYNTHETIC = 0x1000; + // Indicates that this dependence was implicitly declared in the source of + // the module declaration + public final static int MODULE_ACC_MANDATED = 0x8000; + + // Applies to classes compiled by new compilers only + public final static short ACC_SUPER = 0x0020; + + public final static short MAX_ACC_FLAG = ACC_STRICT; + + public final static String[] ACCESS_NAMES = { "public", "private", "protected", "static", "final", "synchronized", "volatile", + "transient", "native", "interface", "abstract", "strictfp" }; + + /** Tags in constant pool to denote type of constant */ + public final static byte CONSTANT_Utf8 = 1; + public final static byte CONSTANT_Integer = 3; + public final static byte CONSTANT_Float = 4; + public final static byte CONSTANT_Long = 5; + public final static byte CONSTANT_Double = 6; + public final static byte CONSTANT_Class = 7; + public final static byte CONSTANT_Fieldref = 9; + public final static byte CONSTANT_String = 8; + public final static byte CONSTANT_Methodref = 10; + public final static byte CONSTANT_InterfaceMethodref = 11; + public final static byte CONSTANT_NameAndType = 12; + + public final static byte CONSTANT_MethodHandle = 15; + public final static byte CONSTANT_MethodType = 16; + public final static byte CONSTANT_Dynamic = 17; + public final static byte CONSTANT_InvokeDynamic = 18; + + public final static byte CONSTANT_Module = 19; + public final static byte CONSTANT_Package = 20; + + + 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","","","CONSTANT_MethodHandle","CONSTANT_MethodType","","CONSTANT_InvokeDynamic", + // J9: + "CONSTANT_Module", "CONSTANT_Package"}; + + /** + * 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" }; + + /** + * Limitations of the Java Virtual Machine. See The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10. + */ + public static final int MAX_CP_ENTRIES = 65535; + public static final int MAX_CODE_SIZE = 65536; // bytes + + /** + * Java VM opcodes. + */ + public static final short NOP = 0; + public static final short ACONST_NULL = 1; + public static final short ICONST_M1 = 2; + public static final short ICONST_0 = 3; + public static final short ICONST_1 = 4; + public static final short ICONST_2 = 5; + public static final short ICONST_3 = 6; + public static final short ICONST_4 = 7; + public static final short ICONST_5 = 8; + public static final short LCONST_0 = 9; + public static final short LCONST_1 = 10; + public static final short FCONST_0 = 11; + public static final short FCONST_1 = 12; + public static final short FCONST_2 = 13; + public static final short DCONST_0 = 14; + public static final short DCONST_1 = 15; + public static final short BIPUSH = 16; + public static final short SIPUSH = 17; + public static final short LDC = 18; + public static final short LDC_W = 19; + public static final short LDC2_W = 20; + public static final short ILOAD = 21; + public static final short LLOAD = 22; + public static final short FLOAD = 23; + public static final short DLOAD = 24; + public static final short ALOAD = 25; + public static final short ILOAD_0 = 26; + public static final short ILOAD_1 = 27; + public static final short ILOAD_2 = 28; + public static final short ILOAD_3 = 29; + public static final short LLOAD_0 = 30; + public static final short LLOAD_1 = 31; + public static final short LLOAD_2 = 32; + public static final short LLOAD_3 = 33; + public static final short FLOAD_0 = 34; + public static final short FLOAD_1 = 35; + public static final short FLOAD_2 = 36; + public static final short FLOAD_3 = 37; + public static final short DLOAD_0 = 38; + public static final short DLOAD_1 = 39; + public static final short DLOAD_2 = 40; + public static final short DLOAD_3 = 41; + public static final short ALOAD_0 = 42; + public static final short ALOAD_1 = 43; + public static final short ALOAD_2 = 44; + public static final short ALOAD_3 = 45; + public static final short IALOAD = 46; + public static final short LALOAD = 47; + public static final short FALOAD = 48; + public static final short DALOAD = 49; + public static final short AALOAD = 50; + public static final short BALOAD = 51; + public static final short CALOAD = 52; + public static final short SALOAD = 53; + public static final short ISTORE = 54; + public static final short LSTORE = 55; + public static final short FSTORE = 56; + public static final short DSTORE = 57; + public static final short ASTORE = 58; + public static final short ISTORE_0 = 59; + public static final short ISTORE_1 = 60; + public static final short ISTORE_2 = 61; + public static final short ISTORE_3 = 62; + public static final short LSTORE_0 = 63; + public static final short LSTORE_1 = 64; + public static final short LSTORE_2 = 65; + public static final short LSTORE_3 = 66; + public static final short FSTORE_0 = 67; + public static final short FSTORE_1 = 68; + public static final short FSTORE_2 = 69; + public static final short FSTORE_3 = 70; + public static final short DSTORE_0 = 71; + public static final short DSTORE_1 = 72; + public static final short DSTORE_2 = 73; + public static final short DSTORE_3 = 74; + public static final short ASTORE_0 = 75; + public static final short ASTORE_1 = 76; + public static final short ASTORE_2 = 77; + public static final short ASTORE_3 = 78; + public static final short IASTORE = 79; + public static final short LASTORE = 80; + public static final short FASTORE = 81; + public static final short DASTORE = 82; + public static final short AASTORE = 83; + public static final short BASTORE = 84; + public static final short CASTORE = 85; + public static final short SASTORE = 86; + public static final short POP = 87; + public static final short POP2 = 88; + public static final short DUP = 89; + public static final short DUP_X1 = 90; + public static final short DUP_X2 = 91; + public static final short DUP2 = 92; + public static final short DUP2_X1 = 93; + public static final short DUP2_X2 = 94; + public static final short SWAP = 95; + public static final short IADD = 96; + public static final short LADD = 97; + public static final short FADD = 98; + public static final short DADD = 99; + public static final short ISUB = 100; + public static final short LSUB = 101; + public static final short FSUB = 102; + public static final short DSUB = 103; + public static final short IMUL = 104; + public static final short LMUL = 105; + public static final short FMUL = 106; + public static final short DMUL = 107; + public static final short IDIV = 108; + public static final short LDIV = 109; + public static final short FDIV = 110; + public static final short DDIV = 111; + public static final short IREM = 112; + public static final short LREM = 113; + public static final short FREM = 114; + public static final short DREM = 115; + public static final short INEG = 116; + public static final short LNEG = 117; + public static final short FNEG = 118; + public static final short DNEG = 119; + public static final short ISHL = 120; + public static final short LSHL = 121; + public static final short ISHR = 122; + public static final short LSHR = 123; + public static final short IUSHR = 124; + public static final short LUSHR = 125; + public static final short IAND = 126; + public static final short LAND = 127; + public static final short IOR = 128; + public static final short LOR = 129; + public static final short IXOR = 130; + public static final short LXOR = 131; + public static final short IINC = 132; + public static final short I2L = 133; + public static final short I2F = 134; + public static final short I2D = 135; + public static final short L2I = 136; + public static final short L2F = 137; + public static final short L2D = 138; + public static final short F2I = 139; + public static final short F2L = 140; + public static final short F2D = 141; + public static final short D2I = 142; + public static final short D2L = 143; + public static final short D2F = 144; + public static final short I2B = 145; + public static final short INT2BYTE = 145; // Old notion + public static final short I2C = 146; + public static final short INT2CHAR = 146; // Old notion + public static final short I2S = 147; + public static final short INT2SHORT = 147; // Old notion + public static final short LCMP = 148; + public static final short FCMPL = 149; + public static final short FCMPG = 150; + public static final short DCMPL = 151; + public static final short DCMPG = 152; + public static final short IFEQ = 153; + public static final short IFNE = 154; + public static final short IFLT = 155; + public static final short IFGE = 156; + public static final short IFGT = 157; + public static final short IFLE = 158; + public static final short IF_ICMPEQ = 159; + public static final short IF_ICMPNE = 160; + public static final short IF_ICMPLT = 161; + public static final short IF_ICMPGE = 162; + public static final short IF_ICMPGT = 163; + public static final short IF_ICMPLE = 164; + public static final short IF_ACMPEQ = 165; + public static final short IF_ACMPNE = 166; + public static final short GOTO = 167; + public static final short JSR = 168; + public static final short RET = 169; + public static final short TABLESWITCH = 170; + public static final short LOOKUPSWITCH = 171; + public static final short IRETURN = 172; + public static final short LRETURN = 173; + public static final short FRETURN = 174; + public static final short DRETURN = 175; + public static final short ARETURN = 176; + public static final short RETURN = 177; + public static final short GETSTATIC = 178; + public static final short PUTSTATIC = 179; + public static final short GETFIELD = 180; + public static final short PUTFIELD = 181; + public static final short INVOKEVIRTUAL = 182; + public static final short INVOKESPECIAL = 183; + public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0 + public static final short INVOKESTATIC = 184; + public static final short INVOKEINTERFACE = 185; + public static final short INVOKEDYNAMIC = 186; + public static final short NEW = 187; + public static final short NEWARRAY = 188; + public static final short ANEWARRAY = 189; + public static final short ARRAYLENGTH = 190; + public static final short ATHROW = 191; + public static final short CHECKCAST = 192; + public static final short INSTANCEOF = 193; + public static final short MONITORENTER = 194; + public static final short MONITOREXIT = 195; + public static final short WIDE = 196; + public static final short MULTIANEWARRAY = 197; + public static final short IFNULL = 198; + public static final short IFNONNULL = 199; + public static final short GOTO_W = 200; + public static final short JSR_W = 201; + + /** + * Non-legal opcodes, may be used by JVM internally. + */ + public static final short BREAKPOINT = 202; + public static final short LDC_QUICK = 203; + public static final short LDC_W_QUICK = 204; + public static final short LDC2_W_QUICK = 205; + public static final short GETFIELD_QUICK = 206; + public static final short PUTFIELD_QUICK = 207; + public static final short GETFIELD2_QUICK = 208; + public static final short PUTFIELD2_QUICK = 209; + public static final short GETSTATIC_QUICK = 210; + public static final short PUTSTATIC_QUICK = 211; + public static final short GETSTATIC2_QUICK = 212; + public static final short PUTSTATIC2_QUICK = 213; + public static final short INVOKEVIRTUAL_QUICK = 214; + public static final short INVOKENONVIRTUAL_QUICK = 215; + public static final short INVOKESUPER_QUICK = 216; + public static final short INVOKESTATIC_QUICK = 217; + public static final short INVOKEINTERFACE_QUICK = 218; + public static final short INVOKEVIRTUALOBJECT_QUICK = 219; + public static final short NEW_QUICK = 221; + public static final short ANEWARRAY_QUICK = 222; + public static final short MULTIANEWARRAY_QUICK = 223; + public static final short CHECKCAST_QUICK = 224; + public static final short INSTANCEOF_QUICK = 225; + public static final short INVOKEVIRTUAL_QUICK_W = 226; + public static final short GETFIELD_QUICK_W = 227; + public static final short PUTFIELD_QUICK_W = 228; + public static final short IMPDEP1 = 254; + public static final short IMPDEP2 = 255; + + /** + * For internal purposes only. + */ + public static final short PUSH = 4711; + public static final short SWITCH = 4712; + + /** + * Illegal codes + */ + public static final short UNDEFINED = '/' - '0'; // -1; + public static final short UNPREDICTABLE = '.' - '0';// -2; + public static final short RESERVED = -3; + public static final String ILLEGAL_OPCODE = "<illegal opcode>"; + public static final String ILLEGAL_TYPE = "<illegal type>"; + + public static final byte T_BOOLEAN = 4; + public static final byte T_CHAR = 5; + public static final byte T_FLOAT = 6; + public static final byte T_DOUBLE = 7; + public static final byte T_BYTE = 8; + public static final byte T_SHORT = 9; + public static final byte T_INT = 10; + public static final byte T_LONG = 11; + + public static final byte T_VOID = 12; // Non-standard + public static final byte T_ARRAY = 13; + public static final byte T_OBJECT = 14; + public static final byte T_REFERENCE = 14; // Deprecated + public static final byte T_UNKNOWN = 15; + 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" // Non-standard + }; + + /** + * 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 }; + + /** + * 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 }; + + public static int PUSH_INST = 0x0001; + public static int CONSTANT_INST = 0x0002; + public static long LOADCLASS_INST = 0x0004; + public static int CP_INST = 0x0008; + public static int INDEXED = 0x0010; + public static int LOAD_INST = 0x0020; // load instruction + public static int LV_INST = 0x0040; // local variable instruction + public static int POP_INST = 0x0080; + public static int STORE_INST = 0x0100; + public static long STACK_INST = 0x0200; + public static long BRANCH_INSTRUCTION = 0x0400; + public static long TARGETER_INSTRUCTION = 0x0800; + public static long NEGATABLE = 0x1000; + public static long IF_INST = 0x2000; + public static long JSR_INSTRUCTION = 0x4000; + public static long RET_INST = 0x8000; + public static long EXCEPTION_THROWER = 0x10000; + + public static final byte[] iLen = new byte[256]; + public static final byte UNDEFINED_LENGTH = 'X' - '0'; + public static final byte VARIABLE_LENGTH = 'V' - '0'; + public static final byte[] stackEntriesProduced = new byte[256]; + public static final Type[] types = new Type[256]; + public static final long[] instFlags = new long[256]; + + public static final Class<Throwable>[][] instExcs = new Class[256][]; + + static final Object _unused = ConstantsInitializer.initialize(); + + /** + * How the byte code operands are to be interpreted. + */ + 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. + */ + 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", "invokedynamic", "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. + */ + 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 */ + }; + + // 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_RUNTIME_INVISIBLE_ANNOTATIONS = 13; + public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = 14; + public static final byte ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = 15; + public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 16; + public static final byte ATTR_ENCLOSING_METHOD = 17; + public static final byte ATTR_ANNOTATION_DEFAULT = 18; + public static final byte ATTR_BOOTSTRAPMETHODS = 19; + public static final byte ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = 20; + public static final byte ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = 21; + public static final byte ATTR_METHOD_PARAMETERS = 22; + + // J9: + public static final byte ATTR_MODULE = 23; + public static final byte ATTR_MODULE_PACKAGES = 24; + public static final byte ATTR_MODULE_MAIN_CLASS = 25; + + // J11: + public static final byte ATTR_NEST_HOST = 26; + public static final byte ATTR_NEST_MEMBERS = 27; + + public static final short KNOWN_ATTRIBUTES = 28; + + public static final String[] ATTRIBUTE_NAMES = { + "SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable", + "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap", + "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations", + "RuntimeInvisibleParameterAnnotations", "LocalVariableTypeTable", "EnclosingMethod", + "AnnotationDefault","BootstrapMethods", "RuntimeVisibleTypeAnnotations", "RuntimeInvisibleTypeAnnotations", + "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers" + }; + + /** + * 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" }; +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/ConstantsInitializer.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/ConstantsInitializer.java new file mode 100644 index 000000000..b9bc0d49f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/ConstantsInitializer.java @@ -0,0 +1,396 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel; + +import org.aspectj.apache.bcel.generic.Type; + +public class ConstantsInitializer { + + public static Object initialize() { + Constants.types[Constants.ILOAD] = Type.INT; + Constants.types[Constants.ISTORE] = Type.INT; + Constants.types[Constants.ILOAD_0] = Type.INT; + Constants.types[Constants.ISTORE_0] = Type.INT; + Constants.types[Constants.ILOAD_1] = Type.INT; + Constants.types[Constants.ISTORE_1] = Type.INT; + Constants.types[Constants.ILOAD_2] = Type.INT; + Constants.types[Constants.ISTORE_2] = Type.INT; + Constants.types[Constants.ILOAD_3] = Type.INT; + Constants.types[Constants.ISTORE_3] = Type.INT; + Constants.types[Constants.LLOAD] = Type.LONG; + Constants.types[Constants.LSTORE] = Type.LONG; + Constants.types[Constants.LLOAD_0] = Type.LONG; + Constants.types[Constants.LSTORE_0] = Type.LONG; + Constants.types[Constants.LLOAD_1] = Type.LONG; + Constants.types[Constants.LSTORE_1] = Type.LONG; + Constants.types[Constants.LLOAD_2] = Type.LONG; + Constants.types[Constants.LSTORE_2] = Type.LONG; + Constants.types[Constants.LLOAD_3] = Type.LONG; + Constants.types[Constants.LSTORE_3] = Type.LONG; + Constants.types[Constants.DLOAD] = Type.DOUBLE; + Constants.types[Constants.DSTORE] = Type.DOUBLE; + Constants.types[Constants.DLOAD_0] = Type.DOUBLE; + Constants.types[Constants.DSTORE_0] = Type.DOUBLE; + Constants.types[Constants.DLOAD_1] = Type.DOUBLE; + Constants.types[Constants.DSTORE_1] = Type.DOUBLE; + Constants.types[Constants.DLOAD_2] = Type.DOUBLE; + Constants.types[Constants.DSTORE_2] = Type.DOUBLE; + Constants.types[Constants.DLOAD_3] = Type.DOUBLE; + Constants.types[Constants.DSTORE_3] = Type.DOUBLE; + Constants.types[Constants.FLOAD] = Type.FLOAT; + Constants.types[Constants.FSTORE] = Type.FLOAT; + Constants.types[Constants.FLOAD_0] = Type.FLOAT; + Constants.types[Constants.FSTORE_0] = Type.FLOAT; + Constants.types[Constants.FLOAD_1] = Type.FLOAT; + Constants.types[Constants.FSTORE_1] = Type.FLOAT; + Constants.types[Constants.FLOAD_2] = Type.FLOAT; + Constants.types[Constants.FSTORE_2] = Type.FLOAT; + Constants.types[Constants.FLOAD_3] = Type.FLOAT; + Constants.types[Constants.FSTORE_3] = Type.FLOAT; + Constants.types[Constants.ALOAD] = Type.OBJECT; + Constants.types[Constants.ASTORE] = Type.OBJECT; + Constants.types[Constants.ALOAD_0] = Type.OBJECT; + Constants.types[Constants.ASTORE_0] = Type.OBJECT; + Constants.types[Constants.ALOAD_1] = Type.OBJECT; + Constants.types[Constants.ASTORE_1] = Type.OBJECT; + Constants.types[Constants.ALOAD_2] = Type.OBJECT; + Constants.types[Constants.ASTORE_2] = Type.OBJECT; + Constants.types[Constants.ALOAD_3] = Type.OBJECT; + Constants.types[Constants.ASTORE_3] = Type.OBJECT; + + // INSTRUCTION_FLAGS - set for all + Constants.instFlags[Constants.NOP] = 0; + Constants.instFlags[Constants.ACONST_NULL] = Constants.PUSH_INST; + Constants.instFlags[Constants.ICONST_M1] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_0] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_1] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_2] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_3] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_4] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.ICONST_5] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.LCONST_0] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.LCONST_1] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.FCONST_0] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.FCONST_1] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.FCONST_2] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.DCONST_0] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.DCONST_1] = Constants.PUSH_INST | Constants.CONSTANT_INST; + + Constants.instFlags[Constants.BIPUSH] = Constants.PUSH_INST | Constants.CONSTANT_INST; + Constants.instFlags[Constants.SIPUSH] = Constants.PUSH_INST | Constants.CONSTANT_INST; + + Constants.instFlags[Constants.LDC] = Constants.EXCEPTION_THROWER | Constants.PUSH_INST | Constants.CP_INST + | Constants.INDEXED; + + Constants.instFlags[Constants.LDC_W] = Constants.EXCEPTION_THROWER | Constants.PUSH_INST | Constants.CP_INST + | Constants.INDEXED; + + Constants.instFlags[Constants.LDC2_W] = Constants.EXCEPTION_THROWER | Constants.PUSH_INST | Constants.CP_INST + | Constants.INDEXED; + + // the next five could be 'wide' prefixed and so have longer lengths + Constants.instFlags[Constants.ILOAD] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + Constants.instFlags[Constants.LLOAD] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + Constants.instFlags[Constants.FLOAD] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + Constants.instFlags[Constants.DLOAD] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + Constants.instFlags[Constants.ALOAD] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + for (int ii = Constants.ILOAD_0; ii <= Constants.ALOAD_3; ii++) { + Constants.instFlags[ii] = Constants.INDEXED | Constants.LOAD_INST | Constants.PUSH_INST | Constants.LV_INST; + } + + // the next five could be 'wide' prefixed and so have longer lengths + Constants.instFlags[Constants.ISTORE] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + Constants.instFlags[Constants.LSTORE] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + Constants.instFlags[Constants.FSTORE] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + Constants.instFlags[Constants.DSTORE] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + Constants.instFlags[Constants.ASTORE] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + for (int ii = Constants.ISTORE_0; ii <= Constants.ASTORE_3; ii++) { + Constants.instFlags[ii] = Constants.INDEXED | Constants.STORE_INST | Constants.POP_INST | Constants.LV_INST; + } + + Constants.instFlags[Constants.IDIV] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.IDIV] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION }; + Constants.instFlags[Constants.IREM] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.IREM] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION }; + Constants.instFlags[Constants.LDIV] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.LDIV] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION }; + Constants.instFlags[Constants.LREM] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.LREM] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION }; + + Constants.instFlags[Constants.ARRAYLENGTH] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.ARRAYLENGTH] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION }; + Constants.instFlags[Constants.ATHROW] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.ATHROW] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.THROWABLE }; + + Constants.instFlags[Constants.AALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.AALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.IALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.IALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.BALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.BALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.FALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.FALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.DALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.DALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.CALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.CALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.LALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.LALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.SALOAD] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.SALOAD] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + + Constants.instFlags[Constants.AASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.AASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.IASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.IASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.BASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.BASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.FASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.FASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.DASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.DASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.CASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.CASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.LASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.LASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + Constants.instFlags[Constants.SASTORE] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.SASTORE] = org.aspectj.apache.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + + // stack instructions + Constants.instFlags[Constants.DUP] = Constants.PUSH_INST | Constants.STACK_INST; + Constants.instFlags[Constants.DUP_X1] = Constants.STACK_INST; // TODO fixme - aren't these two push/stack producers? + // (although peculiar ones...) + Constants.instFlags[Constants.DUP_X2] = Constants.STACK_INST; + Constants.instFlags[Constants.DUP2] = Constants.PUSH_INST | Constants.STACK_INST; + Constants.instFlags[Constants.DUP2_X1] = Constants.STACK_INST; // TODO fixme - aren't these two push/stack producers? + // (although peculiar ones...) + Constants.instFlags[Constants.DUP2_X2] = Constants.STACK_INST; + Constants.instFlags[Constants.POP] = Constants.STACK_INST | Constants.POP_INST; + Constants.instFlags[Constants.POP2] = Constants.STACK_INST | Constants.POP_INST; + Constants.instFlags[Constants.SWAP] = Constants.STACK_INST; + + Constants.instFlags[Constants.MONITORENTER] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.MONITORENTER] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION }; + Constants.instFlags[Constants.MONITOREXIT] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.MONITOREXIT] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION }; + + // branching instructions + Constants.instFlags[Constants.GOTO] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION; + Constants.instFlags[Constants.GOTO_W] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION; + Constants.instFlags[Constants.JSR] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.JSR_INSTRUCTION; + Constants.instFlags[Constants.JSR_W] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.JSR_INSTRUCTION; + + Constants.instFlags[Constants.IFGT] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFLE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFNE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFEQ] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFGE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFLT] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFNULL] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION | Constants.NEGATABLE + | Constants.IF_INST; + Constants.instFlags[Constants.IFNONNULL] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ACMPEQ] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ACMPNE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPEQ] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPGE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPGT] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPLE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPLT] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + Constants.instFlags[Constants.IF_ICMPNE] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION + | Constants.NEGATABLE | Constants.IF_INST; + + Constants.instFlags[Constants.LOOKUPSWITCH] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION; + Constants.instFlags[Constants.TABLESWITCH] = Constants.BRANCH_INSTRUCTION | Constants.TARGETER_INSTRUCTION; + + // fixme these class arrays should be constants + Constants.instFlags[Constants.ARETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.ARETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + Constants.instFlags[Constants.DRETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.DRETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + Constants.instFlags[Constants.FRETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.FRETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + Constants.instFlags[Constants.IRETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.IRETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + Constants.instFlags[Constants.LRETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.LRETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + Constants.instFlags[Constants.RETURN] = Constants.RET_INST | Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.RETURN] = new Class[] { ExceptionConstants.ILLEGAL_MONITOR_STATE }; + + Constants.instFlags[Constants.NEW] = Constants.LOADCLASS_INST | Constants.EXCEPTION_THROWER | Constants.CP_INST + | Constants.INDEXED; + Constants.instExcs[Constants.NEW] = ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION_FOR_ALLOCATIONS; + Constants.instFlags[Constants.NEWARRAY] = Constants.EXCEPTION_THROWER; + Constants.instExcs[Constants.NEWARRAY] = new Class[] { org.aspectj.apache.bcel.ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION }; + + Constants.types[Constants.IINC] = Type.INT; + Constants.instFlags[Constants.IINC] = Constants.LV_INST | Constants.INDEXED; + Constants.instFlags[Constants.RET] = Constants.INDEXED; + + Constants.instFlags[Constants.ANEWARRAY] = Constants.CP_INST | Constants.LOADCLASS_INST | Constants.EXCEPTION_THROWER + | Constants.INDEXED; + Constants.instExcs[Constants.ANEWARRAY] = ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION_ANEWARRAY; + Constants.instFlags[Constants.CHECKCAST] = Constants.CP_INST | Constants.LOADCLASS_INST | Constants.EXCEPTION_THROWER + | Constants.INDEXED; + Constants.instExcs[Constants.CHECKCAST] = ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION_CHECKCAST; + Constants.instFlags[Constants.INSTANCEOF] = Constants.CP_INST | Constants.LOADCLASS_INST | Constants.EXCEPTION_THROWER + | Constants.INDEXED; + Constants.instExcs[Constants.INSTANCEOF] = ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION; + Constants.instFlags[Constants.MULTIANEWARRAY] = Constants.CP_INST | Constants.LOADCLASS_INST | Constants.EXCEPTION_THROWER + | Constants.INDEXED; + Constants.instExcs[Constants.MULTIANEWARRAY] = ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION_ANEWARRAY; // fixme i + // think + // this + // is a + // stackproducer, old + // bcel says no... + + Constants.instFlags[Constants.GETFIELD] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + Constants.instExcs[Constants.GETFIELD] = ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION_GETFIELD_PUTFIELD; + Constants.instFlags[Constants.GETSTATIC] = Constants.PUSH_INST | Constants.EXCEPTION_THROWER | Constants.LOADCLASS_INST + | Constants.CP_INST | Constants.INDEXED; + Constants.instExcs[Constants.GETSTATIC] = ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION_GETSTATIC_PUTSTATIC; + Constants.instFlags[Constants.PUTFIELD] = Constants.POP_INST | Constants.EXCEPTION_THROWER | Constants.LOADCLASS_INST + | Constants.CP_INST | Constants.INDEXED; + Constants.instExcs[Constants.PUTFIELD] = ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION_GETFIELD_PUTFIELD; + Constants.instFlags[Constants.PUTSTATIC] = Constants.EXCEPTION_THROWER | Constants.POP_INST | Constants.CP_INST + | Constants.LOADCLASS_INST | Constants.INDEXED; + Constants.instExcs[Constants.PUTSTATIC] = ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION_GETSTATIC_PUTSTATIC; + + Constants.instFlags[Constants.INVOKEINTERFACE] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + Constants.instExcs[Constants.INVOKEINTERFACE] = ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION_INVOKEINTERFACE; + Constants.instFlags[Constants.INVOKESPECIAL] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + Constants.instExcs[Constants.INVOKESPECIAL] = ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESPECIAL_INVOKEVIRTUAL; + Constants.instFlags[Constants.INVOKESTATIC] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + Constants.instExcs[Constants.INVOKESTATIC] = ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESTATIC; + Constants.instFlags[Constants.INVOKEVIRTUAL] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + Constants.instExcs[Constants.INVOKEVIRTUAL] = ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESPECIAL_INVOKEVIRTUAL; + + Constants.instFlags[Constants.INVOKEDYNAMIC] = Constants.EXCEPTION_THROWER | Constants.CP_INST | Constants.LOADCLASS_INST + | Constants.INDEXED; + // TBD + // Constants.instExcs[Constants.INVOKEDYNAMIC] = ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESPECIAL_INVOKEVIRTUAL; + + //@formatter:off + char[] lengths = // . = varies in length, / = undefined + ("1111111111111111" + // nop > dconst_1 + "2323322222111111" + // bipush > lload_1 + "1111111111111111" + // lload_2 > laload + "1111112222211111" + // faload > lstore_0 + "1111111111111111" + // lstore_1 > iastore + "1111111111111111" + // lastore > swap + "1111111111111111" + // iadd > ddiv + "1111111111111111" + // irem > land + "1111311111111111" + // ior > d2l + "1111111113333333" + // d2f > if_icmpeq + "3333333332..1111" + // if_icmpne > dreturn + "1133333335532311" + // areturn > athrow + "3311.433551/////").toCharArray(); // checkcast > + //@formatter:on + int count = 0; + for (; count < lengths.length; count++) { + Constants.iLen[count] = (byte) (lengths[count] - 48); + } + while (count < 256) { + Constants.iLen[count] = Constants.UNDEFINED; + count++; + } + Constants.iLen[Constants.BREAKPOINT] = 1; + Constants.iLen[Constants.IMPDEP1] = 1; + Constants.iLen[Constants.IMPDEP2] = 1; + + char[] producesOnStack = ("0111111112211122" + // nop > dconst_1 + "1111212121111122" + // bipush > lload_1 + "2211112222111112" + // lload_2 > laload + "1211110000000000" + // faload > lstore_0 + "0000000000000000" + // lstore_1 > iastore + "0000000002344562" + // lastore > swap + "1212121212121212" + // iadd > ddiv + "1212121212121212" + // irem > land + "1212021211212212" + // ior > d2l + "1111111110000000" + // d2f > if_icmpeq + "0000000010000000" + // if_icmpne > dreturn + "00.0.0.....11111" + // areturn > athrow + "11000100010/").toCharArray(); // checkcast > + count = 0; + for (; count < producesOnStack.length; count++) { + Constants.stackEntriesProduced[count] = (byte) (producesOnStack[count] - 48); + } + while (count < 256) { + Constants.iLen[count] = Constants.UNDEFINED; + count++; + } + return null; + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/ExceptionConstants.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/ExceptionConstants.java new file mode 100644 index 000000000..cf3d81308 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/ExceptionConstants.java @@ -0,0 +1,150 @@ +package org.aspectj.apache.bcel; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * Exception constants. + * + * @version $Id: ExceptionConstants.java,v 1.5 2009/09/14 20:29:10 aclement Exp $ + * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase">E. Haase</A> + */ +@SuppressWarnings("rawtypes") +public interface ExceptionConstants { + /** + * The mother of all exceptions + */ + public static final Class<Throwable> THROWABLE = Throwable.class; + + /** + * Super class of any run-time exception + */ + public static final Class<RuntimeException> RUNTIME_EXCEPTION = RuntimeException.class; + + /** + * Super class of any linking exception (aka Linkage Error) + */ + public static final Class<LinkageError> LINKING_EXCEPTION = LinkageError.class; + + /** + * Linking Exceptions + */ + public static final Class<ClassCircularityError> CLASS_CIRCULARITY_ERROR = ClassCircularityError.class; + public static final Class<ClassFormatError> CLASS_FORMAT_ERROR = ClassFormatError.class; + public static final Class<ExceptionInInitializerError> EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class; + public static final Class<IncompatibleClassChangeError> INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class; + public static final Class<AbstractMethodError> ABSTRACT_METHOD_ERROR = AbstractMethodError.class; + public static final Class<IllegalAccessError> ILLEGAL_ACCESS_ERROR = IllegalAccessError.class; + public static final Class<InstantiationError> INSTANTIATION_ERROR = InstantiationError.class; + public static final Class<NoSuchFieldError> NO_SUCH_FIELD_ERROR = NoSuchFieldError.class; + public static final Class<NoSuchMethodError> NO_SUCH_METHOD_ERROR = NoSuchMethodError.class; + public static final Class<NoClassDefFoundError> NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class; + public static final Class<UnsatisfiedLinkError> UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class; + public static final Class<VerifyError> 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<NullPointerException> NULL_POINTER_EXCEPTION = NullPointerException.class; + public static final Class<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class; + public static final Class<ArithmeticException> ARITHMETIC_EXCEPTION = ArithmeticException.class; + public static final Class<NegativeArraySizeException> NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class; + public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class; + public static final Class<IllegalMonitorStateException> 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_CLASS_AND_INTERFACE_RESOLUTION_MULTIANEWARRAY = { NO_CLASS_DEF_FOUND_ERROR, + CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR, EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR, + NEGATIVE_ARRAY_SIZE_EXCEPTION, ILLEGAL_ACCESS_ERROR }; + public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION_ANEWARRAY = { NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, + VERIFY_ERROR, ABSTRACT_METHOD_ERROR, EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR, + NEGATIVE_ARRAY_SIZE_EXCEPTION }; // Chapter 5.1 + public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION_CHECKCAST = { NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, + VERIFY_ERROR, ABSTRACT_METHOD_ERROR, EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR, CLASS_CAST_EXCEPTION }; // Chapter + // 5.1 + public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION_FOR_ALLOCATIONS = { NO_CLASS_DEF_FOUND_ERROR, + CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR, EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR, + INSTANTIATION_ERROR, ILLEGAL_ACCESS_ERROR }; + + 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_FIELD_AND_METHOD_RESOLUTION_GETFIELD_PUTFIELD = { NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, + NO_SUCH_METHOD_ERROR, INCOMPATIBLE_CLASS_CHANGE_ERROR, NULL_POINTER_EXCEPTION }; + + public static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION_GETSTATIC_PUTSTATIC = { NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, + NO_SUCH_METHOD_ERROR, INCOMPATIBLE_CLASS_CHANGE_ERROR }; + + public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION_INVOKEINTERFACE = { INCOMPATIBLE_CLASS_CHANGE_ERROR, + ILLEGAL_ACCESS_ERROR, ABSTRACT_METHOD_ERROR, UNSATISFIED_LINK_ERROR }; + public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESPECIAL_INVOKEVIRTUAL = { INCOMPATIBLE_CLASS_CHANGE_ERROR, + NULL_POINTER_EXCEPTION, ABSTRACT_METHOD_ERROR, UNSATISFIED_LINK_ERROR }; +// public static final Class[] EXCS_INVOKEDYNAMIC = { BOOTSTRAP_METHOD_ERROR}; + + public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION_INVOKESTATIC = { INCOMPATIBLE_CLASS_CHANGE_ERROR, + UNSATISFIED_LINK_ERROR }; + + 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 }; + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/Repository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/Repository.java new file mode 100644 index 000000000..073355b5b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/Repository.java @@ -0,0 +1,260 @@ +package org.aspectj.apache.bcel; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.util.ClassPath; +import org.aspectj.apache.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.aspectj.apache.bcel.util.Repository + * @see org.aspectj.apache.bcel.util.SyntheticRepository + * + * @version $Id: Repository.java,v 1.6 2009/09/09 22:18:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class Repository { + private static org.aspectj.apache.bcel.util.Repository _repository = null; + + /** + * @return currently used repository instance + */ + public static org.aspectj.apache.bcel.util.Repository getRepository() { + if (_repository == null) { + _repository = SyntheticRepository.getInstance(); + } + return _repository; + } + + /** + * Set repository instance to be used for class loading + */ + public static void setRepository(org.aspectj.apache.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, or null if the class could not be found or parsed correctly + */ + public static JavaClass lookupClass(String class_name) { + try { + JavaClass clazz = getRepository().findClass(class_name); + + if (clazz != null) { + return clazz; + } + + return getRepository().loadClass(class_name); + } catch (ClassNotFoundException ex) { + return null; + } + } + + // /** + // * Try to find class source via getResourceAsStream(). + // * + // * @see Class + // * @return JavaClass object for given runtime class + // */ + // public static JavaClass lookupClass(Class clazz) { + // try { + // return getRepository().loadClass(clazz); + // } catch (ClassNotFoundException ex) { + // return null; + // } + // } + + /** + * @return class file object for given Java class. + */ + public static ClassPath.ClassFile lookupClassFile(String class_name) { + try { + return ClassPath.getSystemClassPath().getClassFile(class_name); + } catch (IOException e) { + return null; + } + } + + /** + * Clear the repository. + */ + public static void clearCache() { + getRepository().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 = getRepository().findClass(clazz.getClassName()); + getRepository().storeClass(clazz); + return old; + } + + /** + * Remove class with given (fully qualified) name from repository. + */ + public static void removeClass(String clazz) { + getRepository().removeClass(getRepository().findClass(clazz)); + } + + // /** + // * Remove given class from repository. + // */ + // public static void removeClass(JavaClass clazz) { + // getRepository().removeClass(clazz); + // } + + // /** + // * @return list of super classes of clazz in ascending order, i.e., Object is always the last element + // */ + // public static JavaClass[] getSuperClasses(JavaClass clazz) { + // return clazz.getSuperClasses(); + // } + // + // /** + // * @return list of super classes of clazz in ascending order, i.e., Object is always the last element. return "null", if class + // * cannot be found. + // */ + // public static JavaClass[] getSuperClasses(String class_name) { + // JavaClass jc = lookupClass(class_name); + // return jc == null ? null : 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). + // */ + // public static JavaClass[] getInterfaces(JavaClass clazz) { + // return clazz.getAllInterfaces(); + // } + + // /** + // * @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces, and so + // on + // */ + // public static JavaClass[] getInterfaces(String class_name) { + // return getInterfaces(lookupClass(class_name)); + // } + + /** + * Equivalent to runtime "instanceof" operator. + * + * @return true, if clazz is an instance of super_class + */ + public static boolean instanceOf(JavaClass clazz, JavaClass super_class) { + return clazz.instanceOf(super_class); + } + + /** + * @return true, if clazz is an instance of super_class + */ + public static boolean instanceOf(String clazz, String super_class) { + return instanceOf(lookupClass(clazz), lookupClass(super_class)); + } + + // /** + // * @return true, if clazz is an instance of super_class + // */ + // public static boolean instanceOf(JavaClass clazz, String super_class) { + // return instanceOf(clazz, lookupClass(super_class)); + // } + + // /** + // * @return true, if clazz is an instance of super_class + // */ + // public static boolean instanceOf(String clazz, JavaClass super_class) { + // return instanceOf(lookupClass(clazz), super_class); + // } + + /** + * @return true, if clazz is an implementation of interface inter + */ + public static boolean implementationOf(JavaClass clazz, JavaClass inter) { + return clazz.implementationOf(inter); + } + + /** + * @return true, if clazz is an implementation of interface inter + */ + public static boolean implementationOf(String clazz, String inter) { + return implementationOf(lookupClass(clazz), lookupClass(inter)); + } + + // + // /** + // * @return true, if clazz is an implementation of interface inter + // */ + // public static boolean implementationOf(JavaClass clazz, String inter) { + // return implementationOf(clazz, lookupClass(inter)); + // } + + // /** + // * @return true, if clazz is an implementation of interface inter + // */ + // public static boolean implementationOf(String clazz, JavaClass inter) { + // return implementationOf(lookupClass(clazz), inter); + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AnnotationDefault.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AnnotationDefault.java new file mode 100644 index 000000000..bd5a7251f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AnnotationDefault.java @@ -0,0 +1,55 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.ElementValue; + +/** + * This attribute is attached to a method and indicates the default + * value for an annotation element. + */ +public class AnnotationDefault extends Attribute { + + private ElementValue value; + + public AnnotationDefault(int nameIndex, int len, DataInputStream dis, ConstantPool cpool) throws IOException { + this(nameIndex, len, ElementValue.readElementValue(dis,cpool), cpool); + } + + private AnnotationDefault(int nameIndex, int len, ElementValue value, ConstantPool cpool) { + super(Constants.ATTR_ANNOTATION_DEFAULT, nameIndex, len, cpool); + this.value = value; + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + // is this next line sufficient? + // return (EnclosingMethod)clone(); + } + + public final ElementValue getElementValue() { return value; } + + public final void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + value.dump(dos); + } + + public void accept(ClassVisitor v) { + v.visitAnnotationDefault(this); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Attribute.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Attribute.java new file mode 100644 index 000000000..daeb59a38 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Attribute.java @@ -0,0 +1,213 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisTypeAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos; + +/** + * 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: Attribute.java,v 1.9 2009/12/09 18:01:31 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 { + public final static Attribute[] NoAttributes = new Attribute[0]; + + protected byte tag; // Tag to distinguish subclasses + protected int nameIndex; + protected int length; + protected ConstantPool cpool; + + protected Attribute(byte tag, int nameIndex, int length, ConstantPool cpool) { + this.tag = tag; + this.nameIndex = nameIndex; + this.length = length; + this.cpool = cpool; + } + + public void dump(DataOutputStream file) throws IOException { + file.writeShort(nameIndex); + file.writeInt(length); + } + + // OPTIMIZE how about just reading them in and storing them until we need to decode what they really are? + public static final Attribute readAttribute(DataInputStream file, ConstantPool cpool) throws IOException { + byte tag = Constants.ATTR_UNKNOWN; + int idx = file.readUnsignedShort(); + String name = cpool.getConstantUtf8(idx).getValue(); + int len = file.readInt(); + + // Compare strings to find known attribute + for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) { + if (name.equals(Constants.ATTRIBUTE_NAMES[i])) { + tag = i; + break; + } + } + switch (tag) { + case Constants.ATTR_UNKNOWN: + return new Unknown(idx, len, file, cpool); + case Constants.ATTR_CONSTANT_VALUE: + return new ConstantValue(idx, len, file, cpool); + case Constants.ATTR_SOURCE_FILE: + return new SourceFile(idx, len, file, cpool); + case Constants.ATTR_CODE: + return new Code(idx, len, file, cpool); + case Constants.ATTR_EXCEPTIONS: + return new ExceptionTable(idx, len, file, cpool); + case Constants.ATTR_LINE_NUMBER_TABLE: + return new LineNumberTable(idx, len, file, cpool); + case Constants.ATTR_LOCAL_VARIABLE_TABLE: + return new LocalVariableTable(idx, len, file, cpool); + case Constants.ATTR_INNER_CLASSES: + return new InnerClasses(idx, len, file, cpool); + case Constants.ATTR_SYNTHETIC: + return new Synthetic(idx, len, file, cpool); + case Constants.ATTR_DEPRECATED: + return new Deprecated(idx, len, file, cpool); + case Constants.ATTR_SIGNATURE: + return new Signature(idx, len, file, cpool); + case Constants.ATTR_STACK_MAP: + return new StackMap(idx, len, file, cpool); + case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: + return new RuntimeVisAnnos(idx, len, file, cpool); + case Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: + return new RuntimeInvisAnnos(idx, len, file, cpool); + case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeVisParamAnnos(idx, len, file, cpool); + case Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeInvisParamAnnos(idx, len, file, cpool); + case Constants.ATTR_ANNOTATION_DEFAULT: + return new AnnotationDefault(idx, len, file, cpool); + case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE: + return new LocalVariableTypeTable(idx, len, file, cpool); + case Constants.ATTR_ENCLOSING_METHOD: + return new EnclosingMethod(idx, len, file, cpool); + case Constants.ATTR_BOOTSTRAPMETHODS: + return new BootstrapMethods(idx,len,file,cpool); + case Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS: + return new RuntimeVisTypeAnnos(idx, len, file, cpool); + case Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS: + return new RuntimeInvisTypeAnnos(idx, len, file, cpool); + case Constants.ATTR_METHOD_PARAMETERS: + return new MethodParameters(idx, len, file, cpool); + case Constants.ATTR_MODULE: + return new Module(idx, len, file, cpool); + case Constants.ATTR_MODULE_PACKAGES: + return new ModulePackages(idx, len, file, cpool); + case Constants.ATTR_MODULE_MAIN_CLASS: + return new ModuleMainClass(idx, len, file, cpool); + case Constants.ATTR_NEST_HOST: + return new NestHost(idx, len, file, cpool); + case Constants.ATTR_NEST_MEMBERS: + return new NestMembers(idx, len, file, cpool); + default: + throw new IllegalStateException(); + } + } + + public String getName() { + return cpool.getConstantUtf8(nameIndex).getValue(); + } + + public final int getLength() { + return length; + } + + public final int getNameIndex() { + return nameIndex; + } + + public final byte getTag() { + return tag; + } + + public final ConstantPool getConstantPool() { + return cpool; + } + + @Override + public String toString() { + return Constants.ATTRIBUTE_NAMES[tag]; + } + + @Override + public abstract void accept(ClassVisitor v); + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AttributeUtils.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AttributeUtils.java new file mode 100644 index 000000000..45d1597a7 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/AttributeUtils.java @@ -0,0 +1,99 @@ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +public class AttributeUtils { + + public static Attribute[] readAttributes(DataInputStream dataInputstream, ConstantPool cpool) { + try { + int length = dataInputstream.readUnsignedShort(); + if (length == 0) { + return Attribute.NoAttributes; + } + Attribute[] attrs = new Attribute[length]; + for (int i = 0; i < length; i++) { + attrs[i] = Attribute.readAttribute(dataInputstream, cpool); + } + return attrs; + } catch (IOException e) { + throw new ClassFormatException("IOException whilst reading set of attributes: " + e.toString()); + } + } + + /** Write (serialize) a set of attributes into a specified output stream */ + public static void writeAttributes(Attribute[] attributes, DataOutputStream file) throws IOException { + if (attributes == null) { + file.writeShort(0); + } else { + file.writeShort(attributes.length); + for (int i = 0; i < attributes.length; i++) { + attributes[i].dump(file); + } + } + } + + public static Signature getSignatureAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_SIGNATURE) { + return (Signature) attributes[i]; + } + } + return null; + } + + public static Code getCodeAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_CODE) { + return (Code) attributes[i]; + } + } + return null; + } + + public static ExceptionTable getExceptionTableAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_EXCEPTIONS) { + return (ExceptionTable) attributes[i]; + } + } + return null; + } + + public static ConstantValue getConstantValueAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].getTag() == Constants.ATTR_CONSTANT_VALUE) { + return (ConstantValue) attributes[i]; + } + } + return null; + } + + public static void accept(Attribute[] attributes, ClassVisitor visitor) { + for (int i = 0; i < attributes.length; i++) { + attributes[i].accept(visitor); + } + } + + public static boolean hasSyntheticAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_SYNTHETIC) { + return true; + } + } + return false; + } + + public static SourceFile getSourceFileAttribute(Attribute[] attributes) { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_SOURCE_FILE) { + return (SourceFile) attributes[i]; + } + } + return null; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/BootstrapMethods.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/BootstrapMethods.java new file mode 100644 index 000000000..f708c0cab --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/BootstrapMethods.java @@ -0,0 +1,268 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Represents the BootstrapMethods attribute in Java 7 classes. + * + * @author Andy Clement + */ +public final class BootstrapMethods extends Attribute { + + // if 'isInPackedState' then this data needs unpacking + private boolean isInPackedState = false; + private byte[] data; // discarded once unpacked + + private int numBootstrapMethods; + private BootstrapMethod[] bootstrapMethods; + + public BootstrapMethods(BootstrapMethods c) { + this(c.getNameIndex(), c.getLength(), c.getBootstrapMethods(), c.getConstantPool()); + } + + public BootstrapMethods(int nameIndex, int length, BootstrapMethod[] lineNumberTable, ConstantPool constantPool) { + super(Constants.ATTR_BOOTSTRAPMETHODS, nameIndex, length, constantPool); + setBootstrapMethods(lineNumberTable); + isInPackedState = false; + } + + public final void setBootstrapMethods(BootstrapMethod[] bootstrapMethods) { + this.data = null; + this.isInPackedState = false; + this.bootstrapMethods = bootstrapMethods; + this.numBootstrapMethods = bootstrapMethods==null?0:bootstrapMethods.length; + } + + BootstrapMethods(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + this(name_index, length, (BootstrapMethod[])null, constant_pool); + data = new byte[length]; + file.readFully(data); + isInPackedState = true; + } + + public static class BootstrapMethod { + private int bootstrapMethodRef; + private int[] bootstrapArguments; + + BootstrapMethod(DataInputStream file) throws IOException { + this(file.readUnsignedShort(), readBootstrapArguments(file)); + } + + private static int[] readBootstrapArguments(DataInputStream dis) throws IOException { + int numBootstrapMethods = dis.readUnsignedShort(); + int[] bootstrapArguments = new int[numBootstrapMethods]; + for (int i=0;i<numBootstrapMethods;i++) { + bootstrapArguments[i] = dis.readUnsignedShort(); + } + return bootstrapArguments; + } + + public BootstrapMethod(int bootstrapMethodRef, int[] bootstrapArguments) { + this.bootstrapMethodRef = bootstrapMethodRef; + this.bootstrapArguments = bootstrapArguments; + } + + public int getBootstrapMethodRef() { + return bootstrapMethodRef; + } + + public int[] getBootstrapArguments() { + return bootstrapArguments; + } + + public final void dump(DataOutputStream file) throws IOException { + file.writeShort(bootstrapMethodRef); + int len = bootstrapArguments.length; + file.writeShort(len); + for (int i=0;i<len;i++) { + file.writeShort(bootstrapArguments[i]); + } + } + + public final int getLength() { + return 2 /*bootstrapMethodRef*/+ + 2 /*number of arguments*/+ + 2 * bootstrapArguments.length; + } + + } + + // Unpacks the byte array into the table + private void unpack() { + if (isInPackedState) { + try { + ByteArrayInputStream bs = new ByteArrayInputStream(data); + DataInputStream dis = new DataInputStream(bs); + numBootstrapMethods = dis.readUnsignedShort(); + bootstrapMethods = new BootstrapMethod[numBootstrapMethods]; + for (int i = 0; i < numBootstrapMethods; i++) { + bootstrapMethods[i] = new BootstrapMethod(dis); + } + dis.close(); + data = null; // throw it away now + } catch (IOException e) { + throw new RuntimeException("Unpacking of LineNumberTable attribute failed"); + } + isInPackedState = 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 + */ + @Override + public void accept(ClassVisitor v) { + unpack(); + v.visitBootstrapMethods(this); + } + + /** + * Dump line number table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + if (isInPackedState) { + file.write(data); + } else { + int blen = bootstrapMethods.length; + file.writeShort(blen); + for (int i = 0; i < blen; i++) { + bootstrapMethods[i].dump(file); + } + } + } + + public final BootstrapMethod[] getBootstrapMethods() { + unpack(); + return bootstrapMethods; + } + + + /** + * @return String representation. + */ + @Override + public final String toString() { + unpack(); + StringBuffer buf = new StringBuffer(); + StringBuffer line = new StringBuffer(); + + for (int i = 0; i < numBootstrapMethods; i++) { + BootstrapMethod bm = bootstrapMethods[i]; + line.append("BootstrapMethod[").append(i).append("]:"); + int ref = bm.getBootstrapMethodRef(); + ConstantMethodHandle mh = (ConstantMethodHandle)getConstantPool().getConstant(ref); + line.append("#"+ref+":"); + line.append(ConstantMethodHandle.kindToString(mh.getReferenceKind())); + line.append(" ").append(getConstantPool().getConstant(mh.getReferenceIndex())); + int [] args = bm.getBootstrapArguments(); + line.append(" argcount:").append(args==null?0:args.length).append(" "); + if (args!=null) { + for (int a=0;a<args.length;a++) { + line.append(args[a]).append("(").append(getConstantPool().getConstant(args[a])).append(") "); + } + } + + + if (i < numBootstrapMethods - 1) { + line.append(", "); + } + + if (line.length() > 72) { + line.append('\n'); + buf.append(line); + line.setLength(0); + } + } + + buf.append(line); + + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + // @Override + // public Attribute copy(ConstantPool constant_pool) { + // unpack(); + // LineNumberTable newTable = (LineNumberTable) clone(); + // newTable.table = new LineNumber[tableLength]; + // for (int i = 0; i < tableLength; i++) { + // newTable.table[i] = table[i].copy(); + // } + // newTable.cpool = constant_pool; + // return newTable; + // } + public final int getNumBootstrapMethods () { + unpack(); + return bootstrapMethods.length; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassFormatException.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassFormatException.java new file mode 100644 index 000000000..a958329e5 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassFormatException.java @@ -0,0 +1,69 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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: ClassFormatException.java,v 1.3 2008/05/28 23:53:02 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class ClassFormatException extends RuntimeException { + public ClassFormatException() { super(); } + public ClassFormatException(String s) { super(s); } +} + diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassParser.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassParser.java new file mode 100644 index 000000000..54882beee --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassParser.java @@ -0,0 +1,249 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.aspectj.apache.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: ClassParser.java,v 1.6 2008/05/30 17:29:14 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class ClassParser { + private DataInputStream file; + private String filename; + private int classnameIndex; + private int superclassnameIndex; + private int major, minor; + private int accessflags; + private int[] interfaceIndices; + private ConstantPool cpool; + private Field[] fields; + private Method[] methods; + private Attribute[] attributes; + + private static final int BUFSIZE = 8192; + + /** Parse class from the given stream */ + public ClassParser(InputStream file, String filename) { + this.filename = filename; + if (file instanceof DataInputStream) this.file = (DataInputStream)file; + else this.file = new DataInputStream(new BufferedInputStream(file,BUFSIZE)); + } + + public ClassParser(ByteArrayInputStream baos, String filename) { + this.filename = filename; + this.file = new DataInputStream(baos); + } + + /** Parse class from given .class file */ + public ClassParser(String file_name) throws IOException { + this.filename = file_name; + file = new DataInputStream(new BufferedInputStream(new FileInputStream(file_name),BUFSIZE)); + } + + /** + * 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). + */ + public JavaClass parse() throws IOException, ClassFormatException { + /****************** 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(); + + // Read everything of interest, so close the file + file.close(); + + // Return the information we have gathered in a new object + JavaClass jc= new JavaClass(classnameIndex, superclassnameIndex, + filename, major, minor, accessflags, + cpool, interfaceIndices, fields, + methods, attributes); + return jc; + } + + /** Read information about the attributes of the class */ + private final void readAttributes() { + attributes = AttributeUtils.readAttributes(file,cpool); + } + + /** Read information about the class and its super class */ + private final void readClassInfo() throws IOException { + accessflags = file.readUnsignedShort(); + + /* Interfaces are implicitely abstract, the flag should be set + * according to the JVM specification */ + if((accessflags & Constants.ACC_INTERFACE) != 0) + accessflags |= Constants.ACC_ABSTRACT; + + // don't police it like this... leave higher level verification code to check it. +// if(((access_flags & Constants.ACC_ABSTRACT) != 0) && +// ((access_flags & Constants.ACC_FINAL) != 0 )) +// throw new ClassFormatException("Class can't be both final and abstract"); + + classnameIndex = file.readUnsignedShort(); + superclassnameIndex = file.readUnsignedShort(); + } + + private final void readConstantPool() throws IOException { + try { + cpool = new ConstantPool(file); + } catch (ClassFormatException cfe) { + // add some context if we can + cfe.printStackTrace(); + if (filename!=null) { + String newmessage = "File: '"+filename+"': "+cfe.getMessage(); + throw new ClassFormatException(newmessage); // this loses the old stack trace but I dont think that matters! + } + throw cfe; + } + } + + /** Read information about the fields of the class */ + private final void readFields() throws IOException, ClassFormatException { + int fieldCount = file.readUnsignedShort(); + if (fieldCount == 0) { + fields = Field.NoFields; + } else { + fields = new Field[fieldCount]; + for(int i=0; i < fieldCount; i++) + fields[i] = new Field(file, cpool); + } + } + + /** Check whether the header of the file is ok. Of course, this has + * to be the first action on successive file reads */ + private final void readID() throws IOException { + int magic = 0xCAFEBABE; + if (file.readInt() != magic) + throw new ClassFormatException(filename + " is not a Java .class file"); + } + + private static final int[] NO_INTERFACES = new int[0]; + + /** Read information about the interfaces implemented by this class */ + private final void readInterfaces() throws IOException { + int interfacesCount = file.readUnsignedShort(); + if (interfacesCount==0) { + interfaceIndices = NO_INTERFACES; + } else { + interfaceIndices = new int[interfacesCount]; + for(int i=0; i < interfacesCount; i++) + interfaceIndices[i] = file.readUnsignedShort(); + } + } + + /** Read information about the methods of the class */ + private final void readMethods() throws IOException { + int methodsCount = file.readUnsignedShort(); + if (methodsCount==0) { + methods = Method.NoMethods; + } else { + methods = new Method[methodsCount]; + for(int i=0; i < methodsCount; i++) + methods[i] = new Method(file, cpool); + } + } + + /** Read major and minor version of compiler which created the file */ + private final void readVersion() throws IOException { + minor = file.readUnsignedShort(); + major = file.readUnsignedShort(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassVisitor.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassVisitor.java new file mode 100644 index 000000000..5c60f818f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ClassVisitor.java @@ -0,0 +1,180 @@ +package org.aspectj.apache.bcel.classfile; + +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisTypeAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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. + * + * Implemented by wish of <A HREF="http://www.inf.fu-berlin.de/~bokowski">Boris Bokowski</A>. + * + * @version $Id: ClassVisitor.java,v 1.4 2009/09/15 19:40:13 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public interface ClassVisitor { + 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 visitConstantMethodHandle(ConstantMethodHandle obj); + + public void visitConstantNameAndType(ConstantNameAndType obj); + + public void visitConstantMethodType(ConstantMethodType obj); + + public void visitConstantInvokeDynamic(ConstantInvokeDynamic obj); + + public void visitConstantDynamic(ConstantDynamic obj); + + public void visitConstantPool(ConstantPool obj); + + public void visitConstantString(ConstantString obj); + + public void visitConstantModule(ConstantModule obj); + + public void visitConstantPackage(ConstantPackage 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 visitBootstrapMethods(BootstrapMethods obj); + + public void visitUnknown(Unknown obj); + + public void visitStackMap(StackMap obj); + + public void visitStackMapEntry(StackMapEntry obj); + + public void visitEnclosingMethod(EnclosingMethod obj); + + public void visitRuntimeVisibleAnnotations(RuntimeVisAnnos obj); + + public void visitRuntimeInvisibleAnnotations(RuntimeInvisAnnos obj); + + public void visitRuntimeVisibleParameterAnnotations(RuntimeVisParamAnnos obj); + + public void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisParamAnnos obj); + + public void visitRuntimeVisibleTypeAnnotations(RuntimeVisTypeAnnos obj); + + public void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisTypeAnnos obj); + + public void visitAnnotationDefault(AnnotationDefault obj); + + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); + + public void visitMethodParameters(MethodParameters methodParameters); + + // J9: + public void visitModule(Module module); + public void visitModulePackages(ModulePackages modulePackage); + public void visitModuleMainClass(ModuleMainClass moduleMainClass); + + // J11: + public void visitNestHost(NestHost nestHost); + public void visitNestMembers(NestMembers nestMembers); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Code.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Code.java new file mode 100644 index 000000000..b714e6cab --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Code.java @@ -0,0 +1,388 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: Code.java,v 1.9 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Attribute + * @see CodeException + * @see LineNumberTable + * @see LocalVariableTable + */ +public final class Code extends Attribute { + private int maxStack; // Maximum size of stack used by this method + private int maxLocals; // Number of local variables + private byte[] code; // Actual byte code + private CodeException[] exceptionTable; + private Attribute[] attributes; + private static final CodeException[] NO_EXCEPTIONS = new CodeException[] {}; + + /** + * 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()); + } + + 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); + + int len = file.readInt(); + code = new byte[len]; // 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. + */ + len = file.readUnsignedShort(); + if (len == 0) { + exceptionTable = NO_EXCEPTIONS; + } else { + exceptionTable = new CodeException[len]; + for (int i = 0; i < len; i++) { + exceptionTable[i] = new CodeException(file); + } + } + + // Read all attributes, eg: LineNumberTable, LocalVariableTable + attributes = AttributeUtils.readAttributes(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.maxStack = max_stack; + this.maxLocals = 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitCode(this); + } + + /** + * Dump code attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + + file.writeShort(maxStack); + file.writeShort(maxLocals); + file.writeInt(code.length); + file.write(code, 0, code.length); + + file.writeShort(exceptionTable.length); + for (int i = 0; i < exceptionTable.length; i++) { + exceptionTable[i].dump(file); + } + + file.writeShort(attributes.length); + for (int i = 0; i < attributes.length; 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.length; i++) { + if (attributes[i].tag == Constants.ATTR_LINE_NUMBER_TABLE) { + return (LineNumberTable) attributes[i]; + } + } + return null; + } + + /** + * @return LocalVariableTable of Code, if it has one + */ + public LocalVariableTable getLocalVariableTable() { + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].tag == Constants.ATTR_LOCAL_VARIABLE_TABLE) { + 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 exceptionTable; + } + + /** + * @return Number of local variables. + */ + public final int getMaxLocals() { + return maxLocals; + } + + /** + * @return Maximum size of stack used by this method. + */ + + public final int getMaxStack() { + return maxStack; + } + + /** + * @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 == null ? 0 : code.length) /* byte-code */ + + 2 /* exception-table length */ + + 8 * (exceptionTable == null ? 0 : exceptionTable.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; + if (attributes != null) { + for (int i = 0; i < attributes.length; i++) { + len += attributes[i].length + 6 /* attribute header size */; + } + } + return len + getInternalLength(); + } + + /** + * @param attributes. + */ + public final void setAttributes(Attribute[] attributes) { + this.attributes = attributes; + length = calculateLength(); // Adjust length + } + + /** + * @param code byte code + */ + public final void setCode(byte[] code) { + this.code = code; + } + + /** + * @param exception_table exception table + */ + public final void setExceptionTable(CodeException[] exception_table) { + this.exceptionTable = exception_table; + } + + /** + * @param max_locals maximum number of local variables + */ + public final void setMaxLocals(int max_locals) { + this.maxLocals = max_locals; + } + + /** + * @param max_stack maximum stack size + */ + public final void setMaxStack(int max_stack) { + this.maxStack = max_stack; + } + + /** + * @return String representation of code chunk. + */ + public final String toString(boolean verbose) { + StringBuffer buf; + + buf = new StringBuffer("Code(max_stack = " + maxStack + ", max_locals = " + maxLocals + ", code_length = " + code.length + + ")\n" + Utility.codeToString(code, cpool, 0, -1, verbose)); + + if (exceptionTable.length > 0) { + buf.append("\nException handler(s) = \n" + "From\tTo\tHandler\tType\n"); + + for (int i = 0; i < exceptionTable.length; i++) { + buf.append(exceptionTable[i].toString(cpool, verbose) + "\n"); + } + } + + if (attributes.length > 0) { + buf.append("\nAttribute(s) = \n"); + + for (int i = 0; i < attributes.length; i++) { + buf.append(attributes[i].toString() + "\n"); + } + } + + return buf.toString(); + } + + /** + * @return String representation of code chunk. + */ + @Override + public final String toString() { + return toString(true); + } + + // /** + // * @return deep copy of this attribute + // */ + // public Attribute copy(ConstantPool constant_pool) { + // Code c = (Code)clone(); + // c.code = (byte[])code.clone(); + // c.cpool = constant_pool; + // + // c.exceptionTable = new CodeException[exceptionTable.length]; + // for(int i=0; i < exceptionTable.length; i++) + // c.exceptionTable[i] = exceptionTable[i].copy(); + // + // c.attributes = new Attribute[attributes.length]; + // for(int i=0; i < attributes.length; i++) + // c.attributes[i] = attributes[i].copy(constant_pool); + // + // return c; + // } + + /** + * Returns the same as toString(true) except that the attribute information isn't included (line numbers). Can be used to check + * whether two pieces of code are equivalent. + */ + public String getCodeString() { + StringBuffer codeString = new StringBuffer(); + codeString.append("Code(max_stack = ").append(maxStack); + codeString.append(", max_locals = ").append(maxLocals); + codeString.append(", code_length = ").append(code.length).append(")\n"); + codeString.append(Utility.codeToString(code, cpool, 0, -1, true)); + if (exceptionTable.length > 0) { + codeString.append("\n").append("Exception entries = ").append(exceptionTable.length).append("\n"); + for (int i = 0; i < exceptionTable.length; i++) { + CodeException exc = exceptionTable[i]; + int type = exc.getCatchType(); + String name = "finally"; + if (type != 0) { + name = this.cpool.getConstantString(type, Constants.CONSTANT_Class); + } + codeString.append(name).append("["); + codeString.append(exc.getStartPC()).append(">").append(exc.getEndPC()).append("]\n"); + } + } + return codeString.toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/CodeException.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/CodeException.java new file mode 100644 index 000000000..72b4d539e --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/CodeException.java @@ -0,0 +1,196 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.Constants; +import java.io.*; + +/** + * 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: CodeException.java,v 1.3 2008/05/28 23:53:02 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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. + */ + + public CodeException(CodeException c) { + this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); + } + + CodeException(DataInputStream file) throws IOException { + start_pc = file.readUnsignedShort(); + end_pc = file.readUnsignedShort(); + handler_pc = file.readUnsignedShort(); + catch_type = file.readUnsignedShort(); + } + + 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; + } + + public void accept(ClassVisitor v) { + v.visitCodeException(this); + } + + 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. + */ + 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Constant.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Constant.java new file mode 100644 index 000000000..d391b75ea --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Constant.java @@ -0,0 +1,149 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * 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: Constant.java,v 1.5 2009/09/10 15:35:04 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class Constant implements Cloneable, Node { + + protected byte tag; + + Constant(byte tag) { + this.tag = tag; + } + + public final byte getTag() { + return tag; + } + + @Override + public String toString() { + return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; + } + + public abstract void accept(ClassVisitor v); + + public abstract void dump(DataOutputStream dataOutputStream) throws IOException; + + public abstract Object getValue(); + + public Constant copy() { + try { + return (Constant) super.clone(); + } catch (CloneNotSupportedException e) { + } + + return null; + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + static final Constant readConstant(DataInputStream dis) throws IOException, ClassFormatException { + byte b = dis.readByte(); + switch (b) { + case Constants.CONSTANT_Class: + return new ConstantClass(dis); + case Constants.CONSTANT_NameAndType: + return new ConstantNameAndType(dis); + case Constants.CONSTANT_Utf8: + return new ConstantUtf8(dis); + case Constants.CONSTANT_Fieldref: + return new ConstantFieldref(dis); + case Constants.CONSTANT_Methodref: + return new ConstantMethodref(dis); + case Constants.CONSTANT_InterfaceMethodref: + return new ConstantInterfaceMethodref(dis); + case Constants.CONSTANT_String: + return new ConstantString(dis); + case Constants.CONSTANT_Integer: + return new ConstantInteger(dis); + case Constants.CONSTANT_Float: + return new ConstantFloat(dis); + case Constants.CONSTANT_Long: + return new ConstantLong(dis); + case Constants.CONSTANT_Double: + return new ConstantDouble(dis); + case Constants.CONSTANT_MethodHandle: + return new ConstantMethodHandle(dis); + case Constants.CONSTANT_MethodType: + return new ConstantMethodType(dis); + case Constants.CONSTANT_InvokeDynamic: + return new ConstantInvokeDynamic(dis); + case Constants.CONSTANT_Module: + return new ConstantModule(dis); + case Constants.CONSTANT_Package: + return new ConstantPackage(dis); + case Constants.CONSTANT_Dynamic: + return new ConstantDynamic(dis); + default: + throw new ClassFormatException("Invalid byte tag in constant pool: " + b); + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantCP.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantCP.java new file mode 100644 index 000000000..a476c4d15 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantCP.java @@ -0,0 +1,109 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Abstract super class for Fieldref and Methodref constants. + * + * @version $Id: ConstantCP.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see ConstantFieldref + * @see ConstantMethodref + * @see ConstantInterfaceMethodref + */ +public abstract class ConstantCP extends Constant { + + protected int classIndex, nameAndTypeIndex; + + ConstantCP(byte tag, DataInputStream file) throws IOException { + this(tag, file.readUnsignedShort(), file.readUnsignedShort()); + } + + protected ConstantCP(byte tag, int classIndex, int nameAndTypeIndex) { + super(tag); + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(classIndex); + file.writeShort(nameAndTypeIndex); + } + + public final int getClassIndex() { + return classIndex; + } + + public final int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public String getClass(ConstantPool cp) { + return cp.constantToString(classIndex, Constants.CONSTANT_Class); + } + + @Override + public final String toString() { + return super.toString() + "(classIndex = " + classIndex + ", nameAndTypeIndex = " + nameAndTypeIndex + ")"; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantClass.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantClass.java new file mode 100644 index 000000000..883f3b25f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantClass.java @@ -0,0 +1,112 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a (external) class. + * + * @version $Id: ConstantClass.java,v 1.6 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author Andy Clement + */ +public final class ConstantClass extends Constant { + private int nameIndex; + + ConstantClass(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Class); + this.nameIndex = file.readUnsignedShort(); + } + + public ConstantClass(int nameIndex) { + super(Constants.CONSTANT_Class); + this.nameIndex = nameIndex; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantClass(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(nameIndex); + } + + public final int getNameIndex() { + return nameIndex; + } + + @Override + public Integer getValue() { + return nameIndex; + } + + public String getClassname(ConstantPool cpool) { + return cpool.getConstantUtf8(nameIndex).getValue(); + } + + @Override + public final String toString() { + return super.toString() + "(name_index = " + nameIndex + ")"; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDouble.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDouble.java new file mode 100644 index 000000000..813aec72a --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDouble.java @@ -0,0 +1,107 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a Double object. + * + * @version $Id: ConstantDouble.java,v 1.6 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author Andy Clement + */ +public final class ConstantDouble extends Constant implements SimpleConstant { + private double value; + + public ConstantDouble(double value) { + super(Constants.CONSTANT_Double); + this.value = value; + } + + ConstantDouble(DataInputStream file) throws IOException { + this(file.readDouble()); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantDouble(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeDouble(value); + } + + @Override + public final String toString() { + return super.toString() + "(bytes = " + value + ")"; + } + + @Override + public Double getValue() { + return value; + } + + public String getStringValue() { + return Double.toString(value); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDynamic.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDynamic.java new file mode 100644 index 000000000..40100f83b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantDynamic.java @@ -0,0 +1,116 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to the name and signature of a field or method. + * + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.10 + * + * @author Andy Clement + * @see Constant + */ +public final class ConstantDynamic extends Constant { + private final int bootstrapMethodAttrIndex; + private final int nameAndTypeIndex; + + ConstantDynamic(DataInputStream file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort()); + } + + public ConstantDynamic(int readUnsignedShort, int nameAndTypeIndex) { + super(Constants.CONSTANT_InvokeDynamic); + this.bootstrapMethodAttrIndex = readUnsignedShort; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(bootstrapMethodAttrIndex); + file.writeShort(nameAndTypeIndex); + } + + public final int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public final int getBootstrapMethodAttrIndex() { + return bootstrapMethodAttrIndex; + } + + @Override + public final String toString() { + return super.toString() + "(bootstrapMethodAttrIndex=" + bootstrapMethodAttrIndex + ",nameAndTypeIndex=" + nameAndTypeIndex + ")"; + } + + @Override + public String getValue() { + return toString(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantDynamic(this); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFieldref.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFieldref.java new file mode 100644 index 000000000..056f3e3fd --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFieldref.java @@ -0,0 +1,87 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class represents a constant pool reference to a field. + * + * @version $Id: ConstantFieldref.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class ConstantFieldref extends ConstantCP { + + ConstantFieldref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Fieldref, file); + } + + public ConstantFieldref(int class_index, int name_and_type_index) { + super(Constants.CONSTANT_Fieldref, class_index, name_and_type_index); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantFieldref(this); + } + + @Override + public String getValue() { + return toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFloat.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFloat.java new file mode 100644 index 000000000..985c28125 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantFloat.java @@ -0,0 +1,108 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a float object. + * + * @version $Id: ConstantFloat.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public final class ConstantFloat extends Constant implements SimpleConstant { + private float floatValue; + + public ConstantFloat(float floatValue) { + super(Constants.CONSTANT_Float); + this.floatValue = floatValue; + } + + ConstantFloat(DataInputStream file) throws IOException { + this(file.readFloat()); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantFloat(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeFloat(floatValue); + } + + @Override + public final Float getValue() { + return floatValue; + } + + public final String getStringValue() { + return Float.toString(floatValue); + } + + @Override + public final String toString() { + return super.toString() + "(bytes = " + floatValue + ")"; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInteger.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInteger.java new file mode 100644 index 000000000..415706eed --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInteger.java @@ -0,0 +1,111 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to an int object. + * + * @version $Id: ConstantInteger.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public final class ConstantInteger extends Constant implements SimpleConstant { + private int intValue; + + public ConstantInteger(int intValue) { + super(Constants.CONSTANT_Integer); + this.intValue = intValue; + } + + ConstantInteger(DataInputStream file) throws IOException { + this(file.readInt()); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantInteger(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeInt(intValue); + } + + @Override + public final String toString() { + return super.toString() + "(bytes = " + intValue + ")"; + } + + @Override + public Integer getValue() { + return intValue; + } + + public int getIntValue() { + return intValue; + } + + public String getStringValue() { + return Integer.toString(intValue); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInterfaceMethodref.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInterfaceMethodref.java new file mode 100644 index 000000000..b973c726e --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInterfaceMethodref.java @@ -0,0 +1,88 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class represents a constant pool reference to an interface method. + * + * @version $Id: ConstantInterfaceMethodref.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class ConstantInterfaceMethodref extends ConstantCP { + + ConstantInterfaceMethodref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_InterfaceMethodref, file); + } + + public ConstantInterfaceMethodref(int classIndex, int nameAndTypeIndex) { + super(Constants.CONSTANT_InterfaceMethodref, classIndex, nameAndTypeIndex); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantInterfaceMethodref(this); + } + + @Override + public String getValue() { + return toString(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInvokeDynamic.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInvokeDynamic.java new file mode 100644 index 000000000..0d263aa65 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantInvokeDynamic.java @@ -0,0 +1,132 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to the name and signature of a field or method. + * + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.10 + * + * @author Andy Clement + * @see Constant + */ +public final class ConstantInvokeDynamic extends Constant { + private final int bootstrapMethodAttrIndex; + private final int nameAndTypeIndex; + + ConstantInvokeDynamic(DataInputStream file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort()); + } + + public ConstantInvokeDynamic(int readUnsignedShort, int nameAndTypeIndex) { + super(Constants.CONSTANT_InvokeDynamic); + this.bootstrapMethodAttrIndex = readUnsignedShort; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(bootstrapMethodAttrIndex); + file.writeShort(nameAndTypeIndex); + } +// +// public final byte getReferenceKind() { +// return bootstrapMethodAttrIndex; +// } +// +// public final String getName(ConstantPool cp) { +// return cp.constantToString(getNameIndex(), Constants.CONSTANT_Utf8); +// } +// +// public final int getSignatureIndex() { +// return referenceIndex; +// } +// +// public final String getSignature(ConstantPool cp) { +// return cp.constantToString(getSignatureIndex(), Constants.CONSTANT_Utf8); +// } + + public final int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public final int getBootstrapMethodAttrIndex() { + return bootstrapMethodAttrIndex; + } + + @Override + public final String toString() { + return super.toString() + "(bootstrapMethodAttrIndex=" + bootstrapMethodAttrIndex + ",nameAndTypeIndex=" + nameAndTypeIndex + ")"; + } + + @Override + public String getValue() { + return toString(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantInvokeDynamic(this); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantLong.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantLong.java new file mode 100644 index 000000000..1d56b98a3 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantLong.java @@ -0,0 +1,108 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a long object. + * + * @version $Id: ConstantLong.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public final class ConstantLong extends Constant implements SimpleConstant { + private long longValue; + + public ConstantLong(long longValue) { + super(Constants.CONSTANT_Long); + this.longValue = longValue; + } + + ConstantLong(DataInputStream file) throws IOException { + this(file.readLong()); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantLong(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeLong(longValue); + } + + @Override + public final Long getValue() { + return longValue; + } + + public final String getStringValue() { + return Long.toString(longValue); + } + + @Override + public final String toString() { + return super.toString() + "(longValue = " + longValue + ")"; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodHandle.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodHandle.java new file mode 100644 index 000000000..712a13f4c --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodHandle.java @@ -0,0 +1,132 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to the name and signature of a field or method. + * + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8 + * + * @author Andy Clement + * @see Constant + */ +public final class ConstantMethodHandle extends Constant { + private byte referenceKind; + private int referenceIndex; + + ConstantMethodHandle(DataInputStream file) throws IOException { + this(file.readByte(), file.readUnsignedShort()); + } + + public ConstantMethodHandle(byte referenceKind, int referenceIndex) { + super(Constants.CONSTANT_MethodHandle); + this.referenceKind = referenceKind; + this.referenceIndex = referenceIndex; + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeByte(referenceKind); + file.writeShort(referenceIndex); + } + + public final byte getReferenceKind() { + return referenceKind; + } + + public final int getReferenceIndex() { + return referenceIndex; + } + + @Override + public final String toString() { + return super.toString() + "(referenceKind=" + referenceKind + ",referenceIndex=" + referenceIndex + ")"; + } + + @Override + public String getValue() { + return toString(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantMethodHandle(this); + } + + public static String kindToString(byte kind) { + switch (kind) { + case 1: return "getfield"; + case 2: return "getstatic"; + case 3: return "putfield"; + case 4: return "putstatic"; + case 5: return "invokevirtual"; + case 6: return "invokestatic"; + case 7: return "invokespecial"; + case 8: return "newinvokespecial"; + case 9: return "invokeinterface"; + default: + return "nyi"; + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodType.java new file mode 100644 index 000000000..867e7eb0a --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodType.java @@ -0,0 +1,121 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to the name and signature of a field or method. + * + * http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.9 + * + * @author Andy Clement + * @see Constant + */ +public final class ConstantMethodType extends Constant { + private int descriptorIndex; + + ConstantMethodType(DataInputStream file) throws IOException { + this(file.readUnsignedShort()); + } + + public ConstantMethodType(int descriptorIndex) { + super(Constants.CONSTANT_MethodType); + this.descriptorIndex = descriptorIndex; + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(descriptorIndex); + } + + public final int getDescriptorIndex() { + return descriptorIndex; + } + +// public final String getName(ConstantPool cp) { +// return cp.constantToString(getNameIndex(), Constants.CONSTANT_Utf8); +// } +// +// public final int getSignatureIndex() { +// return referenceIndex; +// } +// +// public final String getSignature(ConstantPool cp) { +// return cp.constantToString(getSignatureIndex(), Constants.CONSTANT_Utf8); +// } + + @Override + public final String toString() { + return super.toString() + "(descriptorIndex=" + descriptorIndex + ")"; + } + + @Override + public String getValue() { + return toString(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantMethodType(this); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodref.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodref.java new file mode 100644 index 000000000..29b37c5d7 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantMethodref.java @@ -0,0 +1,87 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class represents a constant pool reference to a method. + * + * @version $Id: ConstantMethodref.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class ConstantMethodref extends ConstantCP { + + ConstantMethodref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Methodref, file); + } + + public ConstantMethodref(int class_index, int name_and_type_index) { + super(Constants.CONSTANT_Methodref, class_index, name_and_type_index); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantMethodref(this); + } + + @Override + public String getValue() { + return toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantModule.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantModule.java new file mode 100644 index 000000000..efe4d3a1b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantModule.java @@ -0,0 +1,111 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2017 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Represents a module. + * + * See http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.4.11 + * + * @author Andy Clement + */ +public final class ConstantModule extends Constant { + + private int nameIndex; + + ConstantModule(DataInputStream file) throws IOException { + this(file.readUnsignedShort()); + } + + public ConstantModule(int nameIndex) { + super(Constants.CONSTANT_Module); + this.nameIndex = nameIndex; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantModule(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(nameIndex); + } + + @Override + public Integer getValue() { + return nameIndex; + } + + public final int getNameIndex() { + return nameIndex; + } + + @Override + public final String toString() { + return super.toString() + "(name_index = " + nameIndex + ")"; + } + + public String getModuleName(ConstantPool cpool) { + Constant c = cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getValue(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantNameAndType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantNameAndType.java new file mode 100644 index 000000000..8af80fab2 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantNameAndType.java @@ -0,0 +1,157 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to the name and signature of a field or method. + * + * @version $Id: ConstantNameAndType.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantNameAndType(DataInputStream 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitConstantNameAndType(this); + } + + /** + * Dump name and signature index to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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); + } + + @Override + public final String toString() { + return super.toString() + "(name_index = " + name_index + ", signature_index = " + signature_index + ")"; + } + + @Override + public String getValue() { + return toString(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantObject.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantObject.java new file mode 100644 index 000000000..70e9b1d0d --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantObject.java @@ -0,0 +1,66 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * This interface denotes those constants that have a "natural" value, such as ConstantLong, ConstantString, etc.. + * + * @version $Id: ConstantObject.java,v 1.4 2009/09/10 03:59:33 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public interface ConstantObject { + public abstract Object getConstantValue(ConstantPool cp); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPackage.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPackage.java new file mode 100644 index 000000000..70f22c749 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPackage.java @@ -0,0 +1,111 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2017 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Represents a module. + * + * See http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.4.12 + * + * @author Andy Clement + */ +public final class ConstantPackage extends Constant { + + private int nameIndex; + + ConstantPackage(DataInputStream file) throws IOException { + this(file.readUnsignedShort()); + } + + public ConstantPackage(int nameIndex) { + super(Constants.CONSTANT_Package); + this.nameIndex = nameIndex; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantPackage(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(nameIndex); + } + + @Override + public Integer getValue() { + return nameIndex; + } + + public final int getNameIndex() { + return nameIndex; + } + + @Override + public final String toString() { + return super.toString() + "(name_index = " + nameIndex + ")"; + } + + public String getPackageName(ConstantPool cpool) { + Constant c = cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getValue(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPool.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPool.java new file mode 100644 index 000000000..0430e28ba --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantPool.java @@ -0,0 +1,816 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.generic.ArrayType; +import org.aspectj.apache.bcel.generic.ObjectType; + +/** + * 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. + */ +public class ConstantPool implements Node { + private Constant[] pool; + private int poolSize; // number of entries in the pool (could be < pool.length as the array is resized in 'chunks') + + private Map<String, Integer> utf8Cache = new HashMap<String, Integer>(); + private Map<String, Integer> methodCache = new HashMap<String, Integer>(); + private Map<String, Integer> fieldCache = new HashMap<String, Integer>(); + + public int getSize() { + return poolSize; + } + + public ConstantPool() { + pool = new Constant[10]; + poolSize = 0; + } + + public ConstantPool(Constant[] constants) { + pool = constants; + poolSize = (constants == null ? 0 : constants.length); + } + + ConstantPool(DataInputStream file) throws IOException { + byte tag; + poolSize = file.readUnsignedShort(); + pool = new Constant[poolSize]; + // pool[0] is unused by the compiler and may be used freely by the implementation + for (int i = 1; i < poolSize; i++) { + pool[i] = Constant.readConstant(file); + tag = pool[i].getTag(); + if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) { + i++; + } + } + } + + public Constant getConstant(int index, byte tag) { + Constant c = getConstant(index); + // if (c == null) throw new ClassFormatException("Constant pool at index " + index + " is null."); + if (c.tag == tag) + return c; + throw new ClassFormatException("Expected class '" + Constants.CONSTANT_NAMES[tag] + "' at index " + index + " and found " + + c); + } + + public Constant getConstant(int index) { + try { + return pool[index]; + } catch (ArrayIndexOutOfBoundsException aioobe) { + throw new ClassFormatException("Index " + index + " into constant pool (size:" + poolSize + ") is invalid"); + } + } + + /** + * @return deep copy of this constant pool + */ + public ConstantPool copy() { + Constant[] newConstants = new Constant[poolSize]; // use the correct size + for (int i = 1; i < poolSize; i++) { + if (pool[i] != null) { + newConstants[i] = pool[i].copy(); + } + } + return new ConstantPool(newConstants); + } + + /** + * 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 = getConstant(index, tag); + int i; + /* + * 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. + */ + // OPTIMIZE remove the difference - use the an interface and same index methods for string ref id + 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).getValue(); + } + + /** + * Resolve constant to a string representation. + */ + public String constantToString(Constant c) { + String str; + int i; + + switch (c.tag) { + case Constants.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = Utility.compactClassName(((ConstantUtf8) c).getValue(), false); + break; + + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = "\"" + escape(((ConstantUtf8) c).getValue()) + "\""; + break; + + case Constants.CONSTANT_Utf8: + case Constants.CONSTANT_Double: + case Constants.CONSTANT_Float: + case Constants.CONSTANT_Long: + case Constants.CONSTANT_Integer: + str = ((SimpleConstant) c).getStringValue(); + 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; + + case Constants.CONSTANT_InvokeDynamic: + ConstantInvokeDynamic cID = ((ConstantInvokeDynamic)c); + return "#"+cID.getBootstrapMethodAttrIndex()+"."+constantToString(cID.getNameAndTypeIndex(), Constants.CONSTANT_NameAndType); + + case Constants.CONSTANT_MethodHandle: + ConstantMethodHandle cMH = ((ConstantMethodHandle)c); + return cMH.getReferenceKind()+":"+constantToString(cMH.getReferenceIndex(),Constants.CONSTANT_Methodref); + + case Constants.CONSTANT_MethodType: + ConstantMethodType cMT = (ConstantMethodType)c; + return constantToString(cMT.getDescriptorIndex(),Constants.CONSTANT_Utf8); + + case Constants.CONSTANT_Module: + ConstantModule cM = (ConstantModule)c; + return "Module:"+constantToString(cM.getNameIndex(),Constants.CONSTANT_Utf8); + + case Constants.CONSTANT_Package: + ConstantPackage cP = (ConstantPackage)c; + return "Package:"+constantToString(cP.getNameIndex(),Constants.CONSTANT_Utf8); + + default: // Never reached + throw new RuntimeException("Unknown constant type " + c.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(); + } + + public String constantToString(int index, byte tag) { + Constant c = getConstant(index, tag); + return constantToString(c); + } + + public String constantToString(int index) { + return constantToString(getConstant(index)); + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantPool(this); + } + + public Constant[] getConstantPool() { + return pool; + } // TEMPORARY, DONT LIKE PASSING THIS DATA OUT! + + public void dump(DataOutputStream file) throws IOException { + file.writeShort(poolSize); + for (int i = 1; i < poolSize; i++) + if (pool[i] != null) + pool[i].dump(file); + } + + public ConstantUtf8 getConstantUtf8(int index) { + Constant c = getConstant(index); + assert c != null; + assert c.tag == Constants.CONSTANT_Utf8; + return (ConstantUtf8) c; + } + + public ConstantModule getConstantModule(int index) { + Constant c = getConstant(index); + assert c != null; + assert c.tag == Constants.CONSTANT_Module; + return (ConstantModule)c; + } + + public ConstantPackage getConstantPackage(int index) { + Constant c = getConstant(index); + assert c != null; + assert c.tag == Constants.CONSTANT_Package; + return (ConstantPackage)c; + } + + public String getConstantString_CONSTANTClass(int index) { + ConstantClass c = (ConstantClass) getConstant(index, Constants.CONSTANT_Class); + index = c.getNameIndex(); + return ((ConstantUtf8) getConstant(index, Constants.CONSTANT_Utf8)).getValue(); + } + + public int getLength() { + return poolSize; + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + + for (int i = 1; i < poolSize; i++) + buf.append(i + ")" + pool[i] + "\n"); + + return buf.toString(); + } + + public int lookupInteger(int n) { + for (int i = 1; i < poolSize; i++) { + if (pool[i] instanceof ConstantInteger) { + ConstantInteger c = (ConstantInteger) pool[i]; + if (c.getValue() == n) + return i; + } + } + return -1; + } + + public int lookupUtf8(String string) { + Integer pos = utf8Cache.get(string); + if (pos != null) { + return pos; + } + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Utf8) { + if (((ConstantUtf8) c).getValue().equals(string)) { + utf8Cache.put(string, i); + return i; + } + } + } + return -1; + } + + public int lookupClass(String classname) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Class) { + int cIndex = ((ConstantClass) c).getNameIndex(); + String cName = ((ConstantUtf8) pool[cIndex]).getValue(); + if (cName.equals(classname)) + return i; + } + } + return -1; + } + + public int addUtf8(String n) { + int ret = lookupUtf8(n); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize++] = new ConstantUtf8(n); + return ret; + } + + public int addInteger(int n) { + int ret = lookupInteger(n); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize++] = new ConstantInteger(n); + return ret; + } + + public int addArrayClass(ArrayType type) { + return addClass(type.getSignature()); + } + + public int addClass(ObjectType type) { + return addClass(type.getClassName()); + } + + public int addClass(String classname) { + String toAdd = classname.replace('.', '/'); + int ret = lookupClass(toAdd); + if (ret != -1) + return ret; + adjustSize(); + ConstantClass c = new ConstantClass(addUtf8(toAdd)); + ret = poolSize; + pool[poolSize++] = c; + return ret; + } + + private void adjustSize() { + if (poolSize + 3 >= pool.length) { + Constant[] cs = pool; + pool = new Constant[cs.length + 8]; + System.arraycopy(cs, 0, pool, 0, cs.length); + } + if (poolSize == 0) + poolSize = 1; // someone about to do something in here! + } + + public int addFieldref(String class_name, String field_name, String signature) { + int ret = lookupFieldref(class_name, field_name, signature); + int class_index, name_and_type_index; + + if (ret != -1) + return ret; + + adjustSize(); + + class_index = addClass(class_name); + name_and_type_index = addNameAndType(field_name, signature); + ret = poolSize; + pool[poolSize++] = new ConstantFieldref(class_index, name_and_type_index); + + return ret; + } + + public int lookupFieldref(String searchClassname, String searchFieldname, String searchSignature) { + searchClassname = searchClassname.replace('.', '/'); + String k = new StringBuffer().append(searchClassname).append(searchFieldname).append(searchSignature).toString(); + Integer pos = fieldCache.get(k); + if (pos != null) + return pos.intValue(); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Fieldref) { + ConstantFieldref cfr = (ConstantFieldref) c; + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + + // check the class + int cIndex = cfr.getClassIndex(); + ConstantClass cc = (ConstantClass) pool[cIndex]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue(); + if (!name.equals(searchFieldname)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue(); + if (!typeSignature.equals(searchSignature)) + continue; + fieldCache.put(k, new Integer(i)); + return i; + } + } + return -1; + } + + public int addNameAndType(String name, String signature) { + int ret = lookupNameAndType(name, signature); + if (ret != -1) + return ret; + adjustSize(); + int name_index = addUtf8(name); + int signature_index = addUtf8(signature); + ret = poolSize; + pool[poolSize++] = new ConstantNameAndType(name_index, signature_index); + return ret; + } + + public int lookupNameAndType(String searchName, String searchTypeSignature) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_NameAndType) { + ConstantNameAndType cnat = (ConstantNameAndType) c; + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue(); + if (!name.equals(searchName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue(); + if (!typeSignature.equals(searchTypeSignature)) + continue; + return i; + } + } + return -1; + } + + public int addFloat(float f) { + int ret = lookupFloat(f); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize++] = new ConstantFloat(f); + return ret; + } + + public int lookupFloat(float f) { + int bits = Float.floatToIntBits(f); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Float) { + ConstantFloat cf = (ConstantFloat) c; + if (Float.floatToIntBits(cf.getValue()) == bits) + return i; + } + } + return -1; + } + + public int addDouble(double d) { + int ret = lookupDouble(d); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize] = new ConstantDouble(d); + poolSize += 2; + return ret; + } + + public int lookupDouble(double d) { + long bits = Double.doubleToLongBits(d); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Double) { + ConstantDouble cf = (ConstantDouble) c; + if (Double.doubleToLongBits(cf.getValue()) == bits) + return i; + } + } + return -1; + } + + public int addLong(long l) { + int ret = lookupLong(l); + if (ret != -1) + return ret; + adjustSize(); + ret = poolSize; + pool[poolSize] = new ConstantLong(l); + poolSize += 2; + return ret; + } + + public int lookupString(String s) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_String) { + ConstantString cs = (ConstantString) c; + ConstantUtf8 cu8 = (ConstantUtf8) pool[cs.getStringIndex()]; + if (cu8.getValue().equals(s)) + return i; + } + } + return -1; + } + + public int addString(String str) { + int ret = lookupString(str); + if (ret != -1) + return ret; + int utf8 = addUtf8(str); + adjustSize(); + ConstantString s = new ConstantString(utf8); + ret = poolSize; + pool[poolSize++] = s; + return ret; + } + + public int lookupLong(long l) { + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Long) { + ConstantLong cf = (ConstantLong) c; + if (cf.getValue() == l) + return i; + } + } + return -1; + } + + public int addConstant(Constant c, ConstantPool cp) { + Constant[] constants = cp.getConstantPool(); + switch (c.getTag()) { + + case Constants.CONSTANT_String: { + ConstantString s = (ConstantString) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; + + return addString(u8.getValue()); + } + + case Constants.CONSTANT_Class: { + ConstantClass s = (ConstantClass) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; + + return addClass(u8.getValue()); + } + + case Constants.CONSTANT_NameAndType: { + ConstantNameAndType n = (ConstantNameAndType) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; + ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; + + return addNameAndType(u8.getValue(), u8_2.getValue()); + } + + case Constants.CONSTANT_InvokeDynamic: { + ConstantInvokeDynamic cid = (ConstantInvokeDynamic)c; + int index1 = cid.getBootstrapMethodAttrIndex(); + ConstantNameAndType cnat = (ConstantNameAndType)constants[cid.getNameAndTypeIndex()]; + ConstantUtf8 name = (ConstantUtf8) constants[cnat.getNameIndex()]; + ConstantUtf8 signature = (ConstantUtf8) constants[cnat.getSignatureIndex()]; + int index2 = addNameAndType(name.getValue(), signature.getValue()); + return addInvokeDynamic(index1,index2); + } + + case Constants.CONSTANT_MethodHandle: + ConstantMethodHandle cmh = (ConstantMethodHandle)c; + return addMethodHandle(cmh.getReferenceKind(),addConstant(constants[cmh.getReferenceIndex()],cp)); + + case Constants.CONSTANT_Utf8: + return addUtf8(((ConstantUtf8) c).getValue()); + + case Constants.CONSTANT_Double: + return addDouble(((ConstantDouble) c).getValue()); + + case Constants.CONSTANT_Float: + return addFloat(((ConstantFloat) c).getValue()); + + case Constants.CONSTANT_Long: + return addLong(((ConstantLong) c).getValue()); + + case Constants.CONSTANT_Integer: + return addInteger(((ConstantInteger) c).getValue()); + + case Constants.CONSTANT_MethodType: + ConstantMethodType cmt = (ConstantMethodType)c; + return addMethodType(addConstant(constants[cmt.getDescriptorIndex()],cp)); + + 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.getValue().replace('/', '.'); + + u8 = (ConstantUtf8) constants[n.getNameIndex()]; + String name = u8.getValue(); + + u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; + String signature = u8.getValue(); + + switch (c.getTag()) { + case Constants.CONSTANT_InterfaceMethodref: + return addInterfaceMethodref(class_name, name, signature); + + case Constants.CONSTANT_Methodref: + return addMethodref(class_name, name, signature); // OPTIMIZE indicate it should be cached! + + 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); + } + } + + public int addMethodHandle(byte referenceKind, int referenceIndex) { + adjustSize(); + int ret = poolSize; + pool[poolSize++] = new ConstantMethodHandle(referenceKind, referenceIndex); + return ret; + } + + public int addMethodType(int descriptorIndex) { + adjustSize(); + int ret = poolSize; + pool[poolSize++] = new ConstantMethodType(descriptorIndex); + return ret; + } + + // OPTIMIZE should put it in the cache now + 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 = poolSize; + pool[poolSize++] = new ConstantMethodref(class_index, name_and_type_index); + return ret; + } + + public int addInvokeDynamic(int bootstrapMethodIndex, int constantNameAndTypeIndex) { + adjustSize(); + int ret = poolSize; + pool[poolSize++] = new ConstantInvokeDynamic(bootstrapMethodIndex, constantNameAndTypeIndex); + return ret; + } + + public int addInterfaceMethodref(String class_name, String method_name, String signature) { + int ret = lookupInterfaceMethodref(class_name, method_name, signature); + int class_index, name_and_type_index; + + if (ret != -1) + return ret; + adjustSize(); + + class_index = addClass(class_name); + name_and_type_index = addNameAndType(method_name, signature); + ret = poolSize; + pool[poolSize++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); + return ret; + } + + public int lookupInterfaceMethodref(String searchClassname, String searchMethodName, String searchSignature) { + searchClassname = searchClassname.replace('.', '/'); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_InterfaceMethodref) { + ConstantInterfaceMethodref cfr = (ConstantInterfaceMethodref) c; + + ConstantClass cc = (ConstantClass) pool[cfr.getClassIndex()]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue(); + if (!name.equals(searchMethodName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue(); + if (!typeSignature.equals(searchSignature)) + continue; + return i; + } + } + return -1; + } + + public int lookupMethodref(String searchClassname, String searchMethodName, String searchSignature) { + String key = new StringBuffer().append(searchClassname).append(searchMethodName).append(searchSignature).toString(); + Integer cached = methodCache.get(key); + if (cached != null) + return cached.intValue(); + searchClassname = searchClassname.replace('.', '/'); + for (int i = 1; i < poolSize; i++) { + Constant c = pool[i]; + if (c != null && c.tag == Constants.CONSTANT_Methodref) { + ConstantMethodref cfr = (ConstantMethodref) c; + ConstantNameAndType cnat = (ConstantNameAndType) pool[cfr.getNameAndTypeIndex()]; + + // check the class + int cIndex = cfr.getClassIndex(); + ConstantClass cc = (ConstantClass) pool[cIndex]; + String cName = ((ConstantUtf8) pool[cc.getNameIndex()]).getValue(); + if (!cName.equals(searchClassname)) + continue; + + // check the name and type + String name = ((ConstantUtf8) pool[cnat.getNameIndex()]).getValue(); + if (!name.equals(searchMethodName)) + continue; // not this one + String typeSignature = ((ConstantUtf8) pool[cnat.getSignatureIndex()]).getValue(); + if (!typeSignature.equals(searchSignature)) + continue; + methodCache.put(key, new Integer(i)); + return i; + } + } + return -1; + } + + public ConstantPool getFinalConstantPool() { + Constant[] cs = new Constant[poolSize]; // create it the exact size we need + System.arraycopy(pool, 0, cs, 0, poolSize); + return new ConstantPool(cs); + } + + public String getModuleName(int moduleIndex) { + return getConstantModule(moduleIndex).getModuleName(this); + } + + public String getPackageName(int packageIndex) { + return getConstantPackage(packageIndex).getPackageName(this); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantString.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantString.java new file mode 100644 index 000000000..ef9da55db --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantString.java @@ -0,0 +1,120 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a String object. + * + * @version $Id: ConstantString.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public final class ConstantString extends Constant { + + private int stringIndex; + + ConstantString(DataInputStream file) throws IOException { + this(file.readUnsignedShort()); + } + + public ConstantString(int stringIndex) { + super(Constants.CONSTANT_String); + this.stringIndex = stringIndex; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantString(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeShort(stringIndex); + } + + // OPTIMIZE fix duplication in these next two methods + /** + * @return the index of the string in the constant pool + */ + @Override + public Integer getValue() { + return stringIndex; + } + + public final int getStringIndex() { + return stringIndex; + } + + @Override + public final String toString() { + return super.toString() + "(string_index = " + stringIndex + ")"; + } + + /** + * @return the string, as dereferenced using the internal index into the supplied constant pool + */ + public String getString(ConstantPool cpool) { + Constant c = cpool.getConstant(stringIndex, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getValue(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantUtf8.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantUtf8.java new file mode 100644 index 000000000..f8200db47 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantUtf8.java @@ -0,0 +1,109 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from the abstract <A HREF="org.aspectj.apache.bcel.classfile.Constant.html">Constant</A> class and + * represents a reference to a Utf8 encoded string. + * + * @version $Id: ConstantUtf8.java,v 1.5 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constant + */ +public final class ConstantUtf8 extends Constant implements SimpleConstant { + private String string; + + ConstantUtf8(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Utf8); + string = file.readUTF(); + } + + public ConstantUtf8(String string) { + super(Constants.CONSTANT_Utf8); + assert string != null; + this.string = string; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantUtf8(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + file.writeByte(tag); + file.writeUTF(string); + } + + @Override + public final String toString() { + return super.toString() + "(\"" + Utility.replace(string, "\n", "\\n") + "\")"; + } + + @Override + public String getValue() { + return string; + } + + public String getStringValue() { + return string; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantValue.java new file mode 100644 index 000000000..730e8aff0 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ConstantValue.java @@ -0,0 +1,131 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: ConstantValue.java,v 1.6 2009/09/16 00:43:49 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Attribute + */ +public final class ConstantValue extends Attribute { + private int constantvalue_index; + + ConstantValue(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + this(name_index, length, file.readUnsignedShort(), constant_pool); + } + + 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; + } + + @Override + public void accept(ClassVisitor v) { + v.visitConstantValue(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(constantvalue_index); + } + + public final int getConstantValueIndex() { + return constantvalue_index; + } + + @Override + public final String toString() { + Constant c = cpool.getConstant(constantvalue_index); + + String buf; + int i; + + // Print constant to string depending on its type + switch (c.getTag()) { + case Constants.CONSTANT_Long: + buf = "" + ((ConstantLong) c).getValue(); + break; + case Constants.CONSTANT_Float: + buf = "" + ((ConstantFloat) c).getValue(); + break; + case Constants.CONSTANT_Double: + buf = "" + ((ConstantDouble) c).getValue(); + break; + case Constants.CONSTANT_Integer: + buf = "" + ((ConstantInteger) c).getValue(); + break; + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = cpool.getConstant(i, Constants.CONSTANT_Utf8); + buf = "\"" + Utility.convertString(((ConstantUtf8) c).getValue()) + "\""; + break; + + default: + throw new IllegalStateException("Type of ConstValue invalid: " + c); + } + + return buf; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Deprecated.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Deprecated.java new file mode 100644 index 000000000..21bbbcb46 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Deprecated.java @@ -0,0 +1,171 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: Deprecated.java,v 1.5 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitDeprecated(this); + } + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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 attribute name + */ + @Override + 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 = (byte[])bytes.clone(); + // + // c.cpool = constant_pool; + // return c; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/EnclosingMethod.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/EnclosingMethod.java new file mode 100644 index 000000000..9e1554ec5 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/EnclosingMethod.java @@ -0,0 +1,87 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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, DataInputStream 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(ClassVisitor 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)cpool.getConstant(classIndex,Constants.CONSTANT_Class); + return c; + } + + public final ConstantNameAndType getEnclosingMethod() { + if (methodIndex == 0) return null; + ConstantNameAndType nat = + (ConstantNameAndType)cpool.getConstant(methodIndex,Constants.CONSTANT_NameAndType); + return nat; + } + + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(classIndex); + file.writeShort(methodIndex); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ExceptionTable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ExceptionTable.java new file mode 100644 index 000000000..ad7d43f2e --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ExceptionTable.java @@ -0,0 +1,199 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: ExceptionTable.java,v 1.5 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitExceptionTable(this); + } + + /** + * Dump exceptions attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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] = cpool.getConstantString(exception_index_table[i], Constants.CONSTANT_Class).replace('/', '.'); + return names; + } + + /** + * @param exception_index_table. 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. + */ + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(""); + String str; + + for (int i = 0; i < number_of_exceptions; i++) { + str = cpool.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(); + // c.exception_index_table = (int[])exception_index_table.clone(); + // c.cpool = constant_pool; + // return c; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Field.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Field.java new file mode 100644 index 000000000..f34464375 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Field.java @@ -0,0 +1,136 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.generic.Type; + +/** + * This class represents the field info structure, i.e., the representation for a variable in the class. See JVM specification for + * details. + * + * @version $Id: Field.java,v 1.6 2009/09/15 03:33:52 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class Field extends FieldOrMethod { + + public static final Field[] NoFields = new Field[0]; + + private Type fieldType = null; // lazily initialized + + private Field() { + } + + public Field(Field c) { + super(c); + } + + Field(DataInputStream dis, ConstantPool cpool) throws IOException { + super(dis, cpool); + } + + public Field(int modifiers, int nameIndex, int signatureIndex, Attribute[] attributes, ConstantPool cpool) { + super(modifiers, nameIndex, signatureIndex, attributes, cpool); + } + + public void accept(ClassVisitor v) { + v.visitField(this); + } + + /** + * @return constant value associated with this field (may be null) + */ + public final ConstantValue getConstantValue() { + return AttributeUtils.getConstantValueAttribute(attributes); + } + + /** + * Return string representation close to declaration format, eg: 'public static final short MAX = 100' + */ + @Override + public final String toString() { + // Get names from constant pool + StringBuffer buf = new StringBuffer(Utility.accessToString(modifiers)); + if (buf.length() > 0) { + buf.append(" "); + } + String signature = Utility.signatureToString(getSignature()); + + buf.append(signature).append(" ").append(getName()); + + ConstantValue cv = getConstantValue(); + if (cv != null) { + buf.append(" = ").append(cv); + } + + // append all attributes that are *not* "ConstantValue" + for (Attribute a : attributes) { + if (!(a instanceof ConstantValue)) { + buf.append(" [").append(a.toString()).append("]"); + } + } + + return buf.toString(); + } + + /** return the type of the field */ + public Type getType() { + if (fieldType == null) { + fieldType = Type.getReturnType(getSignature()); + } + return fieldType; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/FieldOrMethod.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/FieldOrMethod.java new file mode 100644 index 000000000..a152b616f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/FieldOrMethod.java @@ -0,0 +1,201 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; + +/** + * Abstract super class for fields and methods. + * + * @version $Id: FieldOrMethod.java,v 1.12 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class FieldOrMethod extends Modifiers implements Node { + protected int nameIndex; + protected int signatureIndex; + protected Attribute[] attributes; + + protected ConstantPool cpool; + private String name; // lazily initialized + private String signature; // lazily initialized + private AnnotationGen[] annotations; // lazily initialized + private String signatureAttributeString = null; + private boolean searchedForSignatureAttribute = false; + + protected 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.getModifiers(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c.getConstantPool()); + } + + protected FieldOrMethod(DataInputStream file, ConstantPool cpool) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, cpool); + attributes = AttributeUtils.readAttributes(file, cpool); + } + + protected FieldOrMethod(int accessFlags, int nameIndex, int signatureIndex, Attribute[] attributes, ConstantPool cpool) { + this.modifiers = accessFlags; + this.nameIndex = nameIndex; + this.signatureIndex = signatureIndex; + this.cpool = cpool; + this.attributes = attributes; + } + + /** + * @param attributes Collection of object attributes. + */ + public void setAttributes(Attribute[] attributes) { + this.attributes = attributes; + } + + public final void dump(DataOutputStream file) throws IOException { + file.writeShort(modifiers); + file.writeShort(nameIndex); + file.writeShort(signatureIndex); + AttributeUtils.writeAttributes(attributes, file); + } + + public final Attribute[] getAttributes() { + return attributes; + } + + public final ConstantPool getConstantPool() { + return cpool; + } + + public final int getNameIndex() { + return nameIndex; + } + + public final int getSignatureIndex() { + return signatureIndex; + } + + public final String getName() { + if (name == null) { + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8); + name = c.getValue(); + } + return name; + } + + public final String getSignature() { + if (signature == null) { + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(signatureIndex, Constants.CONSTANT_Utf8); + signature = c.getValue(); + } + return signature; + } + + /** + * This will return the contents of a signature attribute attached to a member, or if there is none it will return the same as + * 'getSignature()'. Signature attributes are attached to members that were declared generic. + */ + public final String getDeclaredSignature() { + if (getGenericSignature() != null) + return getGenericSignature(); + return getSignature(); + } + + public AnnotationGen[] getAnnotations() { + // Ensure we have unpacked any attributes that contain annotations. + // We don't remove these annotation attributes from the attributes list, they + // remain there. + if (annotations == null) { + // Find attributes that contain annotation data + List<AnnotationGen> accumulatedAnnotations = new ArrayList<AnnotationGen>(); + for (int i = 0; i < attributes.length; i++) { + Attribute attribute = attributes[i]; + if (attribute instanceof RuntimeAnnos) { + RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) attribute; + accumulatedAnnotations.addAll(runtimeAnnotations.getAnnotations()); + } + } + if (accumulatedAnnotations.size() == 0) { + annotations = AnnotationGen.NO_ANNOTATIONS; + } else { + annotations = accumulatedAnnotations.toArray(new AnnotationGen[] {}); + } + } + return annotations; + } + + /** + * 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) { + Signature sig = AttributeUtils.getSignatureAttribute(attributes); + signatureAttributeString = (sig == null ? null : sig.getSignature()); + searchedForSignatureAttribute = true; + } + return signatureAttributeString; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClass.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClass.java new file mode 100644 index 000000000..d3b1eb0a8 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClass.java @@ -0,0 +1,232 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: InnerClass.java,v 1.4 2009/09/10 15:35:05 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see InnerClasses + */ +public final class InnerClass implements Cloneable, Node { + 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(DataInputStream 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(ClassVisitor 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. + */ + public final void setInnerAccessFlags(int inner_access_flags) { + this.inner_access_flags = inner_access_flags; + } + + /** + * @param inner_class_index. + */ + public final void setInnerClassIndex(int inner_class_index) { + this.inner_class_index = inner_class_index; + } + + /** + * @param inner_name_index. + */ + public final void setInnerNameIndex(int inner_name_index) { + this.inner_name_index = inner_name_index; + } + + /** + * @param outer_class_index. + */ + public final void setOuterClassIndex(int outer_class_index) { + this.outer_class_index = outer_class_index; + } + + /** + * @return String representation. + */ + @Override + 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)).getValue(); + 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClasses.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClasses.java new file mode 100644 index 000000000..0078156ed --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/InnerClasses.java @@ -0,0 +1,181 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: InnerClasses.java,v 1.5 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 + * @param sourcefile_index Index in constant pool to CONSTANT_Utf8 + */ + 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitInnerClasses(this); + } + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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. + */ + 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. + */ + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(); + + for (int i = 0; i < number_of_classes; i++) + buf.append(inner_classes[i].toString(cpool) + "\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.cpool = constant_pool; + // return c; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/JavaClass.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/JavaClass.java new file mode 100644 index 000000000..25c415295 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/JavaClass.java @@ -0,0 +1,837 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +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.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.StringTokenizer; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; +import org.aspectj.apache.bcel.generic.Type; +import org.aspectj.apache.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: JavaClass.java,v 1.22 2009/09/15 19:40:14 aclement Exp $ + * @see org.aspectj.apache.bcel.generic.ClassGen + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class JavaClass extends Modifiers implements Cloneable, Node { + + private static final String[] NoInterfaceNames = new String[0]; + private static final Field[] NoFields = new Field[0]; + private static final Method[] NoMethod = new Method[0]; + private static final int[] NoInterfaceIndices = new int[0]; + private static final Attribute[] NoAttributes = new Attribute[0]; + + private String fileName; + private String packageName; + private String sourcefileName; + private int classnameIdx; + private int superclassnameIdx; + private String classname; + private String superclassname; + private int major, minor; + private ConstantPool cpool; + private int[] interfaces; + private String[] interfacenames; + private Field[] fields; + private Method[] methods; + private Attribute[] attributes; + private AnnotationGen[] annotations; + + private boolean isGeneric = false; + private boolean isAnonymous = false; + private boolean isNested = false; + private boolean computedNestedTypeStatus = false; + + // Annotations are collected from certain attributes, don't do it more than necessary! + private boolean annotationsOutOfDate = true; + + // state for dealing with generic signature string + private String signatureAttributeString = null; + private Signature signatureAttribute = null; + private boolean searchedForSignatureAttribute = false; + + /** + * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any better. + */ + private transient org.aspectj.apache.bcel.util.Repository repository = null; + + public JavaClass(int classnameIndex, int superclassnameIndex, String filename, int major, int minor, int access_flags, + ConstantPool cpool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes) { + if (interfaces == null) { + interfaces = NoInterfaceIndices; + } + + this.classnameIdx = classnameIndex; + this.superclassnameIdx = superclassnameIndex; + this.fileName = filename; + this.major = major; + this.minor = minor; + this.modifiers = access_flags; + this.cpool = cpool; + this.interfaces = interfaces; + this.fields = (fields == null ? NoFields : fields); + this.methods = (methods == null ? NoMethod : methods); + this.attributes = (attributes == null ? NoAttributes : attributes); + annotationsOutOfDate = true; + + // Get source file name if available + SourceFile sfAttribute = AttributeUtils.getSourceFileAttribute(attributes); + sourcefileName = sfAttribute == null ? "<Unknown>" : sfAttribute.getSourceFileName(); + + /* + * According to the specification the following entries must be of type `ConstantClass' but we check that anyway via the + * `ConstPool.getConstant' method. + */ + classname = cpool.getConstantString(classnameIndex, Constants.CONSTANT_Class); + classname = Utility.compactClassName(classname, false); + + int index = classname.lastIndexOf('.'); + if (index < 0) { + packageName = ""; + } else { + packageName = classname.substring(0, index); + } + + if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object + superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class); + superclassname = Utility.compactClassName(superclassname, false); + } else { + superclassname = "java.lang.Object"; + } + + if (interfaces.length == 0) { + interfacenames = NoInterfaceNames; + } else { + interfacenames = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + String str = cpool.getConstantString(interfaces[i], Constants.CONSTANT_Class); + interfacenames[i] = Utility.compactClassName(str, 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(ClassVisitor v) { + v.visitJavaClass(this); + } + + /** + * 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(); + } + dump(new DataOutputStream(new FileOutputStream(file))); + } + + /** + * 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. + */ + public void dump(OutputStream file) throws IOException { + dump(new DataOutputStream(file)); + } + + /** + * Dump Java class to output stream in binary format. + */ + public void dump(DataOutputStream file) throws IOException { + file.writeInt(0xcafebabe); + file.writeShort(minor); + file.writeShort(major); + + cpool.dump(file); + + file.writeShort(modifiers); + file.writeShort(classnameIdx); + file.writeShort(superclassnameIdx); + + 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); + } + + AttributeUtils.writeAttributes(attributes, file); + + file.close(); + } + + public Attribute[] getAttributes() { + return attributes; + } + + public AnnotationGen[] getAnnotations() { + if (annotationsOutOfDate) { + // Find attributes that contain annotation data + List<AnnotationGen> accumulatedAnnotations = new ArrayList<AnnotationGen>(); + for (int i = 0; i < attributes.length; i++) { + Attribute attribute = attributes[i]; + if (attribute instanceof RuntimeAnnos) { + RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) attribute; + accumulatedAnnotations.addAll(runtimeAnnotations.getAnnotations()); + } + } + annotations = accumulatedAnnotations.toArray(new AnnotationGen[] {}); + annotationsOutOfDate = false; + } + return annotations; + } + + /** + * @return Class name. + */ + public String getClassName() { + return classname; + } + + /** + * @return Package name. + */ + public String getPackageName() { + return packageName; + } + + public int getClassNameIndex() { + return classnameIdx; + } + + public ConstantPool getConstantPool() { + return cpool; + } + + /** + * @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 fileName; + } + + /** + * @return Names of implemented interfaces. + */ + public String[] getInterfaceNames() { + return interfacenames; + } + + /** + * @return Indices in constant pool of implemented interfaces. + */ + public int[] getInterfaceIndices() { + return interfaces; + } + + public int getMajor() { + return major; + } + + /** + * @return Methods of the class. + */ + public Method[] getMethods() { + return methods; + } + + /** + * @return A org.aspectj.apache.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; + } + + public Method getMethod(java.lang.reflect.Constructor<?> c) { + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (method.getName().equals("<init>") && c.getModifiers() == method.getModifiers() + && Type.getSignature(c).equals(method.getSignature())) { + return method; + } + } + + return null; + } + + public Field getField(java.lang.reflect.Field field) { + String fieldName = field.getName(); + for (Field f : fields) { + if (f.getName().equals(fieldName)) { + return f; + } + } + 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 sourcefileName; + } + + /** + * @return Superclass name. + */ + public String getSuperclassName() { + return superclassname; + } + + /** + * @return Class name index. + */ + public int getSuperclassNameIndex() { + return superclassnameIdx; + } + + /** + * @param attributes . + */ + public void setAttributes(Attribute[] attributes) { + this.attributes = attributes; + annotationsOutOfDate = true; + } + + /** + * @param class_name . + */ + public void setClassName(String class_name) { + this.classname = class_name; + } + + /** + * @param class_name_index . + */ + public void setClassNameIndex(int class_name_index) { + this.classnameIdx = class_name_index; + } + + /** + * @param constant_pool . + */ + public void setConstantPool(ConstantPool constant_pool) { + this.cpool = 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.fileName = file_name; + } + + /** + * @param interface_names . + */ + public void setInterfaceNames(String[] interface_names) { + this.interfacenames = interface_names; + } + + /** + * @param interfaces . + */ + public void setInterfaces(int[] interfaces) { + this.interfaces = interfaces; + } + + public void setMajor(int major) { + this.major = major; + } + + public void setMethods(Method[] methods) { + this.methods = methods; + } + + 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.sourcefileName = source_file_name; + } + + /** + * @param superclass_name . + */ + public void setSuperclassName(String superclass_name) { + this.superclassname = superclass_name; + } + + /** + * @param superclass_name_index . + */ + public void setSuperclassNameIndex(int superclass_name_index) { + this.superclassnameIdx = superclass_name_index; + } + + /** + * @return String representing class contents. + */ + @Override + public String toString() { + String access = Utility.accessToString(modifiers, true); + access = access.equals("") ? "" : access + " "; + + StringBuffer buf = new StringBuffer(access + Utility.classOrInterface(modifiers) + " " + classname + " extends " + + Utility.compactClassName(superclassname, false) + '\n'); + int size = interfaces.length; + + if (size > 0) { + buf.append("implements\t\t"); + + for (int i = 0; i < size; i++) { + buf.append(interfacenames[i]); + if (i < size - 1) { + buf.append(", "); + } + } + + buf.append('\n'); + } + + buf.append("filename\t\t" + fileName + '\n'); + buf.append("compiled from\t\t" + sourcefileName + '\n'); + buf.append("compiler version\t" + major + "." + minor + '\n'); + buf.append("access flags\t\t" + modifiers + '\n'); + buf.append("constant pool\t\t" + cpool.getLength() + " entries\n"); + buf.append("ACC_SUPER flag\t\t" + isSuper() + "\n"); + + if (attributes.length > 0) { + buf.append("\nAttribute(s):\n"); + for (int i = 0; i < attributes.length; i++) { + buf.append(indent(attributes[i])); + } + } + + 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" + fields.length + " fields:\n"); + for (int i = 0; i < fields.length; i++) { + buf.append("\t" + fields[i] + '\n'); + } + } + + if (methods.length > 0) { + buf.append("\n" + methods.length + " methods:\n"); + for (int i = 0; i < methods.length; i++) { + buf.append("\t" + methods[i] + '\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" + tok.nextToken() + "\n"); + } + + return buf.toString(); + } + + public final boolean isSuper() { + return (modifiers & Constants.ACC_SUPER) != 0; + } + + public final boolean isClass() { + return (modifiers & 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; + } + // Attribute[] attrs = attributes.getAttributes(); + for (int i = 0; i < attributes.length; i++) { + if (attributes[i] instanceof InnerClasses) { + InnerClass[] innerClasses = ((InnerClasses) attributes[i]).getInnerClasses(); + for (int j = 0; j < innerClasses.length; j++) { + boolean innerClassAttributeRefersToMe = false; + String inner_class_name = cpool.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; + } + + // J5SUPPORT: + /** + * Returns true if this class represents an annotation, i.e. it was a 'public @interface blahblah' declaration + */ + public final boolean isAnnotation() { + return (modifiers & Constants.ACC_ANNOTATION) != 0; + } + + /** + * Returns true if this class represents an enum type + */ + public final boolean isEnum() { + return (modifiers & Constants.ACC_ENUM) != 0; + } + + /********************* New repository functionality *********************/ + + /** + * Gets the ClassRepository which holds its definition. By default this is the same as SyntheticRepository.getInstance(); + */ + public org.aspectj.apache.bcel.util.Repository getRepository() { + if (repository == null) { + repository = SyntheticRepository.getInstance(); + } + return repository; + } + + /** + * Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done. + */ + public void setRepository(org.aspectj.apache.bcel.util.Repository repository) { + this.repository = repository; + } + + /** + * Equivalent to runtime "instanceof" operator. + * + * @return true if this JavaClass is derived from teh super class + */ + public final boolean instanceOf(JavaClass super_class) { + 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 clazz is an implementation of interface inter + */ + public boolean implementationOf(JavaClass inter) { + if (!inter.isInterface()) { + throw new IllegalArgumentException(inter.getClassName() + " is no interface"); + } + + if (this.equals(inter)) { + return true; + } + + Collection<JavaClass> superInterfaces = getAllInterfaces(); + + for (JavaClass superInterface : superInterfaces) { + if (superInterface.equals(inter)) { + return true; + } + } + // 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 + */ + public JavaClass getSuperClass() { + if ("java.lang.Object".equals(getClassName())) { + return null; + } + + try { + return getRepository().loadClass(getSuperclassName()); + } catch (ClassNotFoundException e) { + System.err.println(e); + return null; + } + } + + /** + * @return list of super classes of this class in ascending order, i.e., java.lang.Object is always the last element + */ + public JavaClass[] getSuperClasses() { + JavaClass clazz = this; + List<JavaClass> vec = new ArrayList<JavaClass>(); + for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { + vec.add(clazz); + } + return vec.toArray(new JavaClass[vec.size()]); + } + + /** + * Get interfaces directly implemented by this JavaClass. + */ + public JavaClass[] getInterfaces() { + String[] interfaces = getInterfaceNames(); + JavaClass[] classes = new JavaClass[interfaces.length]; + + try { + for (int i = 0; i < interfaces.length; i++) { + classes[i] = getRepository().loadClass(interfaces[i]); + } + } catch (ClassNotFoundException e) { + System.err.println(e); + return null; + } + + return classes; + } + + /** + * Get all interfaces implemented by this JavaClass (transitively). + */ + public Collection<JavaClass> getAllInterfaces() { + Queue<JavaClass> queue = new LinkedList<JavaClass>(); + List<JavaClass> interfaceList = new ArrayList<JavaClass>(); + + queue.add(this); + + while (!queue.isEmpty()) { + JavaClass clazz = queue.remove(); + + JavaClass souper = clazz.getSuperClass(); + JavaClass[] interfaces = clazz.getInterfaces(); + + if (clazz.isInterface()) { + interfaceList.add(clazz); + } else { + if (souper != null) { + queue.add(souper); + } + } + + for (int i = 0; i < interfaces.length; i++) { + queue.add(interfaces[i]); + } + } + + return interfaceList; + // return interfaceList.toArray(new JavaClass[interfaceList.size()]); + } + + /** + * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be + * Ljava/util/Vector; the signature attribute will tell us e.g. "<E:>Ljava/lang/Object". We can learn the type variable names, + * their bounds, and the true superclass and superinterface types (including any parameterizations) Coded for performance - + * searches for the attribute only when requested - only searches for it once. + */ + public final String getGenericSignature() { + loadGenericSignatureInfoIfNecessary(); + return signatureAttributeString; + } + + public boolean isGeneric() { + loadGenericSignatureInfoIfNecessary(); + return isGeneric; + } + + private void loadGenericSignatureInfoIfNecessary() { + if (!searchedForSignatureAttribute) { + signatureAttribute = AttributeUtils.getSignatureAttribute(attributes); + signatureAttributeString = signatureAttribute == null ? null : signatureAttribute.getSignature(); + isGeneric = signatureAttribute != null && signatureAttributeString.charAt(0) == '<'; + searchedForSignatureAttribute = true; + } + } + + public final Signature getSignatureAttribute() { + loadGenericSignatureInfoIfNecessary(); + return signatureAttribute; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumber.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumber.java new file mode 100644 index 000000000..6b2a64877 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumber.java @@ -0,0 +1,120 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * 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: LineNumber.java,v 1.6 2009/09/09 21:26:54 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author Andy Clement + * @see LineNumberTable + */ +public final class LineNumber implements Node { + private int startPC; + private int lineNumber; + + public LineNumber(LineNumber c) { + this(c.getStartPC(), c.getLineNumber()); + } + + LineNumber(DataInputStream file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort()); + } + + public LineNumber(int startPC, int lineNumber) { + this.startPC = startPC; + this.lineNumber = lineNumber; + } + + public void accept(ClassVisitor v) { + v.visitLineNumber(this); + } + + public final void dump(DataOutputStream file) throws IOException { + file.writeShort(startPC); + file.writeShort(lineNumber); + } + + public final int getLineNumber() { + return lineNumber; + } + + public final int getStartPC() { + return startPC; + } + + // public final void setLineNumber(int line_number) { + // this.lineNumber = line_number; + // } + // + // public final void setStartPC(int start_pc) { + // this.startPC = start_pc; + // } + + @Override + public final String toString() { + return "LineNumber(" + startPC + ", " + lineNumber + ")"; + } + + public LineNumber copy() { + return new LineNumber(this); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumberTable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumberTable.java new file mode 100644 index 000000000..871bfe6bf --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LineNumberTable.java @@ -0,0 +1,276 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: LineNumberTable.java,v 1.8 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Code changes: asc Feb06 Made unpacking lazy + */ +public final class LineNumberTable extends Attribute { + + // if 'isInPackedState' then this data needs unpacking + private boolean isInPackedState = false; + private byte[] data; // discarded once unpacked + + private int tableLength; + private LineNumber[] table; + + /* + * 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()); + } + + public LineNumberTable(int nameIndex, int length, LineNumber[] lineNumberTable, ConstantPool constantPool) { + super(Constants.ATTR_LINE_NUMBER_TABLE, nameIndex, length, constantPool); + setLineNumberTable(lineNumberTable); + isInPackedState = false; + } + + /** + * Construct object from file stream. + * + * @param name_index Index of name + * @param length Content length in bytes + * @param file Input stream + * @throws IOException + * @param constant_pool Array of constants + */ + LineNumberTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + this(name_index, length, (LineNumber[]) null, constant_pool); + data = new byte[length]; + file.readFully(data); + isInPackedState = true; + // assert(bytesRead==length) + } + + // Unpacks the byte array into the table + private void unpack() { + if (isInPackedState) { + try { + ByteArrayInputStream bs = new ByteArrayInputStream(data); + DataInputStream dis = new DataInputStream(bs); + tableLength = (dis.readUnsignedShort()); + table = new LineNumber[tableLength]; + for (int i = 0; i < tableLength; i++) { + table[i] = new LineNumber(dis); + } + dis.close(); + data = null; // throw it away now + } catch (IOException e) { + throw new RuntimeException("Unpacking of LineNumberTable attribute failed"); + } + isInPackedState = 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 + */ + @Override + public void accept(ClassVisitor v) { + unpack(); + v.visitLineNumberTable(this); + } + + /** + * Dump line number table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + if (isInPackedState) { + file.write(data); + } else { + file.writeShort(tableLength); + for (int i = 0; i < tableLength; i++) { + table[i].dump(file); + } + } + } + + /** + * @return Array of (pc offset, line number) pairs. + */ + public final LineNumber[] getLineNumberTable() { + unpack(); + return table; + } + + /** + * @param line_number_table. + */ + public final void setLineNumberTable(LineNumber[] line_number_table) { + this.data = null; + this.isInPackedState = false; + this.table = line_number_table; + this.tableLength = (line_number_table == null) ? 0 : line_number_table.length; + } + + /** + * @return String representation. + */ + @Override + public final String toString() { + unpack(); + StringBuffer buf = new StringBuffer(); + StringBuffer line = new StringBuffer(); + + for (int i = 0; i < tableLength; i++) { + line.append(table[i].toString()); + + if (i < tableLength - 1) { + line.append(", "); + } + + if (line.length() > 72) { + line.append('\n'); + buf.append(line); + 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) { + unpack(); + int l = 0, r = tableLength - 1; + + if (r < 0) // array is empty + 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 = table[i].getStartPC(); + + if (j == pos) + return table[i].getLineNumber(); + else if (pos < j) // else constrain search area + r = i - 1; + else + // pos > j + 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 table[min_index].getLineNumber(); + } + + /** + * @return deep copy of this attribute + */ + // @Override + // public Attribute copy(ConstantPool constant_pool) { + // unpack(); + // LineNumberTable newTable = (LineNumberTable) clone(); + // newTable.table = new LineNumber[tableLength]; + // for (int i = 0; i < tableLength; i++) { + // newTable.table[i] = table[i].copy(); + // } + // newTable.cpool = constant_pool; + // return newTable; + // } + public final int getTableLength() { + unpack(); + return tableLength; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariable.java new file mode 100644 index 000000000..c8d5cd87f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariable.java @@ -0,0 +1,267 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: LocalVariable.java,v 1.5 2009/09/10 15:35:05 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see LocalVariableTable + */ +public final class LocalVariable implements Constants, Cloneable, Node { + + 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(DataInputStream 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(ClassVisitor 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.getValue(); + } + + /** + * @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.getValue(); + } + + /** + * @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. + */ + public final void setLength(int length) { + this.length = length; + } + + /** + * @param name_index. + */ + public final void setNameIndex(int name_index) { + this.name_index = name_index; + } + + /** + * @param signature_index. + */ + public final void setSignatureIndex(int signature_index) { + this.signature_index = signature_index; + } + + /** + * @param index. + */ + 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. + */ + @Override + 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java new file mode 100644 index 000000000..e6415dae6 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTable.java @@ -0,0 +1,230 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class represents collection of local variables in a method. This attribute is contained in the <em>Code</em> attribute. + * + * @version $Id: LocalVariableTable.java,v 1.8 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Code + * @see LocalVariable Updates: Andy 14Feb06 - Made unpacking of the data lazy, depending on someone actually asking for it. + */ +public class LocalVariableTable extends Attribute { + + // if 'isInPackedState' then this data needs unpacking + private boolean isInPackedState = false; + private byte[] data; + + private int localVariableTableLength; + private LocalVariable[] localVariableTable; + + /** + * 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 { + super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool); + data = new byte[length]; + file.readFully(data); + isInPackedState = true; + // assert(bytesRead==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 + */ + @Override + public void accept(ClassVisitor v) { + unpack(); + v.visitLocalVariableTable(this); + } + + /** + * Dump local variable table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + if (isInPackedState) { + file.write(data); + } else { + file.writeShort(localVariableTableLength); + for (int i = 0; i < localVariableTableLength; i++) + localVariableTable[i].dump(file); + } + } + + /** + * @return Array of local variables of method. + */ + public final LocalVariable[] getLocalVariableTable() { + unpack(); + return localVariableTable; + } + + /** + * @return first matching variable using index + */ + public final LocalVariable getLocalVariable(int index) { + unpack(); + for (int i = 0; i < localVariableTableLength; i++) { + if (localVariableTable[i] != null && localVariableTable[i].getIndex() == index) { + return localVariableTable[i]; + } + } + return null; + } + + public final void setLocalVariableTable(LocalVariable[] local_variable_table) { + data = null; + isInPackedState = false; + this.localVariableTable = local_variable_table; + localVariableTableLength = (local_variable_table == null) ? 0 : local_variable_table.length; + } + + /** + * @return String representation. + */ + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(""); + unpack(); + for (int i = 0; i < localVariableTableLength; i++) { + buf.append(localVariableTable[i].toString()); + + if (i < localVariableTableLength - 1) + buf.append('\n'); + } + + return buf.toString(); + } + + /** + * @return deep copy of this attribute + */ + // public Attribute copy(ConstantPool constant_pool) { + // unpack(); + // LocalVariableTable c = (LocalVariableTable) clone(); + // + // c.localVariableTable = new LocalVariable[localVariableTableLength]; + // for (int i = 0; i < localVariableTableLength; i++) + // c.localVariableTable[i] = localVariableTable[i].copy(); + // + // c.cpool = constant_pool; + // return c; + // } + public final int getTableLength() { + unpack(); + return localVariableTableLength; + } + + // --- + // Unpacks the byte array into the table + private void unpack() { + if (!isInPackedState) + return; + try { + ByteArrayInputStream bs = new ByteArrayInputStream(data); + DataInputStream dis = new DataInputStream(bs); + localVariableTableLength = (dis.readUnsignedShort()); + localVariableTable = new LocalVariable[localVariableTableLength]; + for (int i = 0; i < localVariableTableLength; i++) + localVariableTable[i] = new LocalVariable(dis, cpool); + dis.close(); + data = null; // throw it away now + } catch (IOException e) { + throw new RuntimeException("Unpacking of LocalVariableTable attribute failed"); + } + isInPackedState = false; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTypeTable.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTypeTable.java new file mode 100644 index 000000000..ecd7e4383 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/LocalVariableTypeTable.java @@ -0,0 +1,136 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * Heavily based on LocalVariableTable + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +// 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); + } + + @Override + public void accept(ClassVisitor v) { + v.visitLocalVariableTypeTable(this); + } + + @Override + 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. + */ + @Override + 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.cpool = constant_pool; + // return c; + // } + + public final int getTableLength() { + return local_variable_type_table_length; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Method.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Method.java new file mode 100644 index 000000000..46aeac845 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Method.java @@ -0,0 +1,273 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos; +import org.aspectj.apache.bcel.generic.Type; + +/** + * 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: Method.java,v 1.11 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class Method extends FieldOrMethod { + + public static final AnnotationGen[][] NO_PARAMETER_ANNOTATIONS = new AnnotationGen[][] {}; + + public static final Method[] NoMethods = new Method[0]; + + private boolean parameterAnnotationsOutOfDate = true; + private AnnotationGen[][] unpackedParameterAnnotations; + + private Method() { + parameterAnnotationsOutOfDate = true; + } + + /** + * 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); + parameterAnnotationsOutOfDate = true; + } + + Method(DataInputStream file, ConstantPool constant_pool) throws IOException { + super(file, constant_pool); + } + + 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); + parameterAnnotationsOutOfDate = true; + } + + public void accept(ClassVisitor v) { + v.visitMethod(this); + } + + // CUSTARD mutable or not? + @Override + public void setAttributes(Attribute[] attributes) { + parameterAnnotationsOutOfDate = true; + super.setAttributes(attributes); + } + + /** + * @return Code attribute of method, if any + */ + public final Code getCode() { + return AttributeUtils.getCodeAttribute(attributes); + } + + public final ExceptionTable getExceptionTable() { + return AttributeUtils.getExceptionTableAttribute(attributes); + } + + /** + * Return LocalVariableTable of code attribute if any (the call is forwarded to the Code attribute) + */ + public final LocalVariableTable getLocalVariableTable() { + Code code = getCode(); + if (code != null) + return code.getLocalVariableTable(); + return null; + } + + /** + * Return LineNumberTable of code attribute if any (the call is forwarded to the Code attribute) + */ + public final LineNumberTable getLineNumberTable() { + Code code = getCode(); + if (code != null) + return code.getLineNumberTable(); + return null; + } + + /** + * Return string representation close to declaration format, eg: 'public static void main(String[] args) throws IOException' + */ + @Override + public final String toString() { + ConstantUtf8 c; + String name, signature, access; // Short cuts to constant pool + StringBuffer buf; + + access = Utility.accessToString(modifiers); + + // Get name and signature from constant pool + c = (ConstantUtf8) cpool.getConstant(signatureIndex, Constants.CONSTANT_Utf8); + signature = c.getValue(); + + c = (ConstantUtf8) cpool.getConstant(nameIndex, Constants.CONSTANT_Utf8); + name = c.getValue(); + + signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable()); + buf = new StringBuffer(signature); + + for (int i = 0; i < attributes.length; i++) { + Attribute a = attributes[i]; + if (!((a instanceof Code) || (a instanceof ExceptionTable))) + buf.append(" [" + a.toString() + "]"); + } + + ExceptionTable e = getExceptionTable(); + if (e != null) { + String str = e.toString(); + if (!str.equals("")) + buf.append("\n\t\tthrows " + str); + } + + return buf.toString(); + } + + /** + * @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()); + } + + private void ensureParameterAnnotationsUnpacked() { + if (!parameterAnnotationsOutOfDate) + return; + parameterAnnotationsOutOfDate = false; + + int parameterCount = getArgumentTypes().length; + if (parameterCount == 0) { + unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS; + return; + } + + RuntimeVisParamAnnos parameterAnnotationsVis = null; + RuntimeInvisParamAnnos parameterAnnotationsInvis = null; + + // Find attributes that contain annotation data + Attribute[] attrs = getAttributes(); + + for (int i = 0; i < attrs.length; i++) { + Attribute attribute = attrs[i]; + if (attribute instanceof RuntimeVisParamAnnos) { + parameterAnnotationsVis = (RuntimeVisParamAnnos) attribute; + } else if (attribute instanceof RuntimeInvisParamAnnos) { + parameterAnnotationsInvis = (RuntimeInvisParamAnnos) attribute; + } + } + + boolean foundSome = false; + // Build a list of annotation arrays, one per argument + if (parameterAnnotationsInvis != null || parameterAnnotationsVis != null) { + List<AnnotationGen[]> annotationsForEachParameter = new ArrayList<AnnotationGen[]>(); + AnnotationGen[] visibleOnes = null; + AnnotationGen[] invisibleOnes = null; + for (int i = 0; i < parameterCount; i++) { + int count = 0; + visibleOnes = new AnnotationGen[0]; + invisibleOnes = new AnnotationGen[0]; + if (parameterAnnotationsVis != null) { + visibleOnes = parameterAnnotationsVis.getAnnotationsOnParameter(i); + count += visibleOnes.length; + } + if (parameterAnnotationsInvis != null) { + invisibleOnes = parameterAnnotationsInvis.getAnnotationsOnParameter(i); + count += invisibleOnes.length; + } + + AnnotationGen[] complete = AnnotationGen.NO_ANNOTATIONS; + if (count != 0) { + complete = new AnnotationGen[visibleOnes.length + invisibleOnes.length]; + System.arraycopy(visibleOnes, 0, complete, 0, visibleOnes.length); + System.arraycopy(invisibleOnes, 0, complete, visibleOnes.length, invisibleOnes.length); + foundSome = true; + } + annotationsForEachParameter.add(complete); + } + if (foundSome) { + unpackedParameterAnnotations = annotationsForEachParameter.toArray(new AnnotationGen[][] {}); + return; + } + } + unpackedParameterAnnotations = NO_PARAMETER_ANNOTATIONS; + } + + public AnnotationGen[] getAnnotationsOnParameter(int i) { + ensureParameterAnnotationsUnpacked(); + if (unpackedParameterAnnotations == NO_PARAMETER_ANNOTATIONS) { + return AnnotationGen.NO_ANNOTATIONS; + } + return unpackedParameterAnnotations[i]; + } + + public AnnotationGen[][] getParameterAnnotations() { + ensureParameterAnnotationsUnpacked(); + return unpackedParameterAnnotations; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/MethodParameters.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/MethodParameters.java new file mode 100644 index 000000000..547041584 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/MethodParameters.java @@ -0,0 +1,112 @@ +/* ******************************************************************* + * Copyright (c) 2013 VMware + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +// see http://cr.openjdk.java.net/~abuckley/8misc.pdf +public class MethodParameters extends Attribute { + + public final static int[] NO_PARAMETER_NAME_INDEXES = new int[0]; + public final static int[] NO_PARAMETER_ACCESS_FLAGS = new int[0]; + + public final static int ACCESS_FLAGS_FINAL = 0x0010; + public final static int ACCESS_FLAGS_SYNTHETIC = 0x1000; + public final static int ACCESS_FLAGS_MANDATED = 0x8000; + + // if 'isInPackedState' then this data needs unpacking + private boolean isInPackedState = false; + private byte[] data; + private int[] names; + private int[] accessFlags; + + public MethodParameters(int index, int length, DataInputStream dis, ConstantPool cpool) throws IOException { + super(Constants.ATTR_METHOD_PARAMETERS,index,length,cpool); + data = new byte[length]; + dis.readFully(data,0,length); + isInPackedState = true; + } + + private void ensureInflated() { + if (names!=null) return; + try { + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data)); + int parametersCount = dis.readUnsignedByte(); + if (parametersCount == 0) { + names = NO_PARAMETER_NAME_INDEXES; + accessFlags = NO_PARAMETER_ACCESS_FLAGS; + } else { + names = new int[parametersCount]; + accessFlags = new int[parametersCount]; + for (int i=0;i<parametersCount;i++) { + names[i] = dis.readUnsignedShort(); + accessFlags[i] = dis.readUnsignedShort(); + } + } + isInPackedState = false; + } catch (IOException ioe) { + throw new RuntimeException("Unabled to inflate type annotation data, badly formed?"); + } + } + + public void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + if (isInPackedState) { + dos.write(data); + } else { + dos.writeByte(names.length); + for (int i=0;i<names.length;i++) { + dos.writeShort(names[i]); + dos.writeShort(accessFlags[i]); + } + } + } + + public int getParametersCount() { + ensureInflated(); + return names.length; + } + + public String getParameterName(int parameter) { + ensureInflated(); + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(names[parameter], Constants.CONSTANT_Utf8); + return c.getValue(); + } + + public int getAccessFlags(int parameter) { + ensureInflated(); + return accessFlags[parameter]; + } + + public boolean isFinal(int parameter) { + return (getAccessFlags(parameter) & ACCESS_FLAGS_FINAL)!=0; + } + + public boolean isSynthetic(int parameter) { + return (getAccessFlags(parameter) & ACCESS_FLAGS_SYNTHETIC)!=0; + } + + public boolean isMandated(int parameter) { + return (getAccessFlags(parameter) & ACCESS_FLAGS_MANDATED)!=0; + } + + @Override + public void accept(ClassVisitor v) { + v.visitMethodParameters(this); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Modifiers.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Modifiers.java new file mode 100644 index 000000000..63719913d --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Modifiers.java @@ -0,0 +1,140 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.Constants; + +/** + * Super class for all objects that have modifiers like private, final, ... I.e. + * classes, fields, and methods. + * was AccessFlags + * + * @version $Id: Modifiers.java,v 1.2 2008/05/28 23:53:01 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class Modifiers { + + protected int modifiers; + + public Modifiers() { } + + public Modifiers(int a) { + modifiers = a; + } + + public final int getModifiers() { + return modifiers; + } + + public final void setModifiers(int modifiers) { + this.modifiers = modifiers; + } + + public final boolean isPublic() { + return (modifiers & Constants.ACC_PUBLIC) != 0; + } + + public final boolean isPrivate() { + return (modifiers & Constants.ACC_PRIVATE) != 0; + } + + public final boolean isProtected() { + return (modifiers & Constants.ACC_PROTECTED) != 0; + } + + public final boolean isStatic() { + return (modifiers & Constants.ACC_STATIC) != 0; + } + + public final boolean isFinal() { + return (modifiers & Constants.ACC_FINAL) != 0; + } + + public final boolean isSynchronized() { + return (modifiers & Constants.ACC_SYNCHRONIZED) != 0; + } + + public final boolean isVolatile() { + return (modifiers & Constants.ACC_VOLATILE) != 0; + } + + public final boolean isTransient() { + return (modifiers & Constants.ACC_TRANSIENT) != 0; + } + + public final boolean isNative() { + return (modifiers & Constants.ACC_NATIVE) != 0; + } + + public final boolean isInterface() { + return (modifiers & Constants.ACC_INTERFACE) != 0; + } + + public final boolean isAbstract() { + return (modifiers & Constants.ACC_ABSTRACT) != 0; + } + + public final boolean isStrictfp() { + return (modifiers & Constants.ACC_STRICT) != 0; + } + + public final boolean isVarargs() { + return (modifiers & Constants.ACC_VARARGS) != 0; + } + + public final boolean isBridge() { + return (modifiers & Constants.ACC_BRIDGE) != 0; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Module.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Module.java new file mode 100644 index 000000000..5eef18cde --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Module.java @@ -0,0 +1,664 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2016-17 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from <em>Attribute</em> and represents the module + * information captured in a class file. + * http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html + * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.25 + * + * @author Andy Clement + */ +public final class Module extends Attribute { + + private static final String[] NO_MODULE_NAMES = {}; + + private int moduleNameIndex; // u2 module_name_index + private int moduleFlags; // u2 module_flags + private int moduleVersionIndex; // u2 module_version_index + private Require[] requires; + private Export[] exports; + private Open[] opens; + private Uses[] uses; + private Provide[] provides; + + private byte[] moduleInfo; + private int ptr; + private boolean unpacked = false; + + public Module(Module module) { + super(module.getTag(), module.getNameIndex(), module.getLength(), module.getConstantPool()); + moduleInfo = module.getBytes(); + } + + public Module(int nameIndex, int length, byte[] data, ConstantPool cp) { + super(Constants.ATTR_MODULE, nameIndex, length, cp); + } + + Module(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException { + this(nameIndex, length, (byte[])null, cp); + moduleInfo = new byte[length]; + stream.read(moduleInfo); + unpacked = false; + } + + public class Require { + + private final int moduleIndex; + private final int flags; + private final int versionIndex; + + public Require(int moduleIndex, int flags, int versionIndex) { + this.moduleIndex = moduleIndex; + this.flags = flags; + this.versionIndex = versionIndex; + } + + public String getModuleName() { + return cpool.getModuleName(moduleIndex); + } + + public int getFlags() { + return flags; + } + + public int getVersionIndex() { + return versionIndex; + } + + public String getVersionString() { + if (versionIndex == 0) { + return null; + } else { + return cpool.getConstantUtf8(versionIndex).getValue(); + } + } + + public String getFlagsAsString() { + StringBuilder s = new StringBuilder(); + if ((flags & Constants.MODULE_ACC_TRANSITIVE)!=0) { + s.append(" transitive"); + } + if ((flags & Constants.MODULE_ACC_STATIC_PHASE)!=0) { + s.append(" static"); + } + if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) { + s.append(" synthetic"); + } + if ((flags & Constants.MODULE_ACC_MANDATED)!=0) { + s.append(" mandated"); + } + return s.toString(); + } + + public String toString() { + return "requires"+getFlagsAsString()+" "+getModuleName()+(versionIndex==0?"":" "+getVersionString()); + } + } + + + public class Export { + + private final int packageIndex; + private final int flags; + private final int[] toModuleIndices; + + public Export(int packageIndex, int flags, int[] toModuleIndices) { + this.packageIndex = packageIndex; + this.flags = flags; + this.toModuleIndices = toModuleIndices; + } + + public int getPackageIndex() { + return packageIndex; + } + + public int getFlags() { + return flags; + } + + public int[] getToModuleIndices() { + return toModuleIndices; + } + + public String getPackage() { + return cpool.getPackageName(packageIndex); + } + + public String getFlagsAsString() { + StringBuilder s = new StringBuilder(); + if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) { + s.append(" synthetic"); + } + if ((flags & Constants.MODULE_ACC_MANDATED)!=0) { + s.append(" synthetic"); + } + return s.toString(); + } + + public String[] getToModuleNames() { + if (toModuleIndices==null) { + return NO_MODULE_NAMES; + } + String[] toModuleNames = new String[toModuleIndices.length]; + for (int i=0;i<toModuleIndices.length;i++) { + toModuleNames[i] = cpool.getModuleName(toModuleIndices[i]); + } + return toModuleNames; + } + + public String toString() { + StringBuilder s =new StringBuilder(); + s.append("exports").append(getFlagsAsString()).append(" ").append(getPackage().replace('/', '.')); + String[] toModules = getToModuleNames(); + if (toModules.length!=0) { + s.append(" to "); + for (int i=0;i<toModules.length;i++) { + if (i>0) { + s.append(", "); + } + s.append(toModules[i]); + } + } + return s.toString().trim(); + } + } + + + public class Open { + + private final int packageIndex; + private final int flags; + private final int[] toModuleIndices; + + public Open(int packageIndex, int flags, int[] toModuleIndices) { + this.packageIndex = packageIndex; + this.flags = flags; + this.toModuleIndices = toModuleIndices; + } + + public int getPackageIndex() { + return packageIndex; + } + + public int getFlags() { + return flags; + } + + public int[] getToModuleIndices() { + return toModuleIndices; + } + + public String getPackage() { + return cpool.getPackageName(packageIndex); + } + + public String getFlagsAsString() { + StringBuilder s = new StringBuilder(); + if ((flags & Constants.MODULE_ACC_SYNTHETIC)!=0) { + s.append(" synthetic"); + } + if ((flags & Constants.MODULE_ACC_MANDATED)!=0) { + s.append(" synthetic"); + } + return s.toString(); + } + + public String[] getToModuleNames() { + if (toModuleIndices==null) { + return NO_MODULE_NAMES; + } + String[] toModuleNames = new String[toModuleIndices.length]; + for (int i=0;i<toModuleIndices.length;i++) { + toModuleNames[i] = cpool.getModuleName(toModuleIndices[i]); + } + return toModuleNames; + } + + public String toString() { + StringBuilder s =new StringBuilder(); + s.append("opens").append(getFlagsAsString()).append(" ").append(getPackage().replace('/', '.')); + String[] toModules = getToModuleNames(); + if (toModules.length!=0) { + s.append(" to "); + for (int i=0;i<toModules.length;i++) { + if (i>0) { + s.append(", "); + } + s.append(toModules[i]); + } + } + return s.toString().trim(); + } + } + + public class Provide { + private final int providedTypeIndex; + private final int[] withTypeIndices; + + public Provide(int providedTypeIndex, int[] withTypeIndices) { + this.providedTypeIndex = providedTypeIndex; + this.withTypeIndices = withTypeIndices; + } + + public String getProvidedType() { + return cpool.getConstantString_CONSTANTClass(providedTypeIndex); + } + + public int getProvidedTypeIndex() { + return providedTypeIndex; + } + + public String[] getWithTypeStrings() { + String[] result = new String[withTypeIndices.length]; + for (int i=0;i<withTypeIndices.length;i++) { + result[i] = cpool.getConstantString_CONSTANTClass(withTypeIndices[i]); + } + return result; + } + + public int[] getWithTypeIndices() { + return withTypeIndices; + } + + public String toString() { + StringBuilder s =new StringBuilder(); + s.append("provides ").append(getProvidedType().replace('/', '.')); + s.append(" with "); + String[] withtypes = getWithTypeStrings(); + for (int i=0;i< withtypes.length;i++) { + if (i>0) s.append(","); + s.append(withtypes[i].replace('/','.')); + } + return s.toString(); + } + } + + public class Uses { + private final int typeNameIndex; + + public Uses(int typeNameIndex) { + this.typeNameIndex = typeNameIndex; + } + + public String getTypeName() { + return cpool.getConstantString_CONSTANTClass(typeNameIndex); + } + + public int getTypeNameIndex() { + return typeNameIndex; + } + + public String toString() { + StringBuilder s =new StringBuilder(); + s.append("uses ").append(getTypeName().replace('/', '.')); + return s.toString().trim(); + } + } + + private final int readInt() { + return ((moduleInfo[ptr++] & 0xFF) << 24) + ((moduleInfo[ptr++] & 0xFF) << 16) + + ((moduleInfo[ptr++] & 0xFF) << 8) + (moduleInfo[ptr++] & 0xFF); + } + + private final int readUnsignedShort() { + return ((moduleInfo[ptr++] & 0xff) << 8) + (moduleInfo[ptr++] & 0xff); + } + + private final int readUnsignedShort(int offset) { + return ((moduleInfo[offset++] & 0xff) << 8) + (moduleInfo[offset] & 0xff); + } + + // Format: http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.25 + private void ensureUnpacked() { + if (!unpacked) { + ptr = 0; + moduleNameIndex = readUnsignedShort(); + moduleFlags = readUnsignedShort(); + moduleVersionIndex = readUnsignedShort(); + + int count = readUnsignedShort(); + requires = new Require[count]; + for (int i = 0; i < count; i++) { + requires[i] = new Require(readUnsignedShort(), readUnsignedShort(), readUnsignedShort()); + } + + count = readUnsignedShort(); + exports = new Export[count]; + for (int i = 0; i < count; i++) { + int index = readUnsignedShort(); + int flags = readUnsignedShort(); + int toCount = readUnsignedShort(); + int[] to = new int[toCount]; + for (int j = 0; j < toCount; j++) { + to[j] = readUnsignedShort(); + } + exports[i] = new Export(index, flags, to); + } + + count = readUnsignedShort(); + opens = new Open[count]; + for (int i = 0; i < count; i++) { + int index = readUnsignedShort(); + int flags = readUnsignedShort(); + int toCount = readUnsignedShort(); + int[] to = new int[toCount]; + for (int j = 0; j < toCount; j++) { + to[j] = readUnsignedShort(); + } + opens[i] = new Open(index, flags, to); + } + count = readUnsignedShort(); + uses = new Uses[count]; + for (int i = 0; i < count; i++) { + uses[i] = new Uses(readUnsignedShort()); + } + count = readUnsignedShort(); + provides = new Provide[count]; + for (int i = 0; i < count; i++) { + int index = readUnsignedShort(); + int toCount = readUnsignedShort(); + int[] to = new int[toCount]; + for (int j = 0; j < toCount; j++) { + to[j] = readUnsignedShort(); + } + provides[i] = new Provide(index, to); + } + unpacked = true; + } + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + if (!unpacked) { + file.write(moduleInfo); + } else { + + file.writeShort(moduleNameIndex); + file.writeShort(moduleFlags); + file.writeShort(moduleVersionIndex); + + file.writeShort(requires.length); + for (int i = 0; i < requires.length; i++) { + file.writeShort(requires[i].moduleIndex); + file.writeShort(requires[i].flags); + file.writeShort(requires[i].versionIndex); + } + file.writeShort(exports.length); + for (Export export : exports) { + file.writeShort(export.packageIndex); + int[] toIndices = export.toModuleIndices; + file.writeShort(toIndices.length); + for (int index : toIndices) { + file.writeShort(index); + } + } + file.writeShort(opens.length); + for (Open open : opens) { + file.writeShort(open.packageIndex); + int[] toIndices = open.toModuleIndices; + file.writeShort(toIndices.length); + for (int index : toIndices) { + file.writeShort(index); + } + } + file.writeShort(uses.length); + for (Uses use : uses) { + file.writeShort(use.getTypeNameIndex()); + } + file.writeShort(provides.length); + for (Provide provide : provides) { + file.writeShort(provide.providedTypeIndex); + int[] toIndices = provide.withTypeIndices; + file.writeShort(toIndices.length); + for (int index : toIndices) { + file.writeShort(index); + } + } + } + } + + public String toStringRequires() { + StringBuilder s = new StringBuilder(); + s.append('#').append(requires.length); + if (requires.length > 0) { + for (Require require : requires) { + s.append(' '); + s.append(require.moduleIndex).append(':').append(require.flags); + } + } + return s.toString(); + } + + public String toStringExports() { + StringBuilder s = new StringBuilder(); + s.append('#').append(exports.length); + if (exports.length > 0) { + for (Export export : exports) { + s.append(' '); + s.append(export.packageIndex).append(":["); + int[] toIndices = export.toModuleIndices; + for (int i = 0; i < toIndices.length; i++) { + if (i > 0) + s.append(','); + s.append(toIndices[i]); + } + s.append("]"); + } + } + return s.toString(); + } + + public String toStringOpens() { + StringBuilder s = new StringBuilder(); + s.append('#').append(opens.length); + if (opens.length > 0) { + for (Open open : opens) { + s.append(' '); + s.append(open.packageIndex).append(":["); + int[] toIndices = open.toModuleIndices; + for (int i = 0; i < toIndices.length; i++) { + if (i > 0) + s.append(','); + s.append(toIndices[i]); + } + s.append("]"); + } + } + return s.toString(); + } + + public String toStringUses() { + StringBuilder s = new StringBuilder(); + s.append('#').append(uses.length); + if (uses.length > 0) { + for (Uses use : uses) { + s.append(' '); + s.append(use.getTypeName()); + } + } + return s.toString(); + } + + public String toStringProvides() { + StringBuilder s = new StringBuilder(); + s.append('#').append(provides.length); + if (provides.length > 0) { + for (Provide provide : provides) { + s.append(' '); + s.append(provide.providedTypeIndex).append(":["); + int[] indices = provide.withTypeIndices; + for (int i = 0; i < indices.length; i++) { + if (i > 0) + s.append(','); + s.append(indices[i]); + } + s.append("]"); + } + } + return s.toString(); + } + + @Override + public final String toString() { + StringBuilder s = new StringBuilder(); + ensureUnpacked(); + s.append("Module("); + if (requires.length != 0) { + s.append("requires="); + s.append(toStringRequires()); + s.append(" "); + } + if (exports.length != 0) { + s.append("exports="); + s.append(toStringExports()); + s.append(" "); + } + if (opens.length != 0) { + s.append("opens="); + s.append(toStringOpens()); + s.append(" "); + } + if (uses.length != 0) { + s.append("uses="); + s.append(toStringUses()); + s.append(" "); + } + if (provides.length != 0) { + s.append("provides="); + s.append(toStringProvides()); + s.append(" "); + } + return s.toString().trim()+")"; + } + + /** + * @return deep copy of this attribute // + */ +// @Override +// public Attribute copy(ConstantPool constant_pool) { +// return (Module) clone(); +// } + + @Override + public void accept(ClassVisitor v) { + v.visitModule(this); + } + + public Require[] getRequires() { + ensureUnpacked(); + return requires; + } + + public String[] getRequiredModuleNames() { + ensureUnpacked(); + String[] results = new String[requires.length]; + for (int i=0;i<requires.length;i++) { + results[i] = cpool.getModuleName(requires[i].moduleIndex); + } + return results; + } + + public byte[] getBytes() { + return moduleInfo; + } + + public Export[] getExports() { + ensureUnpacked(); + return exports; + } + + public Open[] getOpens() { + ensureUnpacked(); + return opens; + } + + public Uses[] getUses() { + ensureUnpacked(); + return uses; + } + + public Provide[] getProvides() { + ensureUnpacked(); + return provides; + } + + public String getModuleName() { + return ((ConstantModule)cpool.getConstant(moduleNameIndex)).getModuleName(cpool); + } + + public int getModuleFlags() { + // 0x0020 (ACC_OPEN) - Indicates that this module is open. + // 0x1000 (ACC_SYNTHETIC) - Indicates that this module was not explicitly or implicitly declared. + // 0x8000 (ACC_MANDATED) - Indicates that this module was implicitly declared + return moduleFlags; + } + + /** @return the module version or null if no version information specified */ + public String getModuleVersion() { + if (moduleVersionIndex == 0) { + return null; + } else { + return cpool.getConstantUtf8(moduleVersionIndex).getValue(); + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModuleMainClass.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModuleMainClass.java new file mode 100644 index 000000000..3fa500a8e --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModuleMainClass.java @@ -0,0 +1,106 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2017 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Indicates the main class of a module. + * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.26 + * + * @author Andy Clement + */ +public final class ModuleMainClass extends Attribute { + + private int mainClassIndex; + + public ModuleMainClass(ModuleMainClass c) { + this(c.getNameIndex(), c.getLength(), c.getMainClassIndex(), c.getConstantPool()); + } + + public ModuleMainClass(int nameIndex, int length, int mainClassIndex, ConstantPool cp) { + super(Constants.ATTR_MODULE_MAIN_CLASS, nameIndex, length, cp); + this.mainClassIndex = mainClassIndex; + } + + ModuleMainClass(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException { + this(nameIndex, length, 0, cp); + this.mainClassIndex = stream.readUnsignedShort(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitModuleMainClass(this); + } + + @Override + public final void dump(DataOutputStream stream) throws IOException { + super.dump(stream); + stream.writeShort(mainClassIndex); + } + + public final int getMainClassIndex() { + return mainClassIndex; + } + + @Override + public final String toString() { + return cpool.getConstantString_CONSTANTClass(mainClassIndex); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModulePackages.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModulePackages.java new file mode 100644 index 000000000..37da4bc47 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/ModulePackages.java @@ -0,0 +1,126 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2017 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Indicates all the packages of a module that are exported or opened by the module attribute. + * http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jvms-diffs.pdf 4.7.26 + * + * @author Andy Clement + */ +public final class ModulePackages extends Attribute { + + private static int[] NO_PACKAGES = new int[0]; + private int[] packageIndices; + + public ModulePackages(ModulePackages c) { + this(c.getNameIndex(), c.getLength(), c.getPackageIndices(), c.getConstantPool()); + } + + public ModulePackages(int nameIndex, int length, int[] packageIndices, ConstantPool cp) { + super(Constants.ATTR_MODULE_PACKAGES, nameIndex, length, cp); + setPackageIndices(packageIndices); + } + + ModulePackages(int nameIndex, int length, DataInputStream stream, ConstantPool cp) throws IOException { + this(nameIndex, length, (int[]) null, cp); + int packageIndicesCount = stream.readUnsignedShort(); + packageIndices = new int[packageIndicesCount]; + for (int i = 0; i < packageIndicesCount; i++) { + packageIndices[i] = stream.readUnsignedShort(); + } + } + + @Override + public void accept(ClassVisitor v) { + v.visitModulePackages(this); + } + + @Override + public final void dump(DataOutputStream stream) throws IOException { + super.dump(stream); + stream.writeShort(packageIndices.length); + for (int i = 0; i < packageIndices.length; i++) { + stream.writeShort(packageIndices[i]); + } + } + + public final int[] getPackageIndices() { + return packageIndices; + } + + public final void setPackageIndices(int[] packageIndices) { + if (packageIndices == null) { + this.packageIndices = NO_PACKAGES; + } else { + this.packageIndices = packageIndices; + } + } + + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < packageIndices.length; i++) { + buf.append(cpool.getPackageName(packageIndices[i]) + "\n"); + } + return buf.toString(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestHost.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestHost.java new file mode 100644 index 000000000..52d312659 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestHost.java @@ -0,0 +1,118 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.28 + * + * @see Attribute + */ +public final class NestHost extends Attribute { + private int hostClassIndex; + + public NestHost(NestHost c) { + this(c.getNameIndex(), c.getLength(), c.getHostClassIndex(), c.getConstantPool()); + } + + public NestHost(int nameIndex, int length, int hostClassIndex, ConstantPool cp) { + super(Constants.ATTR_NEST_MEMBERS, nameIndex, length, cp); + this.hostClassIndex = hostClassIndex; + } + + NestHost(int nameIndex, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + this(nameIndex, length, 0, constant_pool); + hostClassIndex = file.readUnsignedShort(); + } + + @Override + public void accept(ClassVisitor v) { + v.visitNestHost(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(hostClassIndex); + } + + public final int getHostClassIndex() { + return hostClassIndex; + } + + public final void setHostClassIndex(int hostClassIndex) { + this.hostClassIndex = hostClassIndex; + } + + public final String getHostClassName() { + ConstantClass constantClass = (ConstantClass)cpool.getConstant(hostClassIndex,Constants.CONSTANT_Class); + return constantClass.getClassname(cpool); + } + + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("NestHost("); + ConstantClass constantClass = (ConstantClass)cpool.getConstant(hostClassIndex,Constants.CONSTANT_Class); + buf.append(constantClass.getClassname(cpool)); + buf.append(")"); + return buf.toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestMembers.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestMembers.java new file mode 100644 index 000000000..9d273966f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/NestMembers.java @@ -0,0 +1,131 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.29 + * + * @see Attribute + */ +public final class NestMembers extends Attribute { + private int numberOfClasses; + private int[] classes; // CONSTANT_Class_info references + + public NestMembers(NestMembers c) { + this(c.getNameIndex(), c.getLength(), c.getClasses(), c.getConstantPool()); + } + + public NestMembers(int nameIndex, int length, int[] classes, ConstantPool cp) { + super(Constants.ATTR_NEST_MEMBERS, nameIndex, length, cp); + setClasses(classes); + } + + NestMembers(int nameIndex, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + this(nameIndex, length, (int[]) null, constant_pool); + numberOfClasses = file.readUnsignedShort(); + classes = new int[numberOfClasses]; + for (int i = 0; i < numberOfClasses; i++) { + classes[i] = file.readUnsignedShort(); + } + } + + @Override + public void accept(ClassVisitor v) { + v.visitNestMembers(this); + } + + @Override + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(numberOfClasses); + for (int i = 0; i < numberOfClasses; i++) { + file.writeShort(classes[i]); + } + } + + public final int[] getClasses() { + return classes; + } + + public final void setClasses(int[] inner_classes) { + this.classes = inner_classes; + numberOfClasses = (inner_classes == null) ? 0 : inner_classes.length; + } + + public final String[] getClassesNames() { + String[] result = new String[numberOfClasses]; + for (int i = 0; i < numberOfClasses; i++) { + ConstantClass constantClass = (ConstantClass)cpool.getConstant(classes[i],Constants.CONSTANT_Class); + result[i] = constantClass.getClassname(cpool); + } + return result; + } + + @Override + public final String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < numberOfClasses; i++) { + ConstantClass constantClass = (ConstantClass)cpool.getConstant(classes[i],Constants.CONSTANT_Class); + buf.append(constantClass.getClassname(cpool)).append(" "); + } + return "NestMembers("+buf.toString().trim()+")"; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Node.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Node.java new file mode 100644 index 000000000..5bef82979 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Node.java @@ -0,0 +1,65 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * Denote class to have an accept method(); + * + * @version $Id: Node.java,v 1.3 2008/05/28 23:53:01 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public interface Node { + public void accept(ClassVisitor obj); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Signature.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Signature.java new file mode 100644 index 000000000..b7488e9a4 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Signature.java @@ -0,0 +1,310 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + * Extended by Adrian Colyer, June 2005 to support unpacking of Signature + * attribute + */ + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * This class is derived from <em>Attribute</em> and represents a reference to a <href="http://wwwipd.ira.uka.de/~pizza/gj/">GJ</a> + * attribute. + * + * @version $Id: Signature.java,v 1.11 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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, DataInputStream 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 constant_pool Array of constants + * @param Signature_index Index in constant pool to CONSTANT_Utf8 + */ + 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 + */ + @Override + public void accept(ClassVisitor 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 + */ + @Override + 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. + */ + public final void setSignatureIndex(int signature_index) { + this.signature_index = signature_index; + } + + /** + * @return GJ signature. + */ + public final String getSignature() { + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(signature_index, Constants.CONSTANT_Utf8); + return c.getValue(); + } + + /** + * 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 + */ + @Override + public final String toString() { + String s = getSignature(); + + return "Signature(" + s + ")"; + } + + // /** + // * @return deep copy of this attribute + // */ + // @Override + // public Attribute copy(ConstantPool constant_pool) { + // return (Signature) clone(); + // } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SimpleConstant.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SimpleConstant.java new file mode 100644 index 000000000..84ff40cf9 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SimpleConstant.java @@ -0,0 +1,58 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.classfile; + +public interface SimpleConstant { + public String getStringValue(); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SourceFile.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SourceFile.java new file mode 100644 index 000000000..9fd840fc0 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/SourceFile.java @@ -0,0 +1,169 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: SourceFile.java,v 1.5 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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, DataInputStream 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitSourceFile(this); + } + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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) cpool.getConstant(sourcefile_index, Constants.CONSTANT_Utf8); + return c.getValue(); + } + + /** + * @return String representation + */ + @Override + public final String toString() { + return "SourceFile(" + getSourceFileName() + ")"; + } + + /** + * @return deep copy of this attribute // + */ + // @Override + // public Attribute copy(ConstantPool constant_pool) { + // return (SourceFile) clone(); + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMap.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMap.java new file mode 100644 index 000000000..29f9c1535 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMap.java @@ -0,0 +1,190 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: StackMap.java,v 1.6 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Code + * @see StackMapEntry + * @see StackMapType + */ +public final class StackMap extends Attribute { + 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 + * @throws IOException + * @param constant_pool Array of constants + */ + 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 + */ + @Override + 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. + */ + @Override + 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.cpool = 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitStackMap(this); + } + + public final int getMapLength() { + return map_length; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapEntry.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapEntry.java new file mode 100644 index 000000000..76bb2ab79 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapEntry.java @@ -0,0 +1,210 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +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: StackMapEntry.java,v 1.5 2008/05/28 23:53:02 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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("(offset=" + 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(ClassVisitor 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapType.java new file mode 100644 index 000000000..b1116abbe --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/StackMapType.java @@ -0,0 +1,172 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.Constants; +import java.io.*; + +/** + * This class represents the type of a local variable or item on stack + * used in the StackMap entries. + * + * @version $Id: StackMapType.java,v 1.3 2008/05/28 23:53:02 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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(DataInputStream 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) + 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Synthetic.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Synthetic.java new file mode 100644 index 000000000..57fe97468 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Synthetic.java @@ -0,0 +1,185 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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: Synthetic.java,v 1.5 2009/09/15 19:40:12 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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()); + } + + // + // public Synthetic(ConstantPoolGen cpool) { + // super(Constants.ATTR_SYNTHETIC, cpool.addUtf8("Synthetic"), 0, cpool); + // ConstantPoolGen cpg = myGen.getConstantPool(); + // int index = ; + // Attribute synthetic = new Synthetic(index, 0, new byte[0], cpg.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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitSynthetic(this); + } + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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. + */ + @Override + public final String toString() { + StringBuffer buf = new StringBuffer("Synthetic"); + + if (length > 0) + buf.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 = (byte[])bytes.clone(); + // + // c.cpool = constant_pool; + // return c; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Unknown.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Unknown.java new file mode 100644 index 000000000..416d105b1 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Unknown.java @@ -0,0 +1,215 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.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.aspectj.apache.bcel.classfile.AttributeReader)">Attribute.addAttributeReader</a>. + * + * + * @version $Id: Unknown.java,v 1.6 2009/09/15 19:40:12 aclement Exp $ + * @see org.aspectj.apache.bcel.classfile.Attribute + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class Unknown extends Attribute { + private byte[] bytes; + private String name; + + // evil static - removed by Andy C - no apparent users (4 Mar 06) + // private static HashMap 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)).getValue(); + // 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 + */ + @Override + public void accept(ClassVisitor v) { + v.visitUnknown(this); + } + + /** + * Dump unknown bytes to file stream. + * + * @param file Output file stream + * @throws IOException + */ + @Override + 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. + */ + @Override + public String getName() { + return name; + } + + /** + * @param bytes. + */ + public final void setBytes(byte[] bytes) { + this.bytes = bytes; + } + + /** + * @return String representation. + */ + @Override + 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 + */ + // @Override + // public Attribute copy(ConstantPool constant_pool) { + // Unknown c = (Unknown) clone(); + // + // if (bytes != null) + // c.bytes = bytes.clone(); + // + // c.cpool = constant_pool; + // return c; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Utility.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Utility.java new file mode 100644 index 000000000..98f5952ae --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/Utility.java @@ -0,0 +1,1094 @@ +package org.aspectj.apache.bcel.classfile; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeParamAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos; +import org.aspectj.apache.bcel.generic.Type; +import org.aspectj.apache.bcel.util.ByteSequence; + +/** + * Utility functions that do not really belong to any class in particular. + * + * @version $Id: Utility.java,v 1.14 2009/09/28 16:39:46 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * + * modified: Andy Clement 2-mar-05 Removed unnecessary static and optimized + */ +public abstract class Utility { + + /* + * 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. + */ + private static boolean wide = false; + + /** + * 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: see comment at top of class... + 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++) { + // Skip `index' lines of code + 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 + codeToString(stream, constant_pool, verbose) + '\n'); + } + } + } catch (IOException e) { + System.out.println(buf.toString()); + e.printStackTrace(); + throw new ClassFormatException("Byte code error: " + e); + } + + return buf.toString(); + } + + /** + * Disassemble a stream of byte codes and return the string representation. + */ + public static final String codeToString(byte[] code, ConstantPool constant_pool, int index, int length) { + return codeToString(code, constant_pool, index, length, true); + } + + 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) { + str = str.replace('/', '.'); + if (chopit) { + int len = prefix.length(); + // If string starts with 'prefix' and contains no further dots + if (str.startsWith(prefix)) { + String result = str.substring(len); + if (result.indexOf('.') == -1) { + str = result; + } + } + } + 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); + } + + 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); + } + + /** + * 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. + */ + 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) != ')') { + ResultHolder rh = signatureToStringInternal(signature.substring(index), chopit); + String param_type = rh.getResult(); + buf.append(param_type); + + if (vars != null) { + LocalVariable l = vars.getLocalVariable(var_index); + + if (l != null) { + buf.append(" " + l.getName()); + } + } else { + buf.append(" arg" + var_index); + } + + if ("double".equals(param_type) || "long".equals(param_type)) { + var_index += 2; + } else { + var_index++; + } + + buf.append(", "); + index += rh.getConsumedChars(); + } + + index++; + + // Read return type after `)' + type = signatureToString(signature.substring(index), chopit); + + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature); + } + + 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(); + } + + /** + * Replace all occurences 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; + StringBuffer buf = new StringBuffer(); + + try { + index = str.indexOf(old); + if (index != -1) { + old_index = 0; + + // 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) { + 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); + } + + public static final String signatureToString(String signature, boolean chopit) { + ResultHolder rh = signatureToStringInternal(signature, chopit); + return rh.getResult(); + } + + /** + * This method converts this string into a Java type declaration such as 'String[]' and throws a `ClassFormatException' when the + * parsed type is invalid. + */ + public static final ResultHolder signatureToStringInternal(String signature, boolean chopit) { + int processedChars = 1; // This is the default, read just one char + try { + switch (signature.charAt(0)) { + case 'B': + return ResultHolder.BYTE; + case 'C': + return ResultHolder.CHAR; + case 'D': + return ResultHolder.DOUBLE; + case 'F': + return ResultHolder.FLOAT; + case 'I': + return ResultHolder.INT; + case 'J': + return ResultHolder.LONG; + case 'L': { // Full class name + int index = signature.indexOf(';'); // Look for closing ';' + + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + + if (signature.length() > index + 1 && signature.charAt(index + 1) == '>') { + index = index + 2; + } + + int genericStart = signature.indexOf('<'); + if (genericStart != -1) { + int genericEnd = signature.indexOf('>'); + // FIXME asc going to need a lot more work in here for generics + ResultHolder rh = signatureToStringInternal(signature.substring(genericStart + 1, genericEnd), chopit); + StringBuffer sb = new StringBuffer(); + sb.append(signature.substring(1, genericStart)); + sb.append("<").append(rh.getResult()).append(">"); + ResultHolder retval = new ResultHolder(compactClassName(sb.toString(), chopit), genericEnd + 1); + return retval; + } else { + processedChars = index + 1; // "Lblabla;" `L' and `;' are removed + ResultHolder retval = new ResultHolder(compactClassName(signature.substring(1, index), chopit), processedChars); + return retval; + } + } + + case 'S': + return ResultHolder.SHORT; + case 'Z': + return ResultHolder.BOOLEAN; + + case '[': { // Array declaration + StringBuffer brackets; + int consumedChars, n; + + brackets = new StringBuffer(); // Accumulate []'s + // Count opening brackets and look for optional size argument + for (n = 0; signature.charAt(n) == '['; n++) { + brackets.append("[]"); + } + consumedChars = n; + ResultHolder restOfIt = signatureToStringInternal(signature.substring(n), chopit); + consumedChars += restOfIt.getConsumedChars(); + brackets.insert(0, restOfIt.getResult()); + return new ResultHolder(brackets.toString(), consumedChars); + } + case 'V': + return ResultHolder.VOID; + + default: + throw new ClassFormatException("Invalid signature: `" + signature + "'"); + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid signature: " + e + ":" + signature); + } + } + + /** + * 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); + } + } + + /** + * 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); + + // Just one digit, so prepend 0 + 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); + } else { + return new String(buf) + str; + } + } + + /** + * 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 annotations A list of AnnotationGen objects + */ + public static Collection<RuntimeAnnos> getAnnotationAttributes(ConstantPool cp, List<AnnotationGen> annotations) { + + if (annotations.size() == 0) { + return null; + } + + try { + int countVisible = 0; + int countInvisible = 0; + + // put the annotations in the right output stream + for (AnnotationGen a : annotations) { + 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 (AnnotationGen a : annotations) { + 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<RuntimeAnnos> newAttributes = new ArrayList<RuntimeAnnos>(); + if (rvaData.length > 2) { + newAttributes.add(new RuntimeVisAnnos(rvaIndex, rvaData.length, rvaData, cp)); + } + if (riaData.length > 2) { + newAttributes.add(new RuntimeInvisAnnos(riaIndex, riaData.length, riaData, cp)); + } + + return newAttributes; + } 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 + */ + // OPTIMIZE looks heavyweight? + public static Attribute[] getParameterAnnotationAttributes(ConstantPool cp, List<AnnotationGen>[] 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<AnnotationGen> l = vec[i]; + if (l != null) { + for (AnnotationGen element : l) { + 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<AnnotationGen> l = vec[i]; + for (AnnotationGen element : l) { + 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<AnnotationGen> l = vec[i]; + for (AnnotationGen element : l) { + 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<RuntimeParamAnnos> newAttributes = new ArrayList<RuntimeParamAnnos>(); + + if (totalVisCount > 0) { + newAttributes.add(new RuntimeVisParamAnnos(rvaIndex, rvaData.length, rvaData, cp)); + } + + if (totalInvisCount > 0) { + newAttributes.add(new RuntimeInvisParamAnnos(riaIndex, riaData.length, riaData, cp)); + } + + return newAttributes.toArray(new Attribute[] {}); + } catch (IOException e) { + System.err.println("IOException whilst processing parameter annotations"); + e.printStackTrace(); + } + return null; + } + + public static class ResultHolder { + private String result; + private int consumed; + + public static final ResultHolder BYTE = new ResultHolder("byte", 1); + public static final ResultHolder CHAR = new ResultHolder("char", 1); + public static final ResultHolder DOUBLE = new ResultHolder("double", 1); + public static final ResultHolder FLOAT = new ResultHolder("float", 1); + public static final ResultHolder INT = new ResultHolder("int", 1); + public static final ResultHolder LONG = new ResultHolder("long", 1); + public static final ResultHolder SHORT = new ResultHolder("short", 1); + public static final ResultHolder BOOLEAN = new ResultHolder("boolean", 1); + public static final ResultHolder VOID = new ResultHolder("void", 1); + + public ResultHolder(String s, int c) { + result = s; + consumed = c; + } + + public String getResult() { + return result; + } + + public int getConsumedChars() { + return consumed; + } + } + + /** + * 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); + } + } + + public static final byte typeOfSignature(char c) throws ClassFormatException { + switch (c) { + 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 type of signature: " + c); + } + } + + /** + * 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 = bytes.readByte(); + if (b != 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 = " + default_offset + ", low = " + low + ", high = " + high + "("); + + 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 = " + default_offset + ", npairs = " + npairs + " ("); + + for (int i = 0; i < npairs; i++) { + match[i] = bytes.readInt(); + jump_table[i] = offset + bytes.readInt(); + buf.append("(" + match[i] + ", " + jump_table[i] + ")"); + 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#" + ((bytes.getIndex() - 1) + bytes.readShort())); + break; + + // 32-bit wide jumps + case Constants.GOTO_W: + case Constants.JSR_W: + buf.append("\t\t#" + ((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%" + 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<" + Constants.TYPE_NAMES[bytes.readByte()] + ">"); + break; + + // Access object/class fields + case Constants.GETFIELD: + case Constants.GETSTATIC: + case Constants.PUTFIELD: + case Constants.PUTSTATIC: + index = bytes.readUnsignedShort(); + buf.append("\t\t" + constant_pool.constantToString(index, Constants.CONSTANT_Fieldref) + + (verbose ? " (" + index + ")" : "")); + break; + + // Operands are references to classes in constant pool + case Constants.NEW: + case Constants.CHECKCAST: + buf.append("\t"); + case Constants.INSTANCEOF: + index = bytes.readUnsignedShort(); + buf.append("\t<" + constant_pool.constantToString(index) + ">" + (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" + constant_pool.constantToString(index) + (verbose ? " (" + index + ")" : "")); + break; + + case Constants.INVOKEINTERFACE: + index = bytes.readUnsignedShort(); + int nargs = bytes.readUnsignedByte(); // historical, redundant + buf.append("\t" + constant_pool.constantToString(index) + (verbose ? " (" + index + ")\t" : "") + nargs + "\t" + + bytes.readUnsignedByte()); // Last byte is a reserved + // space + break; + + case Constants.INVOKEDYNAMIC://http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokedynamic + index = bytes.readUnsignedShort(); + bytes.readUnsignedShort(); // zeroes + buf.append("\t" + constant_pool.constantToString(index) + (verbose ? " (" + index + ")" : "")); + break; + + // Operands are references to items in constant pool + case Constants.LDC_W: + case Constants.LDC2_W: + index = bytes.readUnsignedShort(); + buf.append("\t\t" + constant_pool.constantToString(index) + (verbose ? " (" + index + ")" : "")); + break; + + case Constants.LDC: + index = bytes.readUnsignedByte(); + buf.append("\t\t" + constant_pool.constantToString(index) + (verbose ? " (" + index + ")" : "")); + break; + + // Array of references + case Constants.ANEWARRAY: + index = bytes.readUnsignedShort(); + buf.append("\t\t<" + compactClassName(constant_pool.getConstantString(index, Constants.CONSTANT_Class), false) + ">" + + (verbose ? " (" + index + ")" : "")); + break; + + // Multidimensional array of references + case Constants.MULTIANEWARRAY: { + index = bytes.readUnsignedShort(); + int dimensions = bytes.readUnsignedByte(); + + buf.append("\t<" + compactClassName(constant_pool.getConstantString(index, Constants.CONSTANT_Class), false) + ">\t" + + dimensions + (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%" + vindex + "\t" + constant); + break; + + default: + if ((Constants.iLen[opcode] - 1) > 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(); + } + + // private helpers + private static final int pow2(int n) { + return 1 << n; + } + + /** + * Convert type to Java method signature, e.g. int[] f(java.lang.String x) becomes (Ljava/lang/String;)[I + * + * @param returnType what the method returns + * @param argTypes what are the argument types + * @return method signature for given type(s). + */ + public static String toMethodSignature(Type returnType, Type[] argTypes) { + StringBuffer buf = new StringBuffer("("); + int length = (argTypes == null) ? 0 : argTypes.length; + for (int i = 0; i < length; i++) { + buf.append(argTypes[i].getSignature()); + } + buf.append(')'); + buf.append(returnType.getSignature()); + return buf.toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationElementValue.java new file mode 100644 index 000000000..2e6024580 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationElementValue.java @@ -0,0 +1,73 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; + +public class AnnotationElementValue extends ElementValue { + + private AnnotationGen a; + + public AnnotationElementValue(AnnotationGen a, ConstantPool cpool) { + super(ANNOTATION, cpool); + this.a = a; + } + + public AnnotationElementValue(int type, AnnotationGen annotation, ConstantPool cpool) { + super(type, cpool); + assert type == ANNOTATION; + this.a = annotation; + } + + public AnnotationElementValue(AnnotationElementValue value, ConstantPool cpool, boolean copyPoolEntries) { + super(ANNOTATION, cpool); + a = new AnnotationGen(value.getAnnotation(), cpool, copyPoolEntries); + } + + @Override + public void dump(DataOutputStream dos) throws IOException { + dos.writeByte(type); // u1 type of value (ANNOTATION == '@') + a.dump(dos); + } + + @Override + public String stringifyValue() { + StringBuffer sb = new StringBuffer(); + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(a.getTypeIndex(), Constants.CONSTANT_Utf8); + sb.append(cu8.getValue()); + // haven't really tested this values section: + List<NameValuePair> pairs = a.getValues(); + if (pairs != null && pairs.size() > 0) { + sb.append("("); + for (int p = 0; p < pairs.size(); p++) { + if (p > 0) { + sb.append(","); + } + sb.append(pairs.get(p).getNameString()).append("=").append(pairs.get(p).getValue().stringifyValue()); + } + sb.append(")"); + } + return sb.toString(); + } + + public AnnotationGen getAnnotation() { + return a; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java new file mode 100644 index 000000000..9a0a42909 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/AnnotationGen.java @@ -0,0 +1,176 @@ +/* ******************************************************************* + * Copyright (c) 2004, 2013 IBM Corporation + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; +import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.generic.ObjectType; + +public class AnnotationGen { + public static final AnnotationGen[] NO_ANNOTATIONS = new AnnotationGen[0]; + + private int typeIndex; + private List<NameValuePair> pairs = Collections.emptyList(); + private ConstantPool cpool; + private boolean isRuntimeVisible = false; + + public AnnotationGen(AnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) { + this.cpool = cpool; + if (copyPoolEntries) { + typeIndex = cpool.addUtf8(a.getTypeSignature()); + } else { + typeIndex = a.getTypeIndex(); + } + isRuntimeVisible = a.isRuntimeVisible(); + pairs = copyValues(a.getValues(), cpool, copyPoolEntries); + } + + private List<NameValuePair> copyValues(List<NameValuePair> in, ConstantPool cpool, boolean copyPoolEntries) { + List<NameValuePair> out = new ArrayList<NameValuePair>(); + for (NameValuePair nvp : in) { + out.add(new NameValuePair(nvp, cpool, copyPoolEntries)); + } + return out; + } + + private AnnotationGen(ConstantPool cpool) { + this.cpool = cpool; + } + + /** + * Retrieve an immutable version of this AnnotationGen + */ + public AnnotationGen(ObjectType type, List<NameValuePair> pairs, boolean runtimeVisible, ConstantPool cpool) { + this.cpool = cpool; + if (type != null) { + this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects + } + this.pairs = pairs; + isRuntimeVisible = runtimeVisible; + } + + public static AnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean b) throws IOException { + AnnotationGen a = new AnnotationGen(cpool); + a.typeIndex = dis.readUnsignedShort(); + int elemValuePairCount = dis.readUnsignedShort(); + for (int i = 0; i < elemValuePairCount; i++) { + int nidx = dis.readUnsignedShort(); + a.addElementNameValuePair(new NameValuePair(nidx, ElementValue.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(pairs.size()); // u2 element_value pair count + for (int i = 0; i < pairs.size(); i++) { + NameValuePair envp = pairs.get(i); + envp.dump(dos); + } + } + + public void addElementNameValuePair(NameValuePair evp) { + if (pairs == Collections.EMPTY_LIST) { + pairs = new ArrayList<NameValuePair>(); + } + pairs.add(evp); + } + + public int getTypeIndex() { + return typeIndex; + } + + public String getTypeSignature() { + ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex); + return utf8.getValue(); + } + + public String getTypeName() { + return Utility.signatureToString(getTypeSignature()); + } + + public List<NameValuePair> getValues() { + return pairs; + } + + @Override + public String toString() { + StringBuffer s = new StringBuffer(); + s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {"); + for (int i = 0; i < pairs.size(); i++) { + s.append(pairs.get(i)); + if (i + 1 < pairs.size()) + s.append(","); + } + s.append("}]"); + return s.toString(); + } + + public String toShortString() { + StringBuffer s = new StringBuffer(); + s.append("@").append(getTypeName()); + if (pairs.size()!=0) { + s.append("("); + for (int i = 0; i < pairs.size(); i++) { + s.append(pairs.get(i)); + if (i + 1 < pairs.size()) + s.append(","); + } + s.append(")"); + } + return s.toString(); + } + + private void isRuntimeVisible(boolean b) { + isRuntimeVisible = b; + } + + public boolean isRuntimeVisible() { + return isRuntimeVisible; + } + + /** + * @return true if the annotation has a value with the specified name and (toString'd) value + */ + public boolean hasNameValuePair(String name, String value) { + for (NameValuePair pair : pairs) { + if (pair.getNameString().equals(name)) { + if (pair.getValue().stringifyValue().equals(value)) { + return true; + } + } + } + return false; + } + + /** + * @return true if the annotation has a value with the specified name + */ + public boolean hasNamedValue(String name) { + for (NameValuePair pair : pairs) { + if (pair.getNameString().equals(name)) { + return true; + } + } + return false; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ArrayElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ArrayElementValue.java new file mode 100644 index 000000000..3dd19af71 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ArrayElementValue.java @@ -0,0 +1,84 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public class ArrayElementValue extends ElementValue { + private static final ElementValue[] NO_VALUES = new ElementValue[0]; + + // J5TODO: Should we make this an array or a list? A list would be easier to modify ... + private ElementValue[] evalues = NO_VALUES; + + public ElementValue[] getElementValuesArray() { + return evalues; + } + + public int getElementValuesArraySize() { + return evalues.length; + } + + public ArrayElementValue(ConstantPool cp) { + super(ARRAY, cp); + } + + 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"); + this.evalues = datums; + } + + public ArrayElementValue(ArrayElementValue value, ConstantPool cpool, boolean copyPoolEntries) { + super(ARRAY, cpool); + evalues = new ElementValue[value.getElementValuesArraySize()]; + ElementValue[] in = value.getElementValuesArray(); + for (int i = 0; i < in.length; i++) { + evalues[i] = ElementValue.copy(in[i], cpool, copyPoolEntries); + } + } + + @Override + 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); + } + } + + @Override + public String stringifyValue() { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < evalues.length; i++) { + ElementValue element = evalues[i]; + sb.append(element.stringifyValue()); + if ((i + 1) < evalues.length) + sb.append(","); + } + sb.append("]"); + return sb.toString(); + } + + public void addElement(ElementValue gen) { + ElementValue[] old = evalues; + evalues = new ElementValue[evalues.length + 1]; + System.arraycopy(old, 0, evalues, 0, old.length); + evalues[old.length] = gen; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ClassElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ClassElementValue.java new file mode 100644 index 000000000..a4e18b6d4 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ClassElementValue.java @@ -0,0 +1,79 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; +import org.aspectj.apache.bcel.generic.ObjectType; + +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; + + protected ClassElementValue(int typeIdx, ConstantPool cpool) { + super(ElementValue.CLASS, cpool); + this.idx = typeIdx; + } + + public ClassElementValue(ObjectType t, ConstantPool cpool) { + super(ElementValue.CLASS, cpool); + // this.idx = cpool.addClass(t); + idx = cpool.addUtf8(t.getSignature()); + } + + /** + * Return immutable variant of this ClassElementValueGen + */ + // public ElementValueGen getElementValue() { + // return new ClassElementValueGen(type,idx,cpGen); + // } + public ClassElementValue(ClassElementValue value, ConstantPool 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.getValue(); + // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx); + // ConstantUtf8 utf8 = (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex()); + // return utf8.getBytes(); + } + + @Override + public String stringifyValue() { + return getClassString(); + } + + @Override + public void dump(DataOutputStream dos) throws IOException { + dos.writeByte(type); // u1 kind of value + dos.writeShort(idx); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java new file mode 100644 index 000000000..06f7c7273 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/ElementValue.java @@ -0,0 +1,135 @@ +/* ******************************************************************* + * Copyright (c) 2004, 2013 IBM, VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public abstract class ElementValue { + + 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'; + + protected int type; + protected ConstantPool cpool; + + 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 ElementValue readElementValue(DataInputStream dis, ConstantPool cpGen) throws IOException { + int type = dis.readUnsignedByte(); + switch (type) { + case 'B': // byte + return new SimpleElementValue(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen); + case 'C': // char + return new SimpleElementValue(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen); + case 'D': // double + return new SimpleElementValue(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen); + case 'F': // float + return new SimpleElementValue(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen); + case 'I': // int + return new SimpleElementValue(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen); + case 'J': // long + return new SimpleElementValue(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen); + case 'S': // short + return new SimpleElementValue(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen); + case 'Z': // boolean + return new SimpleElementValue(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen); + case 's': // String + return new SimpleElementValue(STRING, dis.readUnsignedShort(), cpGen); + + case 'e': // Enum constant + return new EnumElementValue(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen); + + case 'c': // Class + return new ClassElementValue(dis.readUnsignedShort(), cpGen); + + // FIXME should this be true here? or should it be the value for the containing annotation? + case '@': // Annotation + return new AnnotationElementValue(ANNOTATION, AnnotationGen.read(dis, cpGen, true), 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); + } + return new ArrayElementValue(ARRAY, evalues, cpGen); + + default: + throw new RuntimeException("Unexpected element value kind in annotation: " + type); + } + } + + protected ConstantPool getConstantPool() { + return cpool; + } + + /** + * Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct. + */ + public static ElementValue copy(ElementValue value, ConstantPool 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 SimpleElementValue((SimpleElementValue) value, cpool, copyPoolEntries); + + case 'e': // Enum constant + return new EnumElementValue((EnumElementValue) value, cpool, copyPoolEntries); + + case '@': // Annotation + return new AnnotationElementValue((AnnotationElementValue) value, cpool, copyPoolEntries); + + case '[': // Array + return new ArrayElementValue((ArrayElementValue) value, cpool, copyPoolEntries); + + case 'c': // Class + return new ClassElementValue((ClassElementValue) value, cpool, copyPoolEntries); + + default: + throw new RuntimeException("Not implemented yet! (" + value.getElementValueType() + ")"); + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/EnumElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/EnumElementValue.java new file mode 100644 index 000000000..a8b219774 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/EnumElementValue.java @@ -0,0 +1,116 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; +import org.aspectj.apache.bcel.generic.ObjectType; + +public class EnumElementValue extends ElementValue { + + // 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 EnumElementValue(int typeIdx, int valueIdx, ConstantPool cpool) { + super(ElementValue.ENUM_CONSTANT, cpool); + if (type != ENUM_CONSTANT) { + throw new RuntimeException("Only element values of type enum can be built with this ctor"); + } + this.typeIdx = typeIdx; + this.valueIdx = valueIdx; + } + + // /** + // * Return immutable variant of this EnumElementValue + // */ + // public ElementValueGen getElementValue() { + // System.err.println("Duplicating value: "+getEnumTypeString()+":"+getEnumValueString()); + // return new EnumElementValueGen(type,typeIdx,valueIdx,cpGen); + // } + + public EnumElementValue(ObjectType t, String value, ConstantPool cpool) { + super(ElementValue.ENUM_CONSTANT, cpool); + typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t); + valueIdx = cpool.addUtf8(value);// was addString(value); + } + + public EnumElementValue(EnumElementValue value, ConstantPool 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(); + } + } + + @Override + 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 + } + + /** + * return signature and value, something like Lp/Color;RED + */ + @Override + public String stringifyValue() { + StringBuffer sb = new StringBuffer(); + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(typeIdx, Constants.CONSTANT_Utf8); + sb.append(cu8.getValue()); + cu8 = (ConstantUtf8) cpool.getConstant(valueIdx, Constants.CONSTANT_Utf8); + sb.append(cu8.getValue()); + return sb.toString(); + } + + public String toString() { + StringBuilder s = new StringBuilder("E("); + s.append(getEnumTypeString()).append(" ").append(getEnumValueString()).append(")"); + return s.toString(); + } + + // 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)).getValue(); + // return Utility.signatureToString(cu8.getBytes()); + } + + public String getEnumValueString() { + return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getValue(); + // ConstantString cu8 = (ConstantString)getConstantPool().getConstant(valueIdx); + // return ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + } + + public int getValueIndex() { + return valueIdx; + } + + public int getTypeIndex() { + return typeIdx; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/NameValuePair.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/NameValuePair.java new file mode 100644 index 000000000..99b4211ec --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/NameValuePair.java @@ -0,0 +1,75 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public class NameValuePair { + private int nameIdx; + private ElementValue value; + private ConstantPool cpool; + + public NameValuePair(NameValuePair pair, ConstantPool 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(pair.getNameString()); + } else { + nameIdx = pair.getNameIndex(); + } + value = ElementValue.copy(pair.getValue(), cpool, copyPoolEntries); + } + + protected NameValuePair(int idx, ElementValue value, ConstantPool cpool) { + this.nameIdx = idx; + this.value = value; + this.cpool = cpool; + } + + public NameValuePair(String name, ElementValue value, ConstantPool 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() { + return cpool.getConstantUtf8(nameIdx).getValue(); + } + + public final ElementValue getValue() { + return value; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(getNameString()).append("=").append(value.stringifyValue()); + return sb.toString(); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnos.java new file mode 100644 index 000000000..ac145087b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeAnnos.java @@ -0,0 +1,98 @@ +/* ******************************************************************* + * Copyright (c) 2004, 2013 IBM, VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.ByteArrayInputStream; +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.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public abstract class RuntimeAnnos extends Attribute { + + private List<AnnotationGen> annotations; + private boolean visible; + + // Keep just a byte stream of the data until someone actually asks for it + private boolean inflated = false; + private byte[] annotation_data; + + public RuntimeAnnos(byte attrid, boolean visible, int nameIdx, int len, ConstantPool cpool) { + super(attrid, nameIdx, len, cpool); + this.visible = visible; + annotations = new ArrayList<AnnotationGen>(); + } + + public RuntimeAnnos(byte attrid, boolean visible, int nameIdx, int len, byte[] data, ConstantPool cpool) { + super(attrid, nameIdx, len, cpool); + this.visible = visible; + annotations = new ArrayList<AnnotationGen>(); + annotation_data = data; + } + + public List<AnnotationGen> getAnnotations() { + if (!inflated) + inflate(); + return annotations; + } + + public boolean areVisible() { + return visible; + } + + protected void readAnnotations(DataInputStream dis, ConstantPool cpool) throws IOException { + annotation_data = new byte[length]; + dis.readFully(annotation_data, 0, length); + } + + protected void writeAnnotations(DataOutputStream dos) throws IOException { + if (!inflated) { + dos.write(annotation_data, 0, length); + } else { + dos.writeShort(annotations.size()); + for (Iterator<AnnotationGen> i = annotations.iterator(); i.hasNext();) { + AnnotationGen ann = i.next(); + ann.dump(dos); + } + } + } + + + private void inflate() { + try { + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data)); + int numberOfAnnotations = dis.readUnsignedShort(); + if (numberOfAnnotations > 0) { + List<AnnotationGen> inflatedAnnotations = new ArrayList<AnnotationGen>(); + for (int i = 0; i < numberOfAnnotations; i++) { + inflatedAnnotations.add(AnnotationGen.read(dis, getConstantPool(), visible)); + } + annotations = inflatedAnnotations; + } + dis.close(); + inflated = true; + } catch (IOException ioe) { + throw new RuntimeException("Unabled to inflate annotation data, badly formed? "); + } + } + + /** FOR TESTING ONLY: Tells you if the annotations have been inflated to an object graph */ + public boolean isInflated() { + return inflated; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisAnnos.java new file mode 100644 index 000000000..a6b2e529f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisAnnos.java @@ -0,0 +1,51 @@ +/* ******************************************************************* + * Copyright (c) 2004, 2013 IBM, VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeInvisAnnos extends RuntimeAnnos { + + public RuntimeInvisAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, false, nameIdx, len, cpool); + } + + public RuntimeInvisAnnos(int nameIdx, int len, + DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readAnnotations(dis,cpool); + } + + public RuntimeInvisAnnos(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS,false,nameIndex,len,rvaData,cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeInvisibleAnnotations(this); + } + + public final void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + writeAnnotations(dos); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisParamAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisParamAnnos.java new file mode 100644 index 000000000..cb2eb8d7a --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisParamAnnos.java @@ -0,0 +1,45 @@ +/* ******************************************************************* + * Copyright (c) 2004, 2013 IBM, VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeInvisParamAnnos extends RuntimeParamAnnos { + + public RuntimeInvisParamAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, false, nameIdx, len, cpool); + } + + public RuntimeInvisParamAnnos(int nameIdx, int len, + DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readParameterAnnotations(dis,cpool); + } + + public RuntimeInvisParamAnnos(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,false,nameIndex,len,rvaData,cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeInvisibleParameterAnnotations(this); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisTypeAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisTypeAnnos.java new file mode 100644 index 000000000..333ccbddd --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeInvisTypeAnnos.java @@ -0,0 +1,36 @@ +/* ******************************************************************* + * Copyright (c) 2013 VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeInvisTypeAnnos extends RuntimeTypeAnnos { + + public RuntimeInvisTypeAnnos(int nameIdx, int len, DataInputStream dis, + ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readTypeAnnotations(dis, cpool); + } + + public RuntimeInvisTypeAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, false, nameIdx, len, cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeInvisibleTypeAnnotations(this); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeParamAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeParamAnnos.java new file mode 100644 index 000000000..517ebee62 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeParamAnnos.java @@ -0,0 +1,137 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public abstract class RuntimeParamAnnos extends Attribute { + + private List<AnnotationGen[]> parameterAnnotations; + private boolean visible; + + + // Keep just a byte stream of the data until someone actually asks for it + private boolean inflated = false; + private byte[] annotation_data; + + + public RuntimeParamAnnos(byte attrid, boolean visible, + int nameIdx, int len, ConstantPool cpool) { + super(attrid,nameIdx,len,cpool); + this.visible = visible; + parameterAnnotations = new ArrayList<AnnotationGen[]>(); + } + + public RuntimeParamAnnos(byte attrid,boolean visible,int nameIdx,int len,byte[] data,ConstantPool cpool) { + super(attrid,nameIdx,len,cpool); + this.visible = visible; + parameterAnnotations = new ArrayList<AnnotationGen[]>(); + annotation_data = data; + } + + public final void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + writeAnnotations(dos); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } + + /** Return a list of Annotation[] - each list entry contains the annotations for one parameter */ + public List /*Annotation[]*/<AnnotationGen[]> getParameterAnnotations() { + if (!inflated) inflate(); + return parameterAnnotations; + } + + public AnnotationGen[] getAnnotationsOnParameter(int parameterIndex) { + if (!inflated) inflate(); + // This may happen. In a ctor for a non static inner type the compiler + // may have added an extra parameter to the generated ctor (the parameter + // contains the instance of the outer class) - in this case + // it may appear that there are more parameters than there are entries + // in the parameter annotations array + if (parameterIndex>=parameterAnnotations.size()) { + return AnnotationGen.NO_ANNOTATIONS; + } + return parameterAnnotations.get(parameterIndex); + } + + public boolean areVisible() { + return visible; + } + + protected void readParameterAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException { + annotation_data = new byte[length]; + dis.readFully(annotation_data,0,length); + } + + private void inflate() { + try { + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data)); + int numParameters = dis.readUnsignedByte(); + if (numParameters > 0) { + List<AnnotationGen[]> inflatedParameterAnnotations = new ArrayList<AnnotationGen[]>(); + for (int i=0; i<numParameters; i++) { + int numAnnotations = dis.readUnsignedShort(); + if (numAnnotations == 0 ) { + inflatedParameterAnnotations.add(AnnotationGen.NO_ANNOTATIONS); + } else { + AnnotationGen[] annotations = new AnnotationGen[numAnnotations]; + for (int j=0; j<numAnnotations; j++) { + annotations[j] = AnnotationGen.read(dis,getConstantPool(),visible); + } + inflatedParameterAnnotations.add(annotations); + } + } + parameterAnnotations = inflatedParameterAnnotations; + } + inflated = true; + } catch (IOException ioe) { + throw new RuntimeException("Unabled to inflate annotation data, badly formed?"); + } + } + + + protected void writeAnnotations(DataOutputStream dos) throws IOException { + if (!inflated) { + dos.write(annotation_data,0,length); + } else { + dos.writeByte(parameterAnnotations.size()); + for (int i=0; i<parameterAnnotations.size(); i++) { + AnnotationGen[] annotations = parameterAnnotations.get(i); + dos.writeShort(annotations.length); + for (int j=0; j<annotations.length;j++) { + annotations[j].dump(dos); + } + } + } + } + + /** FOR TESTING ONLY: Tells you if the annotations have been inflated to an object graph */ + public boolean isInflated() { + return inflated; + } + + public String toString() { + return "Runtime"+(visible?"Visible":"Invisible")+"ParameterAnnotations ["+(inflated?"inflated":"not yet inflated")+"]"; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeTypeAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeTypeAnnos.java new file mode 100644 index 000000000..fb5c32ce1 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeTypeAnnos.java @@ -0,0 +1,105 @@ +/* ******************************************************************* + * Copyright (c) 2013 VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public abstract class RuntimeTypeAnnos extends Attribute { + + private boolean visible; + private TypeAnnotationGen[] typeAnnotations; // null until inflated + + // Keep just a byte stream of the data until someone actually asks for the information within + private byte[] annotation_data; + + public RuntimeTypeAnnos(byte attrid, boolean visible, int nameIdx, int len, ConstantPool cpool) { + super(attrid,nameIdx,len,cpool); + this.visible = visible; + } + + protected void readTypeAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException { + annotation_data = new byte[length]; + dis.readFully(annotation_data,0,length); + } + + public final void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + writeTypeAnnotations(dos); + } + + protected void writeTypeAnnotations(DataOutputStream dos) throws IOException { + if (typeAnnotations == null) { + dos.write(annotation_data,0,length); + } else { + dos.writeShort(typeAnnotations.length); + for (int i=0; i<typeAnnotations.length; i++) { + typeAnnotations[i].dump(dos); + } + } + } + +// public RuntimeTypeAnnos(byte attrid,boolean visible,int nameIdx,int len,byte[] data,ConstantPool cpool) { +// super(attrid,nameIdx,len,cpool); +// this.visible = visible; +// parameterAnnotations = new ArrayList<AnnotationGen[]>(); +// annotation_data = data; +// } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } + + public TypeAnnotationGen[] getTypeAnnotations() { + ensureInflated(); + return typeAnnotations; + } + + + public boolean areVisible() { + return visible; + } + + private void ensureInflated() { + if (typeAnnotations !=null) { + return; + } + try { + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data)); + int numTypeAnnotations = dis.readUnsignedShort(); + if (numTypeAnnotations == 0) { + typeAnnotations = TypeAnnotationGen.NO_TYPE_ANNOTATIONS; + } else { + typeAnnotations = new TypeAnnotationGen[numTypeAnnotations]; + for (int i=0; i<numTypeAnnotations; i++) { + typeAnnotations[i] = TypeAnnotationGen.read(dis,getConstantPool(),visible); + } + } + } catch (IOException ioe) { + throw new RuntimeException("Unabled to inflate type annotation data, badly formed?"); + } + } + + public String toString() { + return "Runtime"+(visible?"Visible":"Invisible")+"TypeAnnotations ["+(isInflated()?"inflated":"not yet inflated")+"]"; + } + + public boolean isInflated() { + return typeAnnotations != null; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisAnnos.java new file mode 100644 index 000000000..3b07cccc7 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisAnnos.java @@ -0,0 +1,51 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeVisAnnos extends RuntimeAnnos { + + public RuntimeVisAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, true, nameIdx, len, cpool); + } + + public RuntimeVisAnnos(int nameIdx, int len, + DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readAnnotations(dis,cpool); + } + + public RuntimeVisAnnos(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS,true,nameIndex,len,rvaData,cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeVisibleAnnotations(this); + } + + public final void dump(DataOutputStream dos) throws IOException { + super.dump(dos); + writeAnnotations(dos); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisParamAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisParamAnnos.java new file mode 100644 index 000000000..b47d8aac1 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisParamAnnos.java @@ -0,0 +1,45 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeVisParamAnnos extends RuntimeParamAnnos { + + public RuntimeVisParamAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, true, nameIdx, len, cpool); + } + + public RuntimeVisParamAnnos(int nameIndex, int len, byte[] rvaData,ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,true,nameIndex,len,rvaData,cpool); + } + + public RuntimeVisParamAnnos(int nameIdx, int len, + DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readParameterAnnotations(dis,cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeVisibleParameterAnnotations(this); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisTypeAnnos.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisTypeAnnos.java new file mode 100644 index 000000000..59b77dabc --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/RuntimeVisTypeAnnos.java @@ -0,0 +1,36 @@ +/* ******************************************************************* + * Copyright (c) 2013 VMware + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ClassVisitor; + +public class RuntimeVisTypeAnnos extends RuntimeTypeAnnos { + + public RuntimeVisTypeAnnos(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, cpool); + readTypeAnnotations(dis,cpool); + } + + public RuntimeVisTypeAnnos(int nameIdx, int len, ConstantPool cpool) { + super(Constants.ATTR_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, true, nameIdx, len, cpool); + } + + public void accept(ClassVisitor v) { + v.visitRuntimeVisibleTypeAnnotations(this); + } + +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValue.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValue.java new file mode 100644 index 000000000..2c795b136 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/SimpleElementValue.java @@ -0,0 +1,330 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial implementation {date} + * ******************************************************************/ + +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantDouble; +import org.aspectj.apache.bcel.classfile.ConstantFloat; +import org.aspectj.apache.bcel.classfile.ConstantInteger; +import org.aspectj.apache.bcel.classfile.ConstantLong; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; + +public class SimpleElementValue extends ElementValue { + + // 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 SimpleElementValue(int type, int idx, ConstantPool cpGen) { + super(type, cpGen); + this.idx = idx; + } + + public SimpleElementValue(int type, ConstantPool cpGen, int value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, long value) { + super(type, cpGen); + idx = cpGen.addLong(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, double value) { + super(type, cpGen); + idx = cpGen.addDouble(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, float value) { + super(type, cpGen); + idx = cpGen.addFloat(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, short value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, byte value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, char value) { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValue(int type, ConstantPool cpGen, boolean value) { + super(type, cpGen); + if (value) { + idx = cpGen.addInteger(1); + } else { + idx = cpGen.addInteger(0); + } + } + + public SimpleElementValue(int type, ConstantPool cpGen, String value) { + super(type, cpGen); + idx = cpGen.addUtf8(value); + } + + public byte getValueByte() { + if (type != PRIMITIVE_BYTE) { + throw new RuntimeException("Dont call getValueByte() on a non BYTE ElementValue"); + } + ConstantInteger c = (ConstantInteger) cpool.getConstant(idx, Constants.CONSTANT_Integer); + return (byte) c.getIntValue(); + } + + public char getValueChar() { + if (type != PRIMITIVE_CHAR) { + throw new RuntimeException("Dont call getValueChar() on a non CHAR ElementValue"); + } + ConstantInteger c = (ConstantInteger) cpool.getConstant(idx, Constants.CONSTANT_Integer); + return (char) c.getIntValue(); + } + + public long getValueLong() { + if (type != PRIMITIVE_LONG) { + throw new RuntimeException("Dont call getValueLong() on a non LONG ElementValue"); + } + ConstantLong j = (ConstantLong) cpool.getConstant(idx); + return j.getValue(); + } + + public float getValueFloat() { + if (type != PRIMITIVE_FLOAT) { + throw new RuntimeException("Dont call getValueFloat() on a non FLOAT ElementValue"); + } + ConstantFloat f = (ConstantFloat) cpool.getConstant(idx); + return f.getValue(); + } + + public double getValueDouble() { + if (type != PRIMITIVE_DOUBLE) { + throw new RuntimeException("Dont call getValueDouble() on a non DOUBLE ElementValue"); + } + ConstantDouble d = (ConstantDouble) cpool.getConstant(idx); + return d.getValue(); + } + + public boolean getValueBoolean() { + if (type != PRIMITIVE_BOOLEAN) { + throw new RuntimeException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + } + ConstantInteger bo = (ConstantInteger) cpool.getConstant(idx); + return (bo.getValue() != 0); + } + + public short getValueShort() { + if (type != PRIMITIVE_SHORT) { + throw new RuntimeException("Dont call getValueShort() on a non SHORT ElementValue"); + } + ConstantInteger s = (ConstantInteger) cpool.getConstant(idx); + return (short) s.getIntValue(); + } + + /** + * 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 SimpleElementValue(SimpleElementValue value, ConstantPool 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); + } + } + } + + 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) cpool.getConstant(idx); + return c.getValue(); + } + + public int getValueInt() { + if (type != PRIMITIVE_INT) { + throw new RuntimeException("Dont call getValueString() on a non STRING ElementValue"); + } + ConstantInteger c = (ConstantInteger) cpool.getConstant(idx); + return c.getValue(); + } + + // Whatever kind of value it is, return it as a string + @Override + public String stringifyValue() { + switch (type) { + case PRIMITIVE_INT: + ConstantInteger c = (ConstantInteger) cpool.getConstant(idx); + return Integer.toString(c.getValue()); + case PRIMITIVE_LONG: + ConstantLong j = (ConstantLong) cpool.getConstant(idx); + return Long.toString(j.getValue()); + case PRIMITIVE_DOUBLE: + ConstantDouble d = (ConstantDouble) cpool.getConstant(idx); + return d.getValue().toString(); + case PRIMITIVE_FLOAT: + ConstantFloat f = (ConstantFloat) cpool.getConstant(idx); + return Float.toString(f.getValue()); + case PRIMITIVE_SHORT: + ConstantInteger s = (ConstantInteger) cpool.getConstant(idx); + return Integer.toString(s.getValue()); + case PRIMITIVE_BYTE: + ConstantInteger b = (ConstantInteger) cpool.getConstant(idx); + return Integer.toString(b.getValue()); + case PRIMITIVE_CHAR: + ConstantInteger ch = (ConstantInteger) cpool.getConstant(idx); + return new Character((char) ch.getIntValue()).toString(); + case PRIMITIVE_BOOLEAN: + ConstantInteger bo = (ConstantInteger) cpool.getConstant(idx); + if (bo.getValue() == 0) { + return "false"; + } else { + return "true"; + } + case STRING: + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(idx); + return cu8.getValue(); + + default: + throw new RuntimeException("SimpleElementValueGen class does not know how to stringify type " + type); + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + switch (type) { + case PRIMITIVE_INT: + ConstantInteger c = (ConstantInteger) cpool.getConstant(idx); + s.append("(int)").append(Integer.toString(c.getValue())); + break; + case PRIMITIVE_LONG: + ConstantLong j = (ConstantLong) cpool.getConstant(idx); + s.append("(long)").append(Long.toString(j.getValue())); + break; + case PRIMITIVE_DOUBLE: + ConstantDouble d = (ConstantDouble) cpool.getConstant(idx); + s.append("(double)").append(d.getValue().toString()); + break; + case PRIMITIVE_FLOAT: + ConstantFloat f = (ConstantFloat) cpool.getConstant(idx); + s.append("(float)").append(Float.toString(f.getValue())); + break; + case PRIMITIVE_SHORT: + ConstantInteger ci = (ConstantInteger) cpool.getConstant(idx); + s.append("(short)").append(Integer.toString(ci.getValue())); + break; + case PRIMITIVE_BYTE: + ConstantInteger b = (ConstantInteger) cpool.getConstant(idx); + s.append("(byte)").append(Integer.toString(b.getValue())); + break; + case PRIMITIVE_CHAR: + ConstantInteger ch = (ConstantInteger) cpool.getConstant(idx); + s.append("(char)").append(new Character((char) ch.getIntValue()).toString()); + break; + case PRIMITIVE_BOOLEAN: + ConstantInteger bo = (ConstantInteger) cpool.getConstant(idx); + s.append("(boolean)"); + if (bo.getValue() == 0) { + s.append("false"); + } else { + s.append("true"); + } + break; + case STRING: + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(idx); + s.append("(string)").append(cu8.getValue()); + break; + default: + throw new RuntimeException("SimpleElementValueGen class does not know how to stringify type " + type); + } + return s.toString(); + } + + @Override + 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); + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/TypeAnnotationGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/TypeAnnotationGen.java new file mode 100644 index 000000000..45e5928a3 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/annotation/TypeAnnotationGen.java @@ -0,0 +1,405 @@ +/* ******************************************************************* + * Copyright (c) 2013 VMware + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.aspectj.apache.bcel.classfile.annotation; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.classfile.ConstantPool; + +public class TypeAnnotationGen { + public static final TypeAnnotationGen[] NO_TYPE_ANNOTATIONS = new TypeAnnotationGen[0]; + public static final int[] NO_TYPE_PATH = new int[0]; + + private ConstantPool cpool; + + private TypeAnnotationGen(ConstantPool cpool) { + this.cpool = cpool; + } + + private int targetType; + private int[] typePath; + private AnnotationGen annotation; + private int info; // meaning varies depending on target type + private int info2; // meaning varies depending on target type + private int[] localVarTarget; + + // target type constants + public final static int CLASS_TYPE_PARAMETER = 0x00; + public final static int METHOD_TYPE_PARAMETER = 0x01; + + public final static int CLASS_EXTENDS = 0x10; + public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; + public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; + public final static int FIELD = 0x13; + public final static int METHOD_RETURN = 0x14; + public final static int METHOD_RECEIVER = 0x15; + public final static int METHOD_FORMAL_PARAMETER = 0x16; + public final static int THROWS = 0x17; + + public final static int LOCAL_VARIABLE = 0x40; + public final static int RESOURCE_VARIABLE = 0x41; + public final static int EXCEPTION_PARAMETER = 0x42; + public final static int INSTANCEOF = 0x43; + public final static int NEW = 0x44; + public final static int CONSTRUCTOR_REFERENCE = 0x45; + public final static int METHOD_REFERENCE = 0x46; + public final static int CAST = 0x47; + public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; + public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; + public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; + public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; + + // type path entry kinds + public final static int TYPE_PATH_ENTRY_KIND_ARRAY = 0; + public final static int TYPE_PATH_ENTRY_KIND_INNER_TYPE = 1; + public final static int TYPE_PATH_ENTRY_KIND_WILDCARD = 2; + public final static int TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT = 3; + + + public static TypeAnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean isVisible) throws IOException { + TypeAnnotationGen typeAnno = new TypeAnnotationGen(cpool); + typeAnno.targetType = dis.readUnsignedByte(); + // read target_info + switch (typeAnno.targetType) { + case CLASS_TYPE_PARAMETER: + typeAnno.info = dis.readUnsignedByte();// type_parameter_index + break; + case METHOD_TYPE_PARAMETER: + typeAnno.info = dis.readUnsignedByte(); // type_parameter_index + break; + case CLASS_EXTENDS: + int superTypeIndex = dis.readUnsignedShort(); + if (superTypeIndex == 65535) { + typeAnno.info = -1; + } else { + typeAnno.info = superTypeIndex; + } + break; + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + typeAnno.info = dis.readUnsignedByte(); // type_parameter_index + typeAnno.info2 = dis.readUnsignedByte(); // bound_index; + break; + case FIELD: + case METHOD_RETURN: + case METHOD_RECEIVER: + break; + case METHOD_FORMAL_PARAMETER: + typeAnno.info = dis.readUnsignedByte(); // method_formal_parameter_index + break; + case THROWS: + typeAnno.info = dis.readUnsignedShort(); // throws_type_index + break; + case LOCAL_VARIABLE: + case RESOURCE_VARIABLE: + typeAnno.localVarTarget = readLocalVarTarget(dis); + break; + case EXCEPTION_PARAMETER: + // TODO should be a SHORT according to the spec but byte for now because of javac (b90) + typeAnno.info = dis.readUnsignedByte(); // exception_table_index + break; + case INSTANCEOF: + case NEW: + case CONSTRUCTOR_REFERENCE: + case METHOD_REFERENCE: + typeAnno.info = dis.readUnsignedShort(); // offset + break; + case CAST: + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + typeAnno.info = dis.readUnsignedShort(); // offset + typeAnno.info2 = dis.readUnsignedByte(); // type_argument_index + break; + default: + throw new IllegalStateException("nyi "+typeAnno.targetType); + } + int typepathlength = dis.readUnsignedByte(); + if (typepathlength==0) { + typeAnno.typePath = NO_TYPE_PATH; + } else { + typeAnno.typePath = new int[typepathlength*2]; + for (int i=0, max = typepathlength*2; i<max; i++) { + typeAnno.typePath[i] = dis.readUnsignedByte(); + } + } + typeAnno.annotation = AnnotationGen.read(dis, cpool, isVisible); + return typeAnno; + } + + public static int[] readLocalVarTarget(DataInputStream dis) throws IOException { + int tableLength = dis.readUnsignedShort(); + int[] table = new int[tableLength*3]; + int count = 0; + for (int i=0;i<tableLength;i++) { + table[count++]=dis.readUnsignedShort(); // start_pc + table[count++]=dis.readUnsignedShort(); // length + table[count++]=dis.readUnsignedShort(); // index + } + return table; + } + + public void dump(DataOutputStream dos) throws IOException { + dos.writeByte(targetType); + switch (targetType) { + case CLASS_TYPE_PARAMETER: + dos.writeByte(this.info); // type_parameter_index + break; + case METHOD_TYPE_PARAMETER: + dos.writeByte(info); // type_parameter_index + break; + case CLASS_EXTENDS: + dos.writeShort(info); // supertype_index + break; + case CLASS_TYPE_PARAMETER_BOUND: + case METHOD_TYPE_PARAMETER_BOUND: + dos.writeByte(info); // type_parameter_index + dos.writeByte(info2); // bound_index; + break; + case FIELD: + case METHOD_RETURN: + case METHOD_RECEIVER: + break; + case METHOD_FORMAL_PARAMETER: + dos.writeByte(info); // method_formal_parameter_index + break; + case THROWS: + dos.writeShort(info); // throws_type_index + break; + case LOCAL_VARIABLE: + case RESOURCE_VARIABLE: + dos.writeShort(localVarTarget.length/3); + for (int i=0;i<localVarTarget.length;i++) { + dos.writeShort(localVarTarget[i]); + } + break; + case EXCEPTION_PARAMETER: + // TODO should be a SHORT according to the spec but byte for now because of javac (b90) + dos.writeByte(info); // exception_table_index + break; + case INSTANCEOF: + case NEW: + case CONSTRUCTOR_REFERENCE: + case METHOD_REFERENCE: + dos.writeShort(info); // offset + break; + case CAST: + case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: + case METHOD_INVOCATION_TYPE_ARGUMENT: + case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: + case METHOD_REFERENCE_TYPE_ARGUMENT: + dos.writeShort(info); // offset + dos.writeByte(info); // type_argument_index + break; + default: + throw new IllegalStateException("nyi "+targetType); + } + dos.writeByte(typePath.length); + for (int i=0;i<typePath.length;i++) { + dos.writeByte(typePath[i]); + } + annotation.dump(dos); + } + + public int getSupertypeIndex() { + assert (targetType==CLASS_EXTENDS); + return info; + } + + public int getOffset() { + assert (targetType==INSTANCEOF || targetType==NEW || targetType==CONSTRUCTOR_REFERENCE || targetType==METHOD_REFERENCE || + targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT || + targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT || + targetType==METHOD_REFERENCE_TYPE_ARGUMENT); + return info; + } + + public int getTypeParameterIndex() { + assert (targetType==CLASS_TYPE_PARAMETER || targetType==METHOD_TYPE_PARAMETER || + targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND); + return info; + } + + public int getTypeArgumentIndex() { + assert (targetType==CAST || targetType==CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT || + targetType==METHOD_INVOCATION_TYPE_ARGUMENT || targetType==CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT || targetType==METHOD_REFERENCE_TYPE_ARGUMENT); + return info2; + } + + public int getBoundIndex() { + assert (targetType==CLASS_TYPE_PARAMETER_BOUND || targetType==METHOD_TYPE_PARAMETER_BOUND); + return info2; + } + + public int getMethodFormalParameterIndex() { + assert (targetType==METHOD_FORMAL_PARAMETER); + return info; + } + + public int getThrowsTypeIndex() { + assert (targetType==THROWS); + return info; + } + + public int[] getLocalVarTarget() { + assert (targetType==LOCAL_VARIABLE||targetType==RESOURCE_VARIABLE); + return localVarTarget; + } + + public int getExceptionTableIndex() { + assert (targetType==EXCEPTION_PARAMETER); + return info; + } + + + + public int getTargetType() { + return targetType; + } + + public AnnotationGen getAnnotation() { + return annotation; + } + +// @Override +// public String toString() { +// StringBuffer s = new StringBuffer(); +// s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {"); +// for (int i = 0; i < pairs.size(); i++) { +// s.append(pairs.get(i)); +// if (i + 1 < pairs.size()) +// s.append(","); +// } +// s.append("}]"); +// return s.toString(); +// } +// +// public String toShortString() { +// StringBuffer s = new StringBuffer(); +// s.append("@" + getTypeName() + "("); +// for (int i = 0; i < pairs.size(); i++) { +// s.append(pairs.get(i)); +// if (i + 1 < pairs.size()) +// s.append(","); +// } +// s.append(")"); +// return s.toString(); +// } +// +// private void isRuntimeVisible(boolean b) { +// isRuntimeVisible = b; +// } +// +// public boolean isRuntimeVisible() { +// return isRuntimeVisible; +// } +// +// /** +// * @return true if the annotation has a value with the specified name and (toString'd) value +// */ +// public boolean hasNameValuePair(String name, String value) { +// for (NameValuePair pair : pairs) { +// if (pair.getNameString().equals(name)) { +// if (pair.getValue().stringifyValue().equals(value)) { +// return true; +// } +// } +// } +// return false; +// } +// +// /** +// * @return true if the annotation has a value with the specified name +// */ +// public boolean hasNamedValue(String name) { +// for (NameValuePair pair : pairs) { +// if (pair.getNameString().equals(name)) { +// return true; +// } +// } +// return false; +// } + +// public TypeAnnotationGen(TypeAnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) { +// this.cpool = cpool; +// if (copyPoolEntries) { +// typeIndex = cpool.addUtf8(a.getTypeSignature()); +// } else { +// typeIndex = a.getTypeIndex(); +// } +// isRuntimeVisible = a.isRuntimeVisible(); +// pairs = copyValues(a.getValues(), cpool, copyPoolEntries); +// } +// +// private List<NameValuePair> copyValues(List<NameValuePair> in, ConstantPool cpool, boolean copyPoolEntries) { +// List<NameValuePair> out = new ArrayList<NameValuePair>(); +// for (NameValuePair nvp : in) { +// out.add(new NameValuePair(nvp, cpool, copyPoolEntries)); +// } +// return out; +// } +// +// +// /** +// * Retrieve an immutable version of this AnnotationGen +// */ +// public TypeAnnotationGen(ObjectType type, List<NameValuePair> pairs, boolean runtimeVisible, ConstantPool cpool) { +// this.cpool = cpool; +// if (type != null) { +// this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects +// } +// this.pairs = pairs; +// isRuntimeVisible = runtimeVisible; +// } +// + + public int[] getTypePath() { + return typePath; + } + + public String getTypePathString() { + return toTypePathString(typePath); + } + + public static String toTypePathString(int[] typepath) { + StringBuilder sb = new StringBuilder(); + int count = 0; + sb.append("["); + while (count < typepath.length) { + if (count>0) sb.append(","); + switch (typepath[count++]) { + case TYPE_PATH_ENTRY_KIND_ARRAY: + sb.append("ARRAY"); + count++; + break; + case TYPE_PATH_ENTRY_KIND_INNER_TYPE: + sb.append("INNER_TYPE"); + count++; + break; + case TYPE_PATH_ENTRY_KIND_WILDCARD: + sb.append("WILDCARD"); + count++; + break; + case TYPE_PATH_ENTRY_KIND_TYPE_ARGUMENT: + sb.append("TYPE_ARGUMENT(").append(typepath[count++]).append(")"); + break; + } + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ArrayType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ArrayType.java new file mode 100644 index 000000000..d9599289b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ArrayType.java @@ -0,0 +1,156 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.Constants; + +/** + * Denotes array type, such as int[][] + * + * @version $Id: ArrayType.java,v 1.4 2008/08/26 15:02:04 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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; + else + 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); + } else + return false; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BasicType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BasicType.java new file mode 100644 index 000000000..477fb1dff --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BasicType.java @@ -0,0 +1,111 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.Constants; + +/** + * Denotes basic type such as int. + * + * @version $Id: BasicType.java,v 1.4 2008/08/28 00:05:57 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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.aspectj.apache.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 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; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BranchHandle.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BranchHandle.java new file mode 100644 index 000000000..35d9528b8 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/BranchHandle.java @@ -0,0 +1,134 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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: BranchHandle.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class BranchHandle extends InstructionHandle { + private InstructionBranch bi; // An alias in fact, but saves lots of casts + + private BranchHandle(InstructionBranch i) { + super(i); + bi = i; + } + + static final BranchHandle getBranchHandle(InstructionBranch i) { + return new BranchHandle(i); + } + + /* + * 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.positionOfThisInstruction; + } + + void setPosition(int pos) { + this.pos = bi.positionOfThisInstruction = pos; + } + + /** + * 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) { + int x = bi.updatePosition(offset, max_offset); + pos = bi.positionOfThisInstruction; + 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); + bi = (InstructionBranch) i; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGen.java new file mode 100644 index 000000000..4ba767d97 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGen.java @@ -0,0 +1,637 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.lang.reflect.Modifier; +import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.Field; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.Method; +import org.aspectj.apache.bcel.classfile.Modifiers; +import org.aspectj.apache.bcel.classfile.SourceFile; +import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeInvisAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos; + +/** + * Template class for building up a java class. May be initialized with an existing java class. + * + * @see JavaClass + * @version $Id: ClassGen.java,v 1.15 2009/09/15 19:40:14 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * + * Upgraded, Andy Clement 9th Mar 06 - calculates SUID + */ +public class ClassGen extends Modifiers implements Cloneable { + + private String classname; + private String superclassname; + private String filename; + private int classnameIndex = -1; + private int superclassnameIndex = -1; + private int major = Constants.MAJOR_1_1; + private int minor = Constants.MINOR_1_1; + private ConstantPool cpool; + private List<Field> fieldsList = new ArrayList<Field>(); + private List<Method> methodsList = new ArrayList<Method>(); + private List<Attribute> attributesList = new ArrayList<Attribute>(); + private List<String> interfaceList = new ArrayList<String>(); + private List<AnnotationGen> annotationsList = new ArrayList<AnnotationGen>(); + + public ClassGen(String classname, String superclassname, String filename, int modifiers, String[] interfacenames, + ConstantPool cpool) { + this.classname = classname; + this.superclassname = superclassname; + this.filename = filename; + this.modifiers = modifiers; + this.cpool = cpool; + if (filename != null) { + addAttribute(new SourceFile(cpool.addUtf8("SourceFile"), 2, cpool.addUtf8(filename), cpool)); + } + this.classnameIndex = cpool.addClass(classname); + this.superclassnameIndex = cpool.addClass(superclassname); + if (interfacenames != null) { + for (String interfacename : interfacenames) { + addInterface(interfacename); + } + } + } + + public ClassGen(String classname, String superclassname, String filename, int modifiers, String[] interfacenames) { + this(classname, superclassname, filename, modifiers, interfacenames, new ConstantPool()); + } + + public ClassGen(JavaClass clazz) { + classnameIndex = clazz.getClassNameIndex(); + superclassnameIndex = clazz.getSuperclassNameIndex(); + classname = clazz.getClassName(); + superclassname = clazz.getSuperclassName(); + filename = clazz.getSourceFileName(); + modifiers = clazz.getModifiers(); + cpool = clazz.getConstantPool().copy(); + major = clazz.getMajor(); + minor = clazz.getMinor(); + + Method[] methods = clazz.getMethods(); + Field[] fields = clazz.getFields(); + String[] interfaces = clazz.getInterfaceNames(); + + for (int i = 0; i < interfaces.length; i++) { + addInterface(interfaces[i]); + } + + // OPTIMIZE Could make unpacking lazy, done on first reference + Attribute[] attributes = clazz.getAttributes(); + for (Attribute attr : attributes) { + if (attr instanceof RuntimeVisAnnos) { + RuntimeVisAnnos rva = (RuntimeVisAnnos) attr; + List<AnnotationGen> annos = rva.getAnnotations(); + for (AnnotationGen a : annos) { + annotationsList.add(new AnnotationGen(a, cpool, false)); + } + } else if (attr instanceof RuntimeInvisAnnos) { + RuntimeInvisAnnos ria = (RuntimeInvisAnnos) attr; + List<AnnotationGen> annos = ria.getAnnotations(); + for (AnnotationGen anno : annos) { + annotationsList.add(new AnnotationGen(anno, cpool, false)); + } + } else { + attributesList.add(attr); + } + } + + for (int i = 0; i < methods.length; i++) { + addMethod(methods[i]); + } + + for (int i = 0; i < fields.length; i++) { + addField(fields[i]); + } + } + + /** + * @return build and return a JavaClass + */ + public JavaClass getJavaClass() { + int[] interfaces = getInterfaces(); + Field[] fields = getFields(); + Method[] methods = getMethods(); + + Collection<Attribute> attributes = null; + if (annotationsList.size() == 0) { + attributes = attributesList; + } else { + // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations' + attributes = new ArrayList<Attribute>(); + attributes.addAll(Utility.getAnnotationAttributes(cpool, annotationsList)); + attributes.addAll(attributesList); + } + + // Must be last since the above calls may still add something to it + ConstantPool cp = this.cpool.getFinalConstantPool(); + + return new JavaClass(classnameIndex, superclassnameIndex, filename, major, minor, modifiers, cp, interfaces, fields, + methods, attributes.toArray(new Attribute[attributes.size()]));// OPTIMIZE avoid toArray()? + } + + public void addInterface(String name) { + interfaceList.add(name); + } + + public void removeInterface(String name) { + interfaceList.remove(name); + } + + public int getMajor() { + return major; + } + + public void setMajor(int major) { + this.major = major; + } + + public void setMinor(int minor) { + this.minor = minor; + } + + public int getMinor() { + return minor; + } + + public void addAttribute(Attribute a) { + attributesList.add(a); + } + + public void addAnnotation(AnnotationGen a) { + annotationsList.add(a); + } + + public void addMethod(Method m) { + methodsList.add(m); + } + + /** + * Convenience method. + * + * Add an empty constructor to this class that does nothing but calling super(). + * + * @param access rights for constructor + */ + public void addEmptyConstructor(int access_flags) { + InstructionList il = new InstructionList(); + il.append(InstructionConstants.THIS); // Push `this' + il.append(new InvokeInstruction(Constants.INVOKESPECIAL, cpool.addMethodref(superclassname, "<init>", "()V"))); + il.append(InstructionConstants.RETURN); + + MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "<init>", classname, il, cpool); + mg.setMaxStack(1); + mg.setMaxLocals(); + addMethod(mg.getMethod()); + } + + /** + * Add a field to this class. + * + * @param f field to add + */ + public void addField(Field f) { + fieldsList.add(f); + } + + public boolean containsField(Field f) { + return fieldsList.contains(f); + } + + /** + * @return field object with given name, or null if not found + */ + public Field findsField(String name) { + for (Field field : fieldsList) { + if (field.getName().equals(name)) { + return field; + } + } + return null; + } + + /** + * @return method object with given name and signature, or null if not found + */ + public Method containsMethod(String name, String signature) { + for (Method method : methodsList) { + if (method.getName().equals(name) && method.getSignature().equals(signature)) { + return method; + } + } + return null; + } + + public void removeAttribute(Attribute a) { + attributesList.remove(a); + } + + public void removeAnnotation(AnnotationGen a) { + annotationsList.remove(a); + } + + public void removeMethod(Method m) { + methodsList.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 = methodsList.indexOf(old); + + if (i < 0) + methodsList.add(new_); + else + methodsList.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 = fieldsList.indexOf(old); + + if (i < 0) + fieldsList.add(new_); + else + fieldsList.set(i, new_); + } + + public void removeField(Field f) { + fieldsList.remove(f); + } + + public String getClassName() { + return classname; + } + + public String getSuperclassName() { + return superclassname; + } + + public String getFileName() { + return filename; + } + + public void setClassName(String name) { + classname = name.replace('/', '.'); + classnameIndex = cpool.addClass(name); + } + + public void setSuperclassName(String name) { + superclassname = name.replace('/', '.'); + superclassnameIndex = cpool.addClass(name); + } + + public Method[] getMethods() { + Method[] methods = new Method[methodsList.size()]; + methodsList.toArray(methods); + return methods; + } + + public void setMethods(Method[] methods) { + methodsList.clear(); + for (int m = 0; m < methods.length; m++) + addMethod(methods[m]); + } + + public void setFields(Field[] fs) { + fieldsList.clear(); + for (int m = 0; m < fs.length; m++) + addField(fs[m]); + } + + public void setMethodAt(Method method, int pos) { + methodsList.set(pos, method); + } + + public Method getMethodAt(int pos) { + return methodsList.get(pos); + } + + public String[] getInterfaceNames() { + int size = interfaceList.size(); + String[] interfaces = new String[size]; + + interfaceList.toArray(interfaces); + return interfaces; + } + + public int[] getInterfaces() { + int size = interfaceList.size(); + int[] interfaces = new int[size]; + + for (int i = 0; i < size; i++) + interfaces[i] = cpool.addClass(interfaceList.get(i)); + + return interfaces; + } + + public Field[] getFields() { + Field[] fields = new Field[fieldsList.size()]; + fieldsList.toArray(fields); + return fields; + } + + public Collection<Attribute> getAttributes() { + return attributesList; + } + + // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? + public AnnotationGen[] getAnnotations() { + AnnotationGen[] annotations = new AnnotationGen[annotationsList.size()]; + annotationsList.toArray(annotations); + return annotations; + } + + public ConstantPool getConstantPool() { + return cpool; + } + + public void setConstantPool(ConstantPool constant_pool) { + cpool = constant_pool; + } + + public void setClassNameIndex(int class_name_index) { + this.classnameIndex = class_name_index; + classname = cpool.getConstantString(class_name_index, Constants.CONSTANT_Class).replace('/', '.'); + } + + public void setSuperclassNameIndex(int superclass_name_index) { + this.superclassnameIndex = superclass_name_index; + superclassname = cpool.getConstantString(superclass_name_index, Constants.CONSTANT_Class).replace('/', '.'); + } + + public int getSuperclassNameIndex() { + return superclassnameIndex; + } + + public int getClassNameIndex() { + return classnameIndex; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } + + public final boolean isAnnotation() { + return (modifiers & Constants.ACC_ANNOTATION) != 0; + } + + public final boolean isEnum() { + return (modifiers & Constants.ACC_ENUM) != 0; + } + + /** + * Calculate the SerialVersionUID for a class. + */ + public long getSUID() { + try { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + // 1. classname + dos.writeUTF(getClassName()); + + // 2. classmodifiers: ACC_PUBLIC, ACC_FINAL, ACC_INTERFACE, and ACC_ABSTRACT + int classmods = 0; + classmods |= (isPublic() ? Constants.ACC_PUBLIC : 0); + classmods |= (isFinal() ? Constants.ACC_FINAL : 0); + classmods |= (isInterface() ? Constants.ACC_INTERFACE : 0); + + if (isAbstract()) { + // if an interface then abstract is only set if it has methods + if (isInterface()) { + if (methodsList.size() > 0) + classmods |= Constants.ACC_ABSTRACT; + } else { + classmods |= Constants.ACC_ABSTRACT; + } + } + + dos.writeInt(classmods); + + // 3. ordered list of interfaces + String[] names = getInterfaceNames(); + if (names != null) { + Arrays.sort(names); + for (int i = 0; i < names.length; i++) + dos.writeUTF(names[i]); + } + + // 4. ordered list of fields (ignoring private static and private transient fields): + // (relevant modifiers are ACC_PUBLIC, ACC_PRIVATE, + // ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_VOLATILE, + // ACC_TRANSIENT) + List<Field> relevantFields = new ArrayList<Field>(); + for (Field field : fieldsList) { + if (!(field.isPrivate() && field.isStatic()) && !(field.isPrivate() && field.isTransient())) { + relevantFields.add(field); + } + } + Collections.sort(relevantFields, new FieldComparator()); + int relevantFlags = Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_STATIC + | Constants.ACC_FINAL | Constants.ACC_VOLATILE | Constants.ACC_TRANSIENT; + for (Field f : relevantFields) { + dos.writeUTF(f.getName()); + dos.writeInt(relevantFlags & f.getModifiers()); + dos.writeUTF(f.getType().getSignature()); + } + + // some up front method processing: discover clinit, init and ordinary methods of interest: + List<Method> relevantMethods = new ArrayList<Method>(); + List<Method> relevantCtors = new ArrayList<Method>(); + boolean hasClinit = false; + for (Method m : methodsList) { + boolean couldBeInitializer = m.getName().charAt(0) == '<'; + if (couldBeInitializer && m.getName().equals("<clinit>")) { + hasClinit = true; + } else if (couldBeInitializer && m.getName().equals("<init>")) { + if (!m.isPrivate()) + relevantCtors.add(m); + } else { + if (!m.isPrivate()) + relevantMethods.add(m); + } + } + Collections.sort(relevantCtors, new ConstructorComparator()); + Collections.sort(relevantMethods, new MethodComparator()); + + // 5. If a class initializer exists, write out the following: + // 1. The name of the method, <clinit>. + // 2. The modifier of the method, java.lang.reflect.Modifier.STATIC, written as a 32-bit integer. + // 3. The descriptor of the method, ()V. + if (hasClinit) { + dos.writeUTF("<clinit>"); + dos.writeInt(Modifier.STATIC); + dos.writeUTF("()V"); + } + + // for methods and constructors: + // ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNCHRONIZED, + // ACC_NATIVE, ACC_ABSTRACT and ACC_STRICT + relevantFlags = Constants.ACC_PUBLIC | Constants.ACC_PRIVATE | Constants.ACC_PROTECTED | Constants.ACC_STATIC + | Constants.ACC_FINAL | Constants.ACC_SYNCHRONIZED | Constants.ACC_NATIVE | Constants.ACC_ABSTRACT + | Constants.ACC_STRICT; + + // 6. sorted non-private constructors + for (Method ctor : relevantCtors) { + dos.writeUTF(ctor.getName()); // <init> + dos.writeInt(relevantFlags & ctor.getModifiers()); + dos.writeUTF(ctor.getSignature().replace('/', '.')); + } + + // 7. sorted non-private methods + for (Method m : relevantMethods) { + dos.writeUTF(m.getName()); + dos.writeInt(relevantFlags & m.getModifiers()); + dos.writeUTF(m.getSignature().replace('/', '.')); + } + dos.flush(); + dos.close(); + byte[] bs = baos.toByteArray(); + MessageDigest md = MessageDigest.getInstance("SHA"); + byte[] result = md.digest(bs); + + long suid = 0L; + int pos = result.length > 8 ? 7 : result.length - 1; // use the bytes we have + while (pos >= 0) { + suid = suid << 8 | ((long) result[pos--] & 0xff); + } + + // if it was definetly 8 everytime... + // long suid = ((long)(sha[0]&0xff) | (long)(sha[1]&0xff) << 8 | + // (long)(sha[2]&0xff) << 16 | (long)(sha[3]&0xff) << 24 | + // (long)(sha[4]&0xff) << 32 | (long)(sha[5]&0xff) << 40 | + // (long)(sha[6]&0xff) << 48 | (long)(sha[7]&0xff) << 56); + return suid; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Unable to calculate suid for " + getClassName() + ": " + e.toString()); + } + } + + private static class FieldComparator implements Comparator<Field> { + public int compare(Field f0, Field f1) { + return f0.getName().compareTo(f1.getName()); + } + } + + private static class ConstructorComparator implements Comparator<Method> { + public int compare(Method m0, Method m1) { + // can ignore the name... + return (m0).getSignature().compareTo(m1.getSignature()); + } + } + + private static class MethodComparator implements Comparator<Method> { + public int compare(Method m0, Method m1) { + int result = m0.getName().compareTo(m1.getName()); + if (result == 0) { + result = m0.getSignature().compareTo(m1.getSignature()); + } + return result; + } + } + + public boolean hasAttribute(String attributeName) { + for (Attribute attr : attributesList) { + if (attr.getName().equals(attributeName)) { + return true; + } + } + return false; + } + + public Attribute getAttribute(String attributeName) { + for (Attribute attr : attributesList) { + if (attr.getName().equals(attributeName)) { + return attr; + } + } + return null; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGenException.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGenException.java new file mode 100644 index 000000000..b981dc8dc --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ClassGenException.java @@ -0,0 +1,68 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * Thrown on internal errors. Extends RuntimeException so it hasn't to be declared + * in the throws clause every time. + * + * @version $Id: ClassGenException.java,v 1.3 2008/05/28 23:52:57 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class ClassGenException extends RuntimeException { + public ClassGenException() { super(); } + public ClassGenException(String s) { super(s); } +} + diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/CodeExceptionGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/CodeExceptionGen.java new file mode 100644 index 000000000..01b839207 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/CodeExceptionGen.java @@ -0,0 +1,202 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.classfile.CodeException; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * 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: CodeExceptionGen.java,v 1.5 2008/05/28 23:52:56 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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(ConstantPool 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) { + InstructionBranch.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) { + InstructionBranch.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) { + InstructionBranch.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; + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGen.java new file mode 100644 index 000000000..6a12a8c80 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGen.java @@ -0,0 +1,245 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.util.Iterator; +import java.util.List; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.Constant; +import org.aspectj.apache.bcel.classfile.ConstantDouble; +import org.aspectj.apache.bcel.classfile.ConstantFloat; +import org.aspectj.apache.bcel.classfile.ConstantInteger; +import org.aspectj.apache.bcel.classfile.ConstantLong; +import org.aspectj.apache.bcel.classfile.ConstantObject; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantString; +import org.aspectj.apache.bcel.classfile.ConstantValue; +import org.aspectj.apache.bcel.classfile.Field; +import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; + +/** + * 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 the declared type). + * + * @version $Id: FieldGen.java,v 1.11 2011/10/03 22:41:24 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Field + */ +public class FieldGen extends FieldGenOrMethodGen { + private Object value = null; + + /** + * 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 modifiers access qualifiers + * @param type field type + * @param name field name + * @param cpool constant pool + */ + public FieldGen(int modifiers, Type type, String name, ConstantPool cpool) { + setModifiers(modifiers); + setType(type); + setName(name); + setConstantPool(cpool); + } + + /** + * 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, ConstantPool cp) { + this(field.getModifiers(), 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 RuntimeAnnos) { + RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) attrs[i]; + List<AnnotationGen> l = runtimeAnnotations.getAnnotations(); + for (Iterator<AnnotationGen> it = l.iterator(); it.hasNext();) { + AnnotationGen element = it.next(); + addAnnotation(new AnnotationGen(element, cp, false)); + } + } else { + addAttribute(attrs[i]); + } + } + } + + public void setValue(int index) { + ConstantPool cp = this.cp; + Constant c = cp.getConstant(index); + if (c instanceof ConstantInteger) { + value = ((ConstantInteger) c).getIntValue(); + } else if (c instanceof ConstantFloat) { + value = ((ConstantFloat) c).getValue(); + } else if (c instanceof ConstantDouble) { + value = ((ConstantDouble) c).getValue(); + } else if (c instanceof ConstantLong) { + value = ((ConstantLong) c).getValue(); + } else if (c instanceof ConstantString) { + value = ((ConstantString)c).getString(cp); + } else { + value = ((ConstantObject) c).getConstantValue(cp); + } + } + + public void setValue(String constantString) { + value = constantString; + } + + public void wipeValue() { + 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 nameIndex = cp.addUtf8(name); + int signatureIndex = cp.addUtf8(signature); + + if (value != null) { + checkType(type); + int index = addConstant(); + addAttribute(new ConstantValue(cp.addUtf8("ConstantValue"), 2, index, cp)); + } + + addAnnotationsAsAttribute(cp); + + return new Field(modifiers, nameIndex, signatureIndex, getAttributesImmutable(), cp); + } + + 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()); + } + } + + @Override + public String getSignature() { + return type.getSignature(); + } + + public String getInitialValue() { + return (value == null ? null : value.toString()); + } + + public void setInitialStringValue(String value) { + this.value = value; + } + + /** + * Return string representation close to declaration format, `public static final short MAX = 100', e.g.. + */ + @Override + public final String toString() { + String access = Utility.accessToString(modifiers); + access = access.equals("") ? "" : (access + " "); + String signature = type.toString(); + String name = getName(); + + StringBuffer buf = new StringBuffer(access).append(signature).append(" ").append(name); + String value = getInitialValue(); + + if (value != null) { + buf.append(" = ").append(value); + } + // TODO: Add attributes and annotations to the string + return buf.toString(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGenOrMethodGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGenOrMethodGen.java new file mode 100644 index 000000000..ff8b6f42c --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldGenOrMethodGen.java @@ -0,0 +1,158 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.Modifiers; +import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; + +/** + * Super class for FieldGen and MethodGen objects, since they have some methods in common! + * + * @version $Id: FieldGenOrMethodGen.java,v 1.8 2009/09/15 19:40:14 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class FieldGenOrMethodGen extends Modifiers { + + protected String name; + protected Type type; + protected ConstantPool cp; + private ArrayList<Attribute> attributeList = new ArrayList<Attribute>(); + protected ArrayList<AnnotationGen> annotationList = new ArrayList<AnnotationGen>(); + + protected FieldGenOrMethodGen() { + } + + public void setType(Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ConstantPool getConstantPool() { + return cp; + } + + public void setConstantPool(ConstantPool cp) { + this.cp = cp; + } + + public void addAttribute(Attribute a) { + attributeList.add(a); + } + + public void removeAttribute(Attribute a) { + attributeList.remove(a); + } + + public void removeAttributes() { + attributeList.clear(); + } + + public List<AnnotationGen> getAnnotations() { + return annotationList; + } + + public void addAnnotation(AnnotationGen ag) { + annotationList.add(ag); + } + + public void removeAnnotation(AnnotationGen ag) { + annotationList.remove(ag); + } + + public void removeAnnotations() { + annotationList.clear(); + } + + public List<Attribute> getAttributes() { + return attributeList; + } + + public Attribute[] getAttributesImmutable() { + Attribute[] attributes = new Attribute[attributeList.size()]; + attributeList.toArray(attributes); + return attributes; + } + + protected void addAnnotationsAsAttribute(ConstantPool cp) { + Collection<RuntimeAnnos> attrs = Utility.getAnnotationAttributes(cp, annotationList); + if (attrs != null) { + for (Attribute attr : attrs) { + addAttribute(attr); + } + } + } + + public abstract String getSignature(); + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldInstruction.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldInstruction.java new file mode 100644 index 000000000..54983e7c9 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldInstruction.java @@ -0,0 +1,112 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * Super class for the GET/PUTxxx family of instructions. + * + * @version $Id: FieldInstruction.java,v 1.7 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class FieldInstruction extends FieldOrMethod { + + public FieldInstruction(short opcode, int index) { + super(opcode, index); + } + + public String toString(ConstantPool cp) { + return org.aspectj.apache.bcel.Constants.OPCODE_NAMES[opcode] + " " + + cp.constantToString(index, org.aspectj.apache.bcel.Constants.CONSTANT_Fieldref); + } + + /** + * @return size of field (1 or 2) + */ + protected int getFieldSize(ConstantPool cpg) { + return Type.getTypeSize(getSignature(cpg)); + } + + public Type getType(ConstantPool cpg) { + return getFieldType(cpg); + } + + public Type getFieldType(ConstantPool cpg) { + return Type.getType(getSignature(cpg)); + } + + public String getFieldName(ConstantPool cpg) { + return getName(cpg); + } + + public int produceStack(ConstantPool cpg) { + if (!isStackProducer()) { + return 0; + } + + return getFieldSize(cpg); // SAME FOR GETFIELD/GETSTATIC + } + + public int consumeStack(ConstantPool cpg) { + if (!isStackConsumer()) { + return 0; + } + if (opcode == GETFIELD) { + return 1; + } + return getFieldSize(cpg) + (opcode == PUTFIELD ? 1 : 0); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldOrMethod.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldOrMethod.java new file mode 100644 index 000000000..44b263ffb --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/FieldOrMethod.java @@ -0,0 +1,133 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.classfile.Constant; +import org.aspectj.apache.bcel.classfile.ConstantCP; +import org.aspectj.apache.bcel.classfile.ConstantNameAndType; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; + +/** + * Super class for InvokeInstruction and FieldInstruction, since they have some methods in common! + * + * @version $Id: FieldOrMethod.java,v 1.8 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class FieldOrMethod extends InstructionCP { + + protected String signature; + protected String name; + private String classname; + + protected FieldOrMethod(short opcode, int index) { + super(opcode, index); + } + + /** + * @return signature of referenced method/field. + */ + public String getSignature(ConstantPool cp) { + if (signature == null) { + Constant c = cp.getConstant(index); + ConstantCP cmr = (ConstantCP) c; + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + signature = ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getValue(); + } + return signature; + } + + /** + * @return name of referenced method/field. + */ + public String getName(ConstantPool cp) { + if (name == null) { + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + name = ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getValue(); + } + return name; + } + + /** + * @return name of the referenced class/interface + */ + public String getClassName(ConstantPool cp) { + if (classname == null) { + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + String str = cp.getConstantString(cmr.getClassIndex(), CONSTANT_Class); + if (str.charAt(0) == '[') { + classname = str; + } else { + classname = str.replace('/', '.'); + } + } + return classname; + } + + /** + * @return type of the referenced class/interface + */ + public ObjectType getClassType(ConstantPool cpg) { + return new ObjectType(getClassName(cpg)); + } + + /** + * @return type of the referenced class/interface + */ + @Override + public ObjectType getLoadClassType(ConstantPool cpg) { + return getClassType(cpg); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/IINC.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/IINC.java new file mode 100644 index 000000000..d70e20308 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/IINC.java @@ -0,0 +1,121 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * IINC - Increment local variable by constant + * + * @version $Id: IINC.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class IINC extends InstructionLV { + private int c; + + public IINC(int n, int c, boolean w) { + super(Constants.IINC, n); + this.c = c; + // this.wide = w;//((n > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); + } + + private boolean wide() { + return ((lvar > org.aspectj.apache.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE)); + } + + public void dump(DataOutputStream out) throws IOException { + if (wide()) { + out.writeByte(WIDE); + out.writeByte(opcode); + out.writeShort(lvar); + out.writeShort(c); + } else { + out.writeByte(opcode); + out.writeByte(lvar); + out.writeByte(c); + } + } + + public int getLength() { + if (wide()) { + return 6; + } else { + return 3; // includes wide byte + } + } + + public String toString(boolean verbose) { + return super.toString(verbose) + " " + c; + } + + public final int getIncrement() { + return c; + } + + public boolean equals(Object other) { + if (!(other instanceof IINC)) { + return false; + } + IINC o = (IINC) other; + return /* o.opcode == opcode && */o.lvar == lvar && o.c == c; + } + + public int hashCode() { + return opcode * 37 + lvar * (c + 17); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java new file mode 100644 index 000000000..b545f4d37 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/INVOKEINTERFACE.java @@ -0,0 +1,127 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * INVOKEINTERFACE - Invoke interface method + * + * <PRE> + * Stack: ..., objectref, [arg1, [arg2 ...]] -> ... + * </PRE> + * + * @version $Id: INVOKEINTERFACE.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 + + public INVOKEINTERFACE(int index, int nargs, int zerobyte) { + super(Constants.INVOKEINTERFACE, index); + + 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; + } + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString(ConstantPool cp) { + return super.toString(cp) + " " + nargs; + } + + public int consumeStack(ConstantPool cpg) { // nargs is given in byte-code + return nargs; // nargs includes this reference + } + + public boolean equals(Object other) { + if (!(other instanceof INVOKEINTERFACE)) { + return false; + } + INVOKEINTERFACE o = (INVOKEINTERFACE) other; + return o.opcode == opcode && o.index == index && o.nargs == nargs; + } + + public int hashCode() { + return opcode * 37 + index * (nargs + 17); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstVisitor.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstVisitor.java new file mode 100644 index 000000000..424ff4a66 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstVisitor.java @@ -0,0 +1,247 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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: InstVisitor.java,v 1.2 2008/05/28 23:52:59 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public interface InstVisitor { + public void visitStackInstruction(Instruction obj); + public void visitLocalVariableInstruction(InstructionLV obj); + public void visitBranchInstruction(InstructionBranch obj); + public void visitLoadClass(Instruction obj); + public void visitFieldInstruction(Instruction obj); + public void visitIfInstruction(Instruction obj); + public void visitConversionInstruction(Instruction obj); + public void visitPopInstruction(Instruction obj); + public void visitStoreInstruction(Instruction obj); + public void visitTypedInstruction(Instruction obj); + public void visitSelect(InstructionSelect obj); + public void visitJsrInstruction(InstructionBranch obj); + public void visitGotoInstruction(Instruction obj); + public void visitUnconditionalBranch(Instruction obj); + public void visitPushInstruction(Instruction obj); + public void visitArithmeticInstruction(Instruction obj); + public void visitCPInstruction(Instruction obj); + public void visitInvokeInstruction(InvokeInstruction obj); + public void visitArrayInstruction(Instruction obj); + public void visitAllocationInstruction(Instruction obj); + public void visitReturnInstruction(Instruction obj); + public void visitFieldOrMethod(Instruction obj); + public void visitConstantPushInstruction(Instruction obj); + public void visitExceptionThrower(Instruction obj); + public void visitLoadInstruction(Instruction obj); + public void visitVariableLengthInstruction(Instruction obj); + public void visitStackProducer(Instruction obj); + public void visitStackConsumer(Instruction obj); + public void visitACONST_NULL(Instruction obj); + public void visitGETSTATIC(FieldInstruction obj); + public void visitIF_ICMPLT(Instruction obj); + public void visitMONITOREXIT(Instruction obj); + public void visitIFLT(Instruction obj); + public void visitLSTORE(Instruction obj); + public void visitPOP2(Instruction obj); + public void visitBASTORE(Instruction obj); + public void visitISTORE(Instruction obj); + public void visitCHECKCAST(Instruction obj); + public void visitFCMPG(Instruction obj); + public void visitI2F(Instruction obj); + public void visitATHROW(Instruction obj); + public void visitDCMPL(Instruction obj); + public void visitARRAYLENGTH(Instruction obj); + public void visitDUP(Instruction obj); + public void visitINVOKESTATIC(InvokeInstruction obj); + public void visitLCONST(Instruction obj); + public void visitDREM(Instruction obj); + public void visitIFGE(Instruction obj); + public void visitCALOAD(Instruction obj); + public void visitLASTORE(Instruction obj); + public void visitI2D(Instruction obj); + public void visitDADD(Instruction obj); + public void visitINVOKESPECIAL(InvokeInstruction obj); + public void visitIAND(Instruction obj); + public void visitPUTFIELD(FieldInstruction obj); + public void visitILOAD(Instruction obj); + public void visitDLOAD(Instruction obj); + public void visitDCONST(Instruction obj); + public void visitNEW(Instruction obj); + public void visitIFNULL(Instruction obj); + public void visitLSUB(Instruction obj); + public void visitL2I(Instruction obj); + public void visitISHR(Instruction obj); + public void visitTABLESWITCH(TABLESWITCH obj); + public void visitIINC(IINC obj); + public void visitDRETURN(Instruction obj); + public void visitFSTORE(Instruction obj); + public void visitDASTORE(Instruction obj); + public void visitIALOAD(Instruction obj); + public void visitDDIV(Instruction obj); + public void visitIF_ICMPGE(Instruction obj); + public void visitLAND(Instruction obj); + public void visitIDIV(Instruction obj); + public void visitLOR(Instruction obj); + public void visitCASTORE(Instruction obj); + public void visitFREM(Instruction obj); + public void visitLDC(Instruction obj); + public void visitBIPUSH(Instruction obj); + public void visitDSTORE(Instruction obj); + public void visitF2L(Instruction obj); + public void visitFMUL(Instruction obj); + public void visitLLOAD(Instruction obj); + public void visitJSR(InstructionBranch obj); + public void visitFSUB(Instruction obj); + public void visitSASTORE(Instruction obj); + public void visitALOAD(Instruction obj); + public void visitDUP2_X2(Instruction obj); + public void visitRETURN(Instruction obj); + public void visitDALOAD(Instruction obj); + public void visitSIPUSH(Instruction obj); + public void visitDSUB(Instruction obj); + public void visitL2F(Instruction obj); + public void visitIF_ICMPGT(Instruction obj); + public void visitF2D(Instruction obj); + public void visitI2L(Instruction obj); + public void visitIF_ACMPNE(Instruction obj); + public void visitPOP(Instruction obj); + public void visitI2S(Instruction obj); + public void visitIFEQ(Instruction obj); + public void visitSWAP(Instruction obj); + public void visitIOR(Instruction obj); + public void visitIREM(Instruction obj); + public void visitIASTORE(Instruction obj); + public void visitNEWARRAY(Instruction obj); + public void visitINVOKEINTERFACE(INVOKEINTERFACE obj); + public void visitINEG(Instruction obj); + public void visitLCMP(Instruction obj); + public void visitJSR_W(InstructionBranch obj); + public void visitMULTIANEWARRAY(MULTIANEWARRAY obj); + public void visitDUP_X2(Instruction obj); + public void visitSALOAD(Instruction obj); + public void visitIFNONNULL(Instruction obj); + public void visitDMUL(Instruction obj); + public void visitIFNE(Instruction obj); + public void visitIF_ICMPLE(Instruction obj); + public void visitLDC2_W(Instruction obj); + public void visitGETFIELD(FieldInstruction obj); + public void visitLADD(Instruction obj); + public void visitNOP(Instruction obj); + public void visitFALOAD(Instruction obj); + public void visitINSTANCEOF(Instruction obj); + public void visitIFLE(Instruction obj); + public void visitLXOR(Instruction obj); + public void visitLRETURN(Instruction obj); + public void visitFCONST(Instruction obj); + public void visitIUSHR(Instruction obj); + public void visitBALOAD(Instruction obj); + public void visitDUP2(Instruction obj); + public void visitIF_ACMPEQ(Instruction obj); + public void visitIMPDEP1(Instruction obj); + public void visitMONITORENTER(Instruction obj); + public void visitLSHL(Instruction obj); + public void visitDCMPG(Instruction obj); + public void visitD2L(Instruction obj); + public void visitIMPDEP2(Instruction obj); + public void visitL2D(Instruction obj); + public void visitRET(RET obj); + public void visitIFGT(Instruction obj); + public void visitIXOR(Instruction obj); + public void visitINVOKEVIRTUAL(InvokeInstruction obj); + public void visitFASTORE(Instruction obj); + public void visitIRETURN(Instruction obj); + public void visitIF_ICMPNE(Instruction obj); + public void visitFLOAD(Instruction obj); + public void visitLDIV(Instruction obj); + public void visitPUTSTATIC(FieldInstruction obj); + public void visitAALOAD(Instruction obj); + public void visitD2I(Instruction obj); + public void visitIF_ICMPEQ(Instruction obj); + public void visitAASTORE(Instruction obj); + public void visitARETURN(Instruction obj); + public void visitDUP2_X1(Instruction obj); + public void visitFNEG(Instruction obj); + public void visitGOTO_W(Instruction obj); + public void visitD2F(Instruction obj); + public void visitGOTO(Instruction obj); + public void visitISUB(Instruction obj); + public void visitF2I(Instruction obj); + public void visitDNEG(Instruction obj); + public void visitICONST(Instruction obj); + public void visitFDIV(Instruction obj); + public void visitI2B(Instruction obj); + public void visitLNEG(Instruction obj); + public void visitLREM(Instruction obj); + public void visitIMUL(Instruction obj); + public void visitIADD(Instruction obj); + public void visitLSHR(Instruction obj); + public void visitLOOKUPSWITCH(LOOKUPSWITCH obj); + public void visitDUP_X1(Instruction obj); + public void visitFCMPL(Instruction obj); + public void visitI2C(Instruction obj); + public void visitLMUL(Instruction obj); + public void visitLUSHR(Instruction obj); + public void visitISHL(Instruction obj); + public void visitLALOAD(Instruction obj); + public void visitASTORE(Instruction obj); + public void visitANEWARRAY(Instruction obj); + public void visitFRETURN(Instruction obj); + public void visitFADD(Instruction obj); + public void visitBREAKPOINT(Instruction obj); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Instruction.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Instruction.java new file mode 100644 index 000000000..113be06ee --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Instruction.java @@ -0,0 +1,454 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.util.ByteSequence; + +/** + * Abstract super class for all Java byte codes. + * + * @version $Id: Instruction.java,v 1.10 2011/04/05 15:15:33 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class Instruction implements Cloneable, Serializable, Constants { + public short opcode = -1; + + public Instruction(short opcode) { + this.opcode = opcode; + } + + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + } + + public String getName() { + return Constants.OPCODE_NAMES[opcode]; + } + + /** + * 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. + * + * @return (shallow) copy of an instruction + */ + // GET RID OF THIS - make it throw an exception and track the callers + final public Instruction copy() { + // if overridden correctly can just return 'this' here + if (InstructionConstants.INSTRUCTIONS[opcode] != null) { // immutable instructions do not need copying + return this; + } else { + Instruction i = null; + try {// OPTIMIZE is clone the right thing to do here? it is horrible + i = (Instruction) clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + } + return i; + } + } + + /** + * Read an instruction bytecode from an input stream and return the appropriate object. + * + * @param file file to read from + * @return instruction object being read + */ + public static final Instruction readInstruction(ByteSequence bytes) throws IOException { + boolean wide = false; + short opcode = (short) bytes.readUnsignedByte(); + + if (opcode == Constants.WIDE) { + wide = true; + opcode = (short) bytes.readUnsignedByte(); + } + + Instruction constantInstruction = InstructionConstants.INSTRUCTIONS[opcode]; + + if (constantInstruction != null) { + return constantInstruction; + } + + Instruction obj = null; + try { + switch (opcode) { + case Constants.BIPUSH: + obj = new InstructionByte(Constants.BIPUSH, bytes.readByte()); + break; + case Constants.SIPUSH: + obj = new InstructionShort(Constants.SIPUSH, bytes.readShort()); + break; + case Constants.LDC: + obj = new InstructionCP(Constants.LDC, bytes.readUnsignedByte()); + break; + case Constants.LDC_W: + case Constants.LDC2_W: + obj = new InstructionCP(opcode, bytes.readUnsignedShort()); + break; + case Constants.ILOAD: + case Constants.LLOAD: + case Constants.FLOAD: + case Constants.DLOAD: + case Constants.ALOAD: + case Constants.ISTORE: + case Constants.LSTORE: + case Constants.FSTORE: + case Constants.DSTORE: + case Constants.ASTORE: + obj = new InstructionLV(opcode, wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte()); + break; + case Constants.IINC: + obj = new IINC(wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte(), wide ? bytes.readShort() + : bytes.readByte(), wide); + break; + case Constants.IFNULL: + case Constants.IFNONNULL: + case Constants.IFEQ: + case Constants.IFNE: + case Constants.IFLT: + case Constants.IFGE: + case Constants.IFGT: + case Constants.IFLE: + case Constants.IF_ICMPEQ: + case Constants.IF_ICMPNE: + case Constants.IF_ICMPLT: + case Constants.IF_ICMPGE: + case Constants.IF_ICMPGT: + case Constants.IF_ICMPLE: + case Constants.IF_ACMPEQ: + case Constants.IF_ACMPNE: + case Constants.GOTO: + case Constants.JSR: + obj = new InstructionBranch(opcode, bytes.readShort()); + break; + case Constants.GOTO_W: + case Constants.JSR_W: + obj = new InstructionBranch(opcode, bytes.readInt()); + break; + case Constants.TABLESWITCH: + obj = new TABLESWITCH(bytes); + break; + case Constants.LOOKUPSWITCH: + obj = new LOOKUPSWITCH(bytes); + break; + case Constants.RET: + obj = new RET(wide ? bytes.readUnsignedShort() : bytes.readUnsignedByte(), wide); + break; + case Constants.NEW: + obj = new InstructionCP(Constants.NEW, bytes.readUnsignedShort()); + break; + case Constants.GETSTATIC: + case Constants.PUTSTATIC: + case Constants.GETFIELD: + case Constants.PUTFIELD: + obj = new FieldInstruction(opcode, bytes.readUnsignedShort()); + break; + case Constants.INVOKEVIRTUAL: + case Constants.INVOKESPECIAL: + case Constants.INVOKESTATIC: + obj = new InvokeInstruction(opcode, bytes.readUnsignedShort()); + break; + case Constants.INVOKEINTERFACE: + obj = new INVOKEINTERFACE(bytes.readUnsignedShort(), bytes.readUnsignedByte(), bytes.readByte()); + break; + case Constants.INVOKEDYNAMIC: + obj = new InvokeDynamic(bytes.readUnsignedShort(),bytes.readUnsignedShort()); + break; + case Constants.NEWARRAY: + obj = new InstructionByte(Constants.NEWARRAY, bytes.readByte()); + break; + case Constants.ANEWARRAY: + case Constants.CHECKCAST: + obj = new InstructionCP(opcode, bytes.readUnsignedShort()); + break; + case Constants.INSTANCEOF: + obj = new InstructionCP(Constants.INSTANCEOF, bytes.readUnsignedShort()); + break; + case Constants.MULTIANEWARRAY: + obj = new MULTIANEWARRAY(bytes.readUnsignedShort(), bytes.readByte()); + break; + default: + throw new ClassGenException("Illegal opcode detected"); + } + } catch (ClassGenException e) { + throw e; + } catch (Exception e) { + throw new ClassGenException(e.toString()); + } + + return obj; + } + + /** + * @return Number of words consumed from stack by this instruction, or Constants.UNPREDICTABLE, if this can not be computed + * statically + */ + public int consumeStack(ConstantPool cpg) { + return Constants.CONSUME_STACK[opcode]; + } + + /** + * @return Number of words produced onto stack by this instruction, or Constants.UNPREDICTABLE, if this can not be computed + * statically + */ + public int produceStack(ConstantPool cpg) { + return Constants.stackEntriesProduced[opcode]; + } + + public short getOpcode() { + return opcode; + } + + public int getLength() { + // if it is zero, it should have been provided by an overriding implementation of getLength() + int len = Constants.iLen[opcode]; + assert len != 0; + // if (len == 0) { + // throw new IllegalStateException("Length not right for " + getName().toUpperCase()); + // } + return len; + } + + /** Some instructions may be reused, so don't do anything by default */ + void dispose() { + } + + @Override + public boolean equals(Object other) { + if (this.getClass() != Instruction.class) { + throw new RuntimeException("NO WAY " + this.getClass()); + } + if (!(other instanceof Instruction)) { + return false; + } + return ((Instruction) other).opcode == opcode; + + // IMPLEMENT EQUALS AND HASHCODE IN THE SUBTYPES! + + // Instruction i1 = this; + // Instruction i2 = (Instruction) that; + // if (i1.opcode == i2.opcode) { + // if (i1.isConstantInstruction()) { + // return i1.getValue().equals(i2.getValue()); + // } else if (i1.isIndexedInstruction()) { + // return i1.getIndex() == i2.getIndex(); + // } else if (i1.opcode == Constants.NEWARRAY) { + // return ((InstructionByte) i1).getTypecode() == ((InstructionByte) i2).getTypecode(); + // } else { + // return true; + // } + // } + // + // return false; + } + + @Override + public int hashCode() { + if (this.getClass() != Instruction.class) { + throw new RuntimeException("NO WAY " + this.getClass()); + } + return opcode * 37; + // int result = 17 + opcode * 37; + // if (isConstantInstruction()) { + // result = 37 * getValue().hashCode() + result; + // } else if (isIndexedInstruction()) { + // result = 37 * getIndex() + result; + // } else if (opcode == Constants.NEWARRAY) { + // result = 37 * ((InstructionByte) this).getTypecode() + result; + // } + // return result; + } + + public Type getType() { + return getType(null); + } + + public Type getType(ConstantPool cp) { + // if (types[opcode]==null) throw new RuntimeException(getName()+" is not a typed instruction"); + Type t = Constants.types[opcode]; + if (t != null) { + return t; + } + throw new RuntimeException("Do not know type for instruction " + getName() + "(" + opcode + ")"); + } + + public Number getValue() { + assert (instFlags[opcode] & CONSTANT_INST) == 0; + // if ((instFlags[opcode] & CONSTANT_INST) == 0) { + // throw new RuntimeException(getName() + " is not a constant instruction"); + // } + switch (opcode) { + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + return new Integer(opcode - ICONST_0); + default: + throw new IllegalStateException("Not implemented yet for " + getName()); + } + } + + public int getIndex() { + return -1; + } + + public void setIndex(int i) { + throw new IllegalStateException("Shouldnt be asking " + getName().toUpperCase()); + } + + public Object getValue(ConstantPool cpg) { + throw new IllegalStateException("Shouldnt be asking " + getName().toUpperCase()); + } + + public boolean isLoadInstruction() { + return (Constants.instFlags[opcode] & LOAD_INST) != 0; + } + + // remove these from here, leave them in the InstructionLV + public boolean isASTORE() { + return false; + } + + public boolean isALOAD() { + return false; + } + + public boolean isStoreInstruction() { + return (Constants.instFlags[opcode] & STORE_INST) != 0; + } + + // public boolean containsTarget(InstructionHandle ih) { + // throw new IllegalStateException("Dont ask!!"); + // } + + public boolean isJsrInstruction() { + return (Constants.instFlags[opcode] & JSR_INSTRUCTION) != 0; + } + + public boolean isConstantInstruction() { + return (Constants.instFlags[opcode] & CONSTANT_INST) != 0; + } + + public boolean isConstantPoolInstruction() { + return (Constants.instFlags[opcode] & CP_INST) != 0; + } + + public boolean isStackProducer() { + return Constants.stackEntriesProduced[opcode] != 0; + } + + public boolean isStackConsumer() { + return Constants.CONSUME_STACK[opcode] != 0; + } + + public boolean isIndexedInstruction() { + return (Constants.instFlags[opcode] & INDEXED) != 0; + } + + public boolean isArrayCreationInstruction() { + return opcode == NEWARRAY || opcode == ANEWARRAY || opcode == MULTIANEWARRAY; + } + + public ObjectType getLoadClassType(ConstantPool cpg) { + assert (Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0; + // if ((Constants.instFlags[opcode] & Constants.LOADCLASS_INST) == 0) { + // throw new IllegalStateException("This opcode " + opcode + " does not have the property " + // + Long.toHexString(Constants.LOADCLASS_INST)); + // } + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return t instanceof ObjectType ? (ObjectType) t : null; + } + + public boolean isReturnInstruction() { + return (Constants.instFlags[opcode] & RET_INST) != 0; + } + + // public boolean isGoto() { + // return opcode == GOTO || opcode == GOTO_W; + // } + + public boolean isLocalVariableInstruction() { + return (Constants.instFlags[opcode] & LV_INST) != 0; + } + + /** + * Long output format: 'name of opcode' "[" 'opcode number' "]" "(" 'length of instruction' ")" + */ + public String toString(boolean verbose) { + if (verbose) { + StringBuffer sb = new StringBuffer(); + sb.append(getName()).append("[").append(opcode).append("](size").append(Constants.iLen[opcode]).append(")"); + return sb.toString(); + } else { + return getName(); + } + } + + @Override + public String toString() { + return toString(true); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionBranch.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionBranch.java new file mode 100644 index 000000000..53fed8e52 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionBranch.java @@ -0,0 +1,338 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * Abstract super class for branching instructions like GOTO, IFEQ, etc.. Branch instructions may have a variable length, namely + * GOTO, JSR, LOOKUPSWITCH and TABLESWITCH. A branch instruction may be talking in terms of absolute destination (targetIndex) or + * about an instruction it doesnt yet know the position if (targetInstruction). targetInstruction (if set) overrides targetIndex + * + * @see InstructionList + * @version $Id: InstructionBranch.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class InstructionBranch extends Instruction implements InstructionTargeter { + private static final int UNSET = -1; + + protected int targetIndex = UNSET; // Branch target relative to this + // instruction + protected InstructionHandle targetInstruction; // Target object in + // instruction list + protected int positionOfThisInstruction; // for calculating relative branch + + // destinations! + + public InstructionBranch(short opcode, InstructionHandle target) { + super(opcode); + setTarget(target); + } + + public InstructionBranch(short opcode, int index) { + super(opcode); + this.targetIndex = index; + } + + public InstructionBranch(short opcode) { + super(opcode); + } + + public void dump(DataOutputStream out) throws IOException { + int target = getTargetOffset(); + + if (Math.abs(target) >= 32767 && opcode != GOTO_W && opcode != JSR_W) { + throw new ClassGenException("Branch target offset too large for short. Instruction: " + getName().toUpperCase() + "(" + + opcode + ")"); + } + + out.writeByte(opcode); + + switch (opcode) { + + case GOTO_W: + case JSR_W: + out.writeInt(target); + break; + + 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 IFEQ: + case IFLE: + case IFLT: + case IFGT: + case IFNE: + case IFGE: + case IFNULL: + case IFNONNULL: + case GOTO: + case JSR: + out.writeShort(target); + break; + + default: + throw new IllegalStateException("Don't know how to write out " + getName().toUpperCase()); + } + + } + + protected int getTargetOffset() { + if (targetInstruction == null && targetIndex == UNSET) { + throw new ClassGenException("Target of " + super.toString(true) + " is unknown"); + } + + if (targetInstruction == null) { + return targetIndex; + } else { + return targetInstruction.getPosition() - positionOfThisInstruction; + } + } + + /** + * 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) { + int i = getTargetOffset(); + + positionOfThisInstruction += offset; + + if (Math.abs(i) >= 32767 - max_offset && opcode != JSR_W && opcode != GOTO_W) { + // Try and promote it to wide if we can + if (opcode == JSR || opcode == GOTO) { + if (opcode == JSR) { + opcode = JSR_W; + } else { + opcode = GOTO_W; + } + return 2; // instruction jump destination grows from a short to a long + } else { + throw new IllegalStateException("Unable to pack method, jump (with opcode=" + opcode + ") is too far: " + + Math.abs(i)); + } + } + + return 0; + } + + /** + * Long output format: + * + * @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 (targetInstruction != null) { + if (targetInstruction.getInstruction() == this) { + t = "<points to itself>"; + } else if (targetInstruction.getInstruction() == null) { + t = "<null destination>"; + } else { + t = targetInstruction.getInstruction().toString(false); + } + } + } else { + if (targetInstruction != null) { + targetIndex = getTargetOffset(); + t = "" + (targetIndex + positionOfThisInstruction); + } + } + + return s + " -> " + t; + } + + /** + * @return target offset in byte code + */ + public final int getIndex() { + return targetIndex; + } + + /** + * @return target of branch instruction + */ + public InstructionHandle getTarget() { + return targetInstruction; + } + + /** + * Set branch target + * + * @param target branch target + */ + public void setTarget(InstructionHandle target) { + notifyTarget(this.targetInstruction, target, this); + this.targetInstruction = target; + } + + /** + * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen + */ + static final void notifyTarget(InstructionHandle oldHandle, InstructionHandle newHandle, InstructionTargeter t) { + if (oldHandle != null) { + oldHandle.removeTargeter(t); + } + if (newHandle != null) { + newHandle.addTargeter(t); + } + } + + /** + * Update the target destination for this instruction. If an oldHandle is provided it is checked to verify that is where the + * target currently points to before changing it. + * + * @param oldHandle old target + * @param newHandle new target + */ + public void updateTarget(InstructionHandle oldHandle, InstructionHandle newHandle) { + if (targetInstruction == oldHandle) { + setTarget(newHandle); + } else { + throw new ClassGenException("Not targeting " + oldHandle + ", but " + targetInstruction); + } + } + + /** + * @return true, if ih is target of this instruction + */ + public boolean containsTarget(InstructionHandle ih) { + return targetInstruction == ih; + } + + /** + * Inform target that it's not targeted anymore. + */ + void dispose() { + setTarget(null); + targetIndex = -1; + positionOfThisInstruction = -1; + } + + public Type getType(ConstantPool cp) { + if ((Constants.instFlags[opcode] & Constants.JSR_INSTRUCTION) != 0) { + return new ReturnaddressType(physicalSuccessor()); + } + return super.getType(cp); + } + + /** + * 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.targetInstruction; + + // 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(); + } + + public boolean isIfInstruction() { + return (Constants.instFlags[opcode] & Constants.IF_INST) != 0; + } + + /** + * Only equal if they are the same branch instruction - otherwise too risky as the targets may only temporarily be pointing at + * the same destination. + */ + public boolean equals(Object other) { + return this == other; + } + + public int hashCode() { + int result = 17; + result = opcode * 37 + result; + return result; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionByte.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionByte.java new file mode 100644 index 000000000..5ba8a9abe --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionByte.java @@ -0,0 +1,108 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * Instruction that needs one byte + */ +public class InstructionByte extends Instruction { + private final byte theByte; + + public InstructionByte(short opcode, byte b) { + super(opcode); + this.theByte = b; + } + + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + out.writeByte(theByte); + } + + public String toString(boolean verbose) { + return super.toString(verbose) + " " + theByte; + } + + /** + * For supporting NEWARRAY + * + * @return typecode of the array + */ + public final byte getTypecode() { + return theByte; + } + + /** + * For supporting NEWARRAY + * + * @return type of the array + */ + public final Type getType() { + return new ArrayType(BasicType.getType(theByte), 1); + } + + public boolean equals(Object other) { + if (!(other instanceof InstructionByte)) { + return false; + } + InstructionByte o = (InstructionByte) other; + return o.opcode == opcode && o.theByte == theByte; + } + + public int hashCode() { + return opcode * 37 + theByte; + } +}
\ No newline at end of file diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCLV.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCLV.java new file mode 100644 index 000000000..85ae588e5 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCLV.java @@ -0,0 +1,27 @@ +package org.aspectj.apache.bcel.generic; + +/** + * A small subclass of the local variable accessing instruction class InstructionLV - this subclass does + * not allow the index to be altered. + */ +public class InstructionCLV extends InstructionLV { + + public InstructionCLV(short opcode) { + super(opcode); + } + + public InstructionCLV(short opcode,int localVariableIndex) { + super(opcode,localVariableIndex); + } + + public void setIndex(int localVariableIndex) { + if (localVariableIndex!=getIndex()) { + throw new ClassGenException("Do not attempt to modify the index to '"+localVariableIndex+"' for this constant instruction: "+this); + } + } + + public boolean canSetIndex() { + return false; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCP.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCP.java new file mode 100644 index 000000000..09222d6a4 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionCP.java @@ -0,0 +1,224 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Constant; +import org.aspectj.apache.bcel.classfile.ConstantClass; +import org.aspectj.apache.bcel.classfile.ConstantDouble; +import org.aspectj.apache.bcel.classfile.ConstantFloat; +import org.aspectj.apache.bcel.classfile.ConstantInteger; +import org.aspectj.apache.bcel.classfile.ConstantLong; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ConstantString; +import org.aspectj.apache.bcel.classfile.ConstantUtf8; + +/** + * Class for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, etc. + * + * @version $Id: InstructionCP.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class InstructionCP extends Instruction { + protected int index; + + public InstructionCP(short opcode, int index) { + super(opcode); + this.index = index; + } + + @Override + public void dump(DataOutputStream out) throws IOException { + if (opcode == LDC_W && index < 256) { + out.writeByte(LDC); + out.writeByte(index); + } else { + out.writeByte(opcode); + if (Constants.iLen[opcode] == 2) { + if (index > 255) { + throw new IllegalStateException(); + } + out.writeByte(index); + } else { + out.writeShort(index); + } + } + } + + @Override + public int getLength() { + if (opcode == LDC_W && index < 256) { + return 2; + } else { + return super.getLength(); + } + } + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool + * index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + @Override + 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.aspectj.apache.bcel.Constants.OPCODE_NAMES[opcode] + " " + str; + } + + /** + * @return index in constant pool referred by this instruction. + */ + @Override + public final int getIndex() { + return index; + } + + @Override + public void setIndex(int index) { + this.index = index; + if (this.index > 255 && opcode == LDC) { + // promote it + opcode = LDC_W; + } + } + + @Override + public Type getType(ConstantPool cpg) { + switch (cpg.getConstant(index).getTag()) { + case CONSTANT_String: + return Type.STRING; + case CONSTANT_Float: + return Type.FLOAT; + case CONSTANT_Integer: + return Type.INT; + case CONSTANT_Long: + return Type.LONG; + case CONSTANT_Double: + return Type.DOUBLE; + case CONSTANT_Class: + String name = cpg.getConstantString_CONSTANTClass(index); + // ConstantPool cp = cpg.getConstantPool(); + // String name = cp.getConstantString(index, CONSTANT_Class); + if (!name.startsWith("[")) { + StringBuffer sb = new StringBuffer(); + sb.append("L").append(name).append(";"); + return Type.getType(sb.toString()); + } else { + return Type.getType(name); + } + default: + throw new RuntimeException("Unknown or invalid constant type at " + index); + } + } + + @Override + public Object getValue(ConstantPool constantPool) { + Constant constant = constantPool.getConstant(index); + + switch (constant.getTag()) { + case Constants.CONSTANT_String: + int i = ((ConstantString) constant).getStringIndex(); + constant = constantPool.getConstant(i); + return ((ConstantUtf8) constant).getValue(); + + case Constants.CONSTANT_Float: + return ((ConstantFloat) constant).getValue(); + + case Constants.CONSTANT_Integer: + return ((ConstantInteger) constant).getValue(); + + case Constants.CONSTANT_Long: + return ((ConstantLong) constant).getValue(); + + case Constants.CONSTANT_Double: + return ((ConstantDouble) constant).getValue(); + default: + throw new RuntimeException("Unknown or invalid constant type at " + index); + } + } + + public boolean equals(Object other) { + if (!(other instanceof InstructionCP)) { + return false; + } + InstructionCP o = (InstructionCP) other; + return o.opcode == opcode && o.index == index; + } + + public int hashCode() { + return opcode * 37 + index; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionConstants.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionConstants.java new file mode 100644 index 000000000..e6f884793 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionConstants.java @@ -0,0 +1,379 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.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: InstructionConstants.java,v 1.4 2008/08/13 18:18:22 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public interface InstructionConstants { + /** Predefined instruction objects + */ + public static final Instruction NOP = new Instruction(Constants.NOP); + public static final Instruction ACONST_NULL = new Instruction(Constants.ACONST_NULL); + public static final Instruction ICONST_M1 = new Instruction(Constants.ICONST_M1); + public static final Instruction ICONST_0 = new Instruction(Constants.ICONST_0); + public static final Instruction ICONST_1 = new Instruction(Constants.ICONST_1); + public static final Instruction ICONST_2 = new Instruction(Constants.ICONST_2); + public static final Instruction ICONST_3 = new Instruction(Constants.ICONST_3); + public static final Instruction ICONST_4 = new Instruction(Constants.ICONST_4); + public static final Instruction ICONST_5 = new Instruction(Constants.ICONST_5); + public static final Instruction LCONST_0 = new Instruction(Constants.LCONST_0); + public static final Instruction LCONST_1 = new Instruction(Constants.LCONST_1); + public static final Instruction FCONST_0 = new Instruction(Constants.FCONST_0); + public static final Instruction FCONST_1 = new Instruction(Constants.FCONST_1); + public static final Instruction FCONST_2 = new Instruction(Constants.FCONST_2); + public static final Instruction DCONST_0 = new Instruction(Constants.DCONST_0); + public static final Instruction DCONST_1 = new Instruction(Constants.DCONST_1); + public static final Instruction IALOAD = new Instruction(Constants.IALOAD); + public static final Instruction LALOAD = new Instruction(Constants.LALOAD); + public static final Instruction FALOAD = new Instruction(Constants.FALOAD); + public static final Instruction DALOAD = new Instruction(Constants.DALOAD); + public static final Instruction AALOAD = new Instruction(Constants.AALOAD); + public static final Instruction BALOAD = new Instruction(Constants.BALOAD); + public static final Instruction CALOAD = new Instruction(Constants.CALOAD); + public static final Instruction SALOAD = new Instruction(Constants.SALOAD); + public static final Instruction IASTORE = new Instruction(Constants.IASTORE); + public static final Instruction LASTORE = new Instruction(Constants.LASTORE); + public static final Instruction FASTORE = new Instruction(Constants.FASTORE); + public static final Instruction DASTORE = new Instruction(Constants.DASTORE); + public static final Instruction AASTORE = new Instruction(Constants.AASTORE); + public static final Instruction BASTORE = new Instruction(Constants.BASTORE); + public static final Instruction CASTORE = new Instruction(Constants.CASTORE); + public static final Instruction SASTORE = new Instruction(Constants.SASTORE); + public static final Instruction POP = new Instruction(Constants.POP); + public static final Instruction POP2 = new Instruction(Constants.POP2); + public static final Instruction DUP = new Instruction(Constants.DUP); + public static final Instruction DUP_X1 = new Instruction(Constants.DUP_X1); + public static final Instruction DUP_X2 = new Instruction(Constants.DUP_X2); + public static final Instruction DUP2 = new Instruction(Constants.DUP2); + public static final Instruction DUP2_X1 = new Instruction(Constants.DUP2_X1); + public static final Instruction DUP2_X2 = new Instruction(Constants.DUP2_X2); + public static final Instruction SWAP = new Instruction(Constants.SWAP); + public static final Instruction IADD = new Instruction(Constants.IADD); + public static final Instruction LADD = new Instruction(Constants.LADD); + public static final Instruction FADD = new Instruction(Constants.FADD); + public static final Instruction DADD = new Instruction(Constants.DADD); + public static final Instruction ISUB = new Instruction(Constants.ISUB); + public static final Instruction LSUB = new Instruction(Constants.LSUB); + public static final Instruction FSUB = new Instruction(Constants.FSUB); + public static final Instruction DSUB = new Instruction(Constants.DSUB); + public static final Instruction IMUL = new Instruction(Constants.IMUL); + public static final Instruction LMUL = new Instruction(Constants.LMUL); + public static final Instruction FMUL = new Instruction(Constants.FMUL); + public static final Instruction DMUL = new Instruction(Constants.DMUL); + public static final Instruction IDIV = new Instruction(Constants.IDIV); + public static final Instruction LDIV = new Instruction(Constants.LDIV); + public static final Instruction FDIV = new Instruction(Constants.FDIV); + public static final Instruction DDIV = new Instruction(Constants.DDIV); + public static final Instruction IREM = new Instruction(Constants.IREM); + public static final Instruction LREM = new Instruction(Constants.LREM); + public static final Instruction FREM = new Instruction(Constants.FREM); + public static final Instruction DREM = new Instruction(Constants.DREM); + public static final Instruction INEG = new Instruction(Constants.INEG); + public static final Instruction LNEG = new Instruction(Constants.LNEG); + public static final Instruction FNEG = new Instruction(Constants.FNEG); + public static final Instruction DNEG = new Instruction(Constants.DNEG); + public static final Instruction ISHL = new Instruction(Constants.ISHL); + public static final Instruction LSHL = new Instruction(Constants.LSHL); + public static final Instruction ISHR = new Instruction(Constants.ISHR); + public static final Instruction LSHR = new Instruction(Constants.LSHR); + public static final Instruction IUSHR = new Instruction(Constants.IUSHR); + public static final Instruction LUSHR = new Instruction(Constants.LUSHR); + public static final Instruction IAND = new Instruction(Constants.IAND); + public static final Instruction LAND = new Instruction(Constants.LAND); + public static final Instruction IOR = new Instruction(Constants.IOR); + public static final Instruction LOR = new Instruction(Constants.LOR); + public static final Instruction IXOR = new Instruction(Constants.IXOR); + public static final Instruction LXOR = new Instruction(Constants.LXOR); + public static final Instruction I2L = new Instruction(Constants.I2L); + public static final Instruction I2F = new Instruction(Constants.I2F); + public static final Instruction I2D = new Instruction(Constants.I2D); + public static final Instruction L2I = new Instruction(Constants.L2I); + public static final Instruction L2F = new Instruction(Constants.L2F); + public static final Instruction L2D = new Instruction(Constants.L2D); + public static final Instruction F2I = new Instruction(Constants.F2I); + public static final Instruction F2L = new Instruction(Constants.F2L); + public static final Instruction F2D = new Instruction(Constants.F2D); + public static final Instruction D2I = new Instruction(Constants.D2I); + public static final Instruction D2L = new Instruction(Constants.D2L); + public static final Instruction D2F = new Instruction(Constants.D2F); + public static final Instruction I2B = new Instruction(Constants.I2B); + public static final Instruction I2C = new Instruction(Constants.I2C); + public static final Instruction I2S = new Instruction(Constants.I2S); + public static final Instruction LCMP = new Instruction(Constants.LCMP); + public static final Instruction FCMPL = new Instruction(Constants.FCMPL); + public static final Instruction FCMPG = new Instruction(Constants.FCMPG); + public static final Instruction DCMPL = new Instruction(Constants.DCMPL); + public static final Instruction DCMPG = new Instruction(Constants.DCMPG); + public static final Instruction IRETURN = new Instruction(Constants.IRETURN); + public static final Instruction LRETURN = new Instruction(Constants.LRETURN); + public static final Instruction FRETURN = new Instruction(Constants.FRETURN); + public static final Instruction DRETURN = new Instruction(Constants.DRETURN); + public static final Instruction ARETURN = new Instruction(Constants.ARETURN); + public static final Instruction RETURN = new Instruction(Constants.RETURN); + public static final Instruction ARRAYLENGTH = new Instruction(Constants.ARRAYLENGTH); + public static final Instruction ATHROW = new Instruction(Constants.ATHROW); + public static final Instruction MONITORENTER = new Instruction(Constants.MONITORENTER); + public static final Instruction MONITOREXIT = new Instruction(Constants.MONITOREXIT); + public static final Instruction IMPDEP1 = new Instruction(Constants.IMPDEP1); + public static final Instruction IMPDEP2 = new Instruction(Constants.IMPDEP2); + + // You can use these constants in multiple places safely, any attempt to change the index + // for these constants will cause an exception + public static final InstructionLV THIS = new InstructionCLV(Constants.ALOAD,0); + public static final InstructionLV ALOAD_0 = new InstructionCLV(Constants.ALOAD_0); + public static final InstructionLV ALOAD_1 = new InstructionCLV(Constants.ALOAD_1); + public static final InstructionLV ALOAD_2 = new InstructionCLV(Constants.ALOAD_2); + public static final InstructionLV ALOAD_3 = new InstructionCLV(Constants.ALOAD_3); + public static final InstructionLV ILOAD_0 = new InstructionCLV(Constants.ILOAD_0); + public static final InstructionLV ILOAD_1 = new InstructionCLV(Constants.ILOAD_1); + public static final InstructionLV ILOAD_2 = new InstructionCLV(Constants.ILOAD_2); + public static final InstructionLV ILOAD_3 = new InstructionCLV(Constants.ILOAD_3); + public static final InstructionLV DLOAD_0 = new InstructionCLV(Constants.DLOAD_0); + public static final InstructionLV DLOAD_1 = new InstructionCLV(Constants.DLOAD_1); + public static final InstructionLV DLOAD_2 = new InstructionCLV(Constants.DLOAD_2); + public static final InstructionLV DLOAD_3 = new InstructionCLV(Constants.DLOAD_3); + public static final InstructionLV FLOAD_0 = new InstructionCLV(Constants.FLOAD_0); + public static final InstructionLV FLOAD_1 = new InstructionCLV(Constants.FLOAD_1); + public static final InstructionLV FLOAD_2 = new InstructionCLV(Constants.FLOAD_2); + public static final InstructionLV FLOAD_3 = new InstructionCLV(Constants.FLOAD_3); + public static final InstructionLV LLOAD_0 = new InstructionCLV(Constants.LLOAD_0); + public static final InstructionLV LLOAD_1 = new InstructionCLV(Constants.LLOAD_1); + public static final InstructionLV LLOAD_2 = new InstructionCLV(Constants.LLOAD_2); + public static final InstructionLV LLOAD_3 = new InstructionCLV(Constants.LLOAD_3); + public static final InstructionLV ASTORE_0 = new InstructionCLV(Constants.ASTORE_0); + public static final InstructionLV ASTORE_1 = new InstructionCLV(Constants.ASTORE_1); + public static final InstructionLV ASTORE_2 = new InstructionCLV(Constants.ASTORE_2); + public static final InstructionLV ASTORE_3 = new InstructionCLV(Constants.ASTORE_3); + public static final InstructionLV ISTORE_0 = new InstructionCLV(Constants.ISTORE_0); + public static final InstructionLV ISTORE_1 = new InstructionCLV(Constants.ISTORE_1); + public static final InstructionLV ISTORE_2 = new InstructionCLV(Constants.ISTORE_2); + public static final InstructionLV ISTORE_3 = new InstructionCLV(Constants.ISTORE_3); + public static final InstructionLV LSTORE_0 = new InstructionCLV(Constants.LSTORE_0); + public static final InstructionLV LSTORE_1 = new InstructionCLV(Constants.LSTORE_1); + public static final InstructionLV LSTORE_2 = new InstructionCLV(Constants.LSTORE_2); + public static final InstructionLV LSTORE_3 = new InstructionCLV(Constants.LSTORE_3); + public static final InstructionLV FSTORE_0 = new InstructionCLV(Constants.FSTORE_0); + public static final InstructionLV FSTORE_1 = new InstructionCLV(Constants.FSTORE_1); + public static final InstructionLV FSTORE_2 = new InstructionCLV(Constants.FSTORE_2); + public static final InstructionLV FSTORE_3 = new InstructionCLV(Constants.FSTORE_3); + public static final InstructionLV DSTORE_0 = new InstructionCLV(Constants.DSTORE_0); + public static final InstructionLV DSTORE_1 = new InstructionCLV(Constants.DSTORE_1); + public static final InstructionLV DSTORE_2 = new InstructionCLV(Constants.DSTORE_2); + public static final InstructionLV DSTORE_3 = new InstructionCLV(Constants.DSTORE_3); + + + /** 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; + INSTRUCTIONS[Constants.IMPDEP1] = IMPDEP1; + INSTRUCTIONS[Constants.IMPDEP2] = IMPDEP2; + + INSTRUCTIONS[Constants.ALOAD_0] = ALOAD_0;INSTRUCTIONS[Constants.ALOAD_1] = ALOAD_1; + INSTRUCTIONS[Constants.ALOAD_2] = ALOAD_2;INSTRUCTIONS[Constants.ALOAD_3] = ALOAD_3; + INSTRUCTIONS[Constants.LLOAD_0] = LLOAD_0;INSTRUCTIONS[Constants.LLOAD_1] = LLOAD_1; + INSTRUCTIONS[Constants.LLOAD_2] = LLOAD_2;INSTRUCTIONS[Constants.LLOAD_3] = LLOAD_3; + INSTRUCTIONS[Constants.DLOAD_0] = DLOAD_0;INSTRUCTIONS[Constants.DLOAD_1] = DLOAD_1; + INSTRUCTIONS[Constants.DLOAD_2] = DLOAD_2;INSTRUCTIONS[Constants.DLOAD_3] = DLOAD_3; + INSTRUCTIONS[Constants.FLOAD_0] = FLOAD_0;INSTRUCTIONS[Constants.FLOAD_1] = FLOAD_1; + INSTRUCTIONS[Constants.FLOAD_2] = FLOAD_2;INSTRUCTIONS[Constants.FLOAD_3] = FLOAD_3; + INSTRUCTIONS[Constants.ILOAD_0] = ILOAD_0;INSTRUCTIONS[Constants.ILOAD_1] = ILOAD_1; + INSTRUCTIONS[Constants.ILOAD_2] = ILOAD_2;INSTRUCTIONS[Constants.ILOAD_3] = ILOAD_3; + + INSTRUCTIONS[Constants.ASTORE_0] = ASTORE_0;INSTRUCTIONS[Constants.ASTORE_1] = ASTORE_1; + INSTRUCTIONS[Constants.ASTORE_2] = ASTORE_2;INSTRUCTIONS[Constants.ASTORE_3] = ASTORE_3; + INSTRUCTIONS[Constants.LSTORE_0] = LSTORE_0;INSTRUCTIONS[Constants.LSTORE_1] = LSTORE_1; + INSTRUCTIONS[Constants.LSTORE_2] = LSTORE_2;INSTRUCTIONS[Constants.LSTORE_3] = LSTORE_3; + INSTRUCTIONS[Constants.DSTORE_0] = DSTORE_0;INSTRUCTIONS[Constants.DSTORE_1] = DSTORE_1; + INSTRUCTIONS[Constants.DSTORE_2] = DSTORE_2;INSTRUCTIONS[Constants.DSTORE_3] = DSTORE_3; + INSTRUCTIONS[Constants.FSTORE_0] = FSTORE_0;INSTRUCTIONS[Constants.FSTORE_1] = FSTORE_1; + INSTRUCTIONS[Constants.FSTORE_2] = FSTORE_2;INSTRUCTIONS[Constants.FSTORE_3] = FSTORE_3; + INSTRUCTIONS[Constants.ISTORE_0] = ISTORE_0;INSTRUCTIONS[Constants.ISTORE_1] = ISTORE_1; + INSTRUCTIONS[Constants.ISTORE_2] = ISTORE_2;INSTRUCTIONS[Constants.ISTORE_3] = ISTORE_3; + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionFactory.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionFactory.java new file mode 100644 index 000000000..4e1e6c8a8 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionFactory.java @@ -0,0 +1,771 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.Utility; + +/** + * 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: InstructionFactory.java,v 1.7 2010/08/23 20:44:10 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see Constants + */ +public class InstructionFactory implements InstructionConstants { + protected ClassGen cg; + protected ConstantPool cp; + + public InstructionFactory(ClassGen cg, ConstantPool cp) { + this.cg = cg; + this.cp = cp; + } + + public InstructionFactory(ClassGen cg) { + this(cg, cg.getConstantPool()); + } + + public InstructionFactory(ConstantPool cp) { + this(null, cp); + } + + public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind) { + return createInvoke(class_name, name, ret_type, arg_types, kind, false); + } + + /** + * 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 + * @param isInterface for an invokestatic on an interface allows us to tell this method the target is an interface + * @see Constants + */ + public InvokeInstruction createInvoke(String class_name, String name, Type ret_type, Type[] arg_types, short kind, boolean isInterface) { + + String signature = Utility.toMethodSignature(ret_type, arg_types); + + int index; + if (kind == Constants.INVOKEINTERFACE || isInterface) { + index = cp.addInterfaceMethodref(class_name, name, signature); + } else if (kind == Constants.INVOKEDYNAMIC){ + throw new IllegalStateException("NYI"); + } else { + index = cp.addMethodref(class_name, name, signature); + } + + switch (kind) { + case Constants.INVOKESPECIAL: + return new InvokeInstruction(Constants.INVOKESPECIAL, index); + case Constants.INVOKEVIRTUAL: + return new InvokeInstruction(Constants.INVOKEVIRTUAL, index); + case Constants.INVOKESTATIC: + return new InvokeInstruction(Constants.INVOKESTATIC, index); + case Constants.INVOKEINTERFACE: + int nargs = 0; + for (int i = 0; i < arg_types.length; i++) { + nargs += arg_types[i].getSize(); + } + return new INVOKEINTERFACE(index, nargs + 1, 0); + default: + throw new RuntimeException("Oops: Unknown invoke kind:" + kind); + } + } + + public InvokeInstruction createInvoke(String class_name, String name, String signature, short kind) { + int index; + if (kind == Constants.INVOKEINTERFACE) { + index = cp.addInterfaceMethodref(class_name, name, signature); + } else if (kind == Constants.INVOKEDYNAMIC){ + throw new IllegalStateException("NYI"); + } else { + index = cp.addMethodref(class_name, name, signature); + } + + switch (kind) { + case Constants.INVOKESPECIAL: + return new InvokeInstruction(Constants.INVOKESPECIAL, index); + case Constants.INVOKEVIRTUAL: + return new InvokeInstruction(Constants.INVOKEVIRTUAL, index); + case Constants.INVOKESTATIC: + return new InvokeInstruction(Constants.INVOKESTATIC, index); + case Constants.INVOKEINTERFACE: + Type[] argumentTypes = Type.getArgumentTypes(signature); + int nargs = 0; + for (int i = 0; i < argumentTypes.length; i++) {// Count size of arguments + nargs += argumentTypes[i].getSize(); + } + return new INVOKEINTERFACE(index, nargs + 1, 0); + default: + throw new RuntimeException("Oops: Unknown invoke kind:" + kind); + } + } + + public static Instruction createALOAD(int n) { + if (n < 4) { + return new InstructionLV((short) (Constants.ALOAD_0 + n)); + } + return new InstructionLV(Constants.ALOAD, n); + } + + public static Instruction createASTORE(int n) { + if (n < 4) { + return new InstructionLV((short) (Constants.ASTORE_0 + n)); + } + return new InstructionLV(Constants.ASTORE, n); + } + + /** + * Uses PUSH to push a constant value onto the stack. + * + * @param value must be of type Number, Boolean, Character or String + */ + // OPTIMIZE callers should use the PUSH methods where possible if they know the types + public Instruction createConstant(Object value) { + Instruction instruction; + + if (value instanceof Number) { + instruction = InstructionFactory.PUSH(cp, (Number) value); + } else if (value instanceof String) { + instruction = InstructionFactory.PUSH(cp, (String) value); + } else if (value instanceof Boolean) { + instruction = InstructionFactory.PUSH(cp, (Boolean) value); + } else if (value instanceof Character) { + instruction = InstructionFactory.PUSH(cp, (Character) value); + } else if (value instanceof ObjectType) { + instruction = InstructionFactory.PUSH(cp, (ObjectType) value); + } else { + throw new ClassGenException("Illegal type: " + value.getClass()); + } + + return instruction; + } + + /** + * 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 FieldInstruction(Constants.GETFIELD, index); + case Constants.PUTFIELD: + return new FieldInstruction(Constants.PUTFIELD, index); + case Constants.GETSTATIC: + return new FieldInstruction(Constants.GETSTATIC, index); + case Constants.PUTSTATIC: + return new FieldInstruction(Constants.PUTSTATIC, index); + + default: + throw new RuntimeException("Oops: Unknown getfield kind:" + kind); + } + } + + /** + * Create reference to `this' + */ + public static Instruction createThis() { + return new InstructionLV(Constants.ALOAD, 0); + } + + /** + * Create typed return + */ + public static Instruction 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); + } + } + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static Instruction createPop(int size) { + return (size == 2) ? POP2 : POP; + } + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static Instruction createDup(int size) { + return (size == 2) ? DUP2 : DUP; + } + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static Instruction createDup_2(int size) { + return (size == 2) ? DUP2_X2 : DUP_X2; + } + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static Instruction createDup_1(int size) { + return (size == 2) ? DUP2_X1 : DUP_X1; + } + + /** + * @param index index of local variable + */ + public static InstructionLV 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 InstructionLV(Constants.ISTORE, index); + case Constants.T_FLOAT: + return new InstructionLV(Constants.FSTORE, index); + case Constants.T_DOUBLE: + return new InstructionLV(Constants.DSTORE, index); + case Constants.T_LONG: + return new InstructionLV(Constants.LSTORE, index); + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return new InstructionLV(Constants.ASTORE, index); + default: + throw new RuntimeException("Invalid type " + type); + } + } + + /** + * @param index index of local variable + */ + public static InstructionLV 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 InstructionLV(Constants.ILOAD, index); + case Constants.T_FLOAT: + return new InstructionLV(Constants.FLOAD, index); + case Constants.T_DOUBLE: + return new InstructionLV(Constants.DLOAD, index); + case Constants.T_LONG: + return new InstructionLV(Constants.LLOAD, index); + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return new InstructionLV(Constants.ALOAD, index); + default: + throw new RuntimeException("Invalid type " + type); + } + } + + /** + * @param type type of elements of array, i.e., array.getElementType() + */ + public static Instruction 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 Instruction 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); + } + } + + private static final char[] shortNames = { 'C', 'F', 'D', 'B', 'S', 'I', 'L' }; + + /** + * 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; + } + + if (src == Constants.T_DOUBLE) { + switch (dest) { + case Constants.T_FLOAT: + return InstructionConstants.D2F; + case Constants.T_INT: + return InstructionConstants.D2I; + case Constants.T_LONG: + return InstructionConstants.D2L; + } + } else if (src == Constants.T_FLOAT) { + switch (dest) { + case Constants.T_DOUBLE: + return InstructionConstants.F2D; + case Constants.T_INT: + return InstructionConstants.F2I; + case Constants.T_LONG: + return InstructionConstants.F2L; + } + } else if (src == Constants.T_INT) { + switch (dest) { + case Constants.T_BYTE: + return InstructionConstants.I2B; + case Constants.T_CHAR: + return InstructionConstants.I2C; + case Constants.T_DOUBLE: + return InstructionConstants.I2D; + case Constants.T_FLOAT: + return InstructionConstants.I2F; + case Constants.T_LONG: + return InstructionConstants.I2L; + case Constants.T_SHORT: + return InstructionConstants.I2S; + } + } else if (src == Constants.T_LONG) { + switch (dest) { + case Constants.T_DOUBLE: + return InstructionConstants.L2D; + case Constants.T_FLOAT: + return InstructionConstants.L2F; + case Constants.T_INT: + return InstructionConstants.L2I; + } + } + + // String name = "org.aspectj.apache.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); + // } + + return null; + // return i; + } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) { + if (dest_type instanceof ArrayType) { + return new InstructionCP(Constants.CHECKCAST, cp.addArrayClass((ArrayType) dest_type)); + } else { + return new InstructionCP(Constants.CHECKCAST, cp.addClass(((ObjectType) dest_type).getClassName())); + } + } else { + throw new RuntimeException("Can not cast " + src_type + " to " + dest_type); + } + } + + public FieldInstruction createGetField(String class_name, String name, Type t) { + return new FieldInstruction(Constants.GETFIELD, cp.addFieldref(class_name, name, t.getSignature())); + } + + public FieldInstruction createGetStatic(String class_name, String name, Type t) { + return new FieldInstruction(Constants.GETSTATIC, cp.addFieldref(class_name, name, t.getSignature())); + } + + public FieldInstruction createPutField(String class_name, String name, Type t) { + return new FieldInstruction(Constants.PUTFIELD, cp.addFieldref(class_name, name, t.getSignature())); + } + + public FieldInstruction createPutStatic(String class_name, String name, Type t) { + return new FieldInstruction(Constants.PUTSTATIC, cp.addFieldref(class_name, name, t.getSignature())); + } + + public Instruction createCheckCast(ReferenceType t) { + if (t instanceof ArrayType) { + return new InstructionCP(Constants.CHECKCAST, cp.addArrayClass((ArrayType) t)); + } else { + return new InstructionCP(Constants.CHECKCAST, cp.addClass((ObjectType) t)); + } + } + + public Instruction createInstanceOf(ReferenceType t) { + if (t instanceof ArrayType) { + return new InstructionCP(Constants.INSTANCEOF, cp.addArrayClass((ArrayType) t)); + } else { + return new InstructionCP(Constants.INSTANCEOF, cp.addClass((ObjectType) t)); + } + } + + public Instruction createNew(ObjectType t) { + return new InstructionCP(Constants.NEW, cp.addClass(t)); + } + + public Instruction 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 InstructionCP(Constants.ANEWARRAY, cp.addClass((ObjectType) t)); + } else if (t instanceof ArrayType) { + return new InstructionCP(Constants.ANEWARRAY, cp.addArrayClass((ArrayType) t)); + } else { + return new InstructionByte(Constants.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 InstructionBranch createBranchInstruction(short opcode, InstructionHandle target) { + switch (opcode) { + case Constants.IFEQ: + return new InstructionBranch(Constants.IFEQ, target); + case Constants.IFNE: + return new InstructionBranch(Constants.IFNE, target); + case Constants.IFLT: + return new InstructionBranch(Constants.IFLT, target); + case Constants.IFGE: + return new InstructionBranch(Constants.IFGE, target); + case Constants.IFGT: + return new InstructionBranch(Constants.IFGT, target); + case Constants.IFLE: + return new InstructionBranch(Constants.IFLE, target); + case Constants.IF_ICMPEQ: + return new InstructionBranch(Constants.IF_ICMPEQ, target); + case Constants.IF_ICMPNE: + return new InstructionBranch(Constants.IF_ICMPNE, target); + case Constants.IF_ICMPLT: + return new InstructionBranch(Constants.IF_ICMPLT, target); + case Constants.IF_ICMPGE: + return new InstructionBranch(Constants.IF_ICMPGE, target); + case Constants.IF_ICMPGT: + return new InstructionBranch(Constants.IF_ICMPGT, target); + case Constants.IF_ICMPLE: + return new InstructionBranch(Constants.IF_ICMPLE, target); + case Constants.IF_ACMPEQ: + return new InstructionBranch(Constants.IF_ACMPEQ, target); + case Constants.IF_ACMPNE: + return new InstructionBranch(Constants.IF_ACMPNE, target); + case Constants.GOTO: + return new InstructionBranch(Constants.GOTO, target); + case Constants.JSR: + return new InstructionBranch(Constants.JSR, target); + case Constants.IFNULL: + return new InstructionBranch(Constants.IFNULL, target); + case Constants.IFNONNULL: + return new InstructionBranch(Constants.IFNONNULL, target); + case Constants.GOTO_W: + return new InstructionBranch(Constants.GOTO_W, target); + case Constants.JSR_W: + return new InstructionBranch(Constants.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(ConstantPool c) { + cp = c; + } + + public ConstantPool getConstantPool() { + return cp; + } + + /** + * Returns the right instruction for putting whatever you want onto the stack + */ + public static Instruction PUSH(ConstantPool cp, int value) { + Instruction instruction = null; + if ((value >= -1) && (value <= 5)) { + return INSTRUCTIONS[Constants.ICONST_0 + value]; + } else if ((value >= -128) && (value <= 127)) { + instruction = new InstructionByte(Constants.BIPUSH, (byte) value); + } else if ((value >= -32768) && (value <= 32767)) { + instruction = new InstructionShort(Constants.SIPUSH, (short) value); + } else // If everything fails create a Constant pool entry + { + int pos = cp.addInteger(value); + if (pos <= Constants.MAX_BYTE) { + instruction = new InstructionCP(Constants.LDC, pos); + } else { + instruction = new InstructionCP(Constants.LDC_W, pos); + } + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, ObjectType t) { + return new InstructionCP(Constants.LDC_W, cp.addClass(t)); + } + + public static Instruction PUSH(ConstantPool cp, boolean value) { + return INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)]; + } + + public static Instruction PUSH(ConstantPool cp, float value) { + Instruction instruction = null; + if (value == 0.0) { + instruction = FCONST_0; + } else if (value == 1.0) { + instruction = FCONST_1; + } else if (value == 2.0) { + instruction = FCONST_2; + } else { + // Create a Constant pool entry + int i = cp.addFloat(value); + instruction = new InstructionCP(i <= Constants.MAX_BYTE ? Constants.LDC : Constants.LDC_W, i); + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, long value) { + Instruction instruction = null; + if (value == 0) { + instruction = LCONST_0; + } else if (value == 1) { + instruction = LCONST_1; + } else { + instruction = new InstructionCP(Constants.LDC2_W, cp.addLong(value)); + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, double value) { + Instruction instruction = null; + if (value == 0.0) { + instruction = DCONST_0; + } else if (value == 1.0) { + instruction = DCONST_1; + } else { + // Create a Constant pool entry + instruction = new InstructionCP(Constants.LDC2_W, cp.addDouble(value)); + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, String value) { + Instruction instruction = null; + if (value == null) { + instruction = ACONST_NULL; + } else { + int i = cp.addString(value); + instruction = new InstructionCP(i <= Constants.MAX_BYTE ? Constants.LDC : Constants.LDC_W, i); + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, Number value) { + Instruction instruction = null; + if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) { + instruction = PUSH(cp, value.intValue()); + } else if (value instanceof Double) { + instruction = PUSH(cp, value.doubleValue()); + } else if (value instanceof Float) { + instruction = PUSH(cp, value.floatValue()); + } else if (value instanceof Long) { + instruction = PUSH(cp, value.longValue()); + } else { + throw new ClassGenException("What's this: " + value); + } + return instruction; + } + + public static Instruction PUSH(ConstantPool cp, Character value) { + return PUSH(cp, value.charValue()); + } + + public static Instruction PUSH(ConstantPool cp, Boolean value) { + return PUSH(cp, value.booleanValue()); + } + + /** + * Return a list that will load the Class object - on 1.5 or later use the class variant of ldc, whilst on earlier JVMs use the + * regular Class.forName. + */ + public InstructionList PUSHCLASS(ConstantPool cp, String className) { + InstructionList iList = new InstructionList(); + int classIndex = cp.addClass(className); + if (cg != null && cg.getMajor() >= Constants.MAJOR_1_5) { + if (classIndex <= Constants.MAX_BYTE) { + iList.append(new InstructionCP(Instruction.LDC, classIndex)); + } else { + iList.append(new InstructionCP(Instruction.LDC_W, classIndex)); + } + } else { + className = className.replace('/', '.'); + iList.append(InstructionFactory.PUSH(cp, className)); + iList.append(this.createInvoke("java.lang.Class", "forName", ObjectType.CLASS, Type.STRINGARRAY1, + Constants.INVOKESTATIC)); + } + return iList; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionHandle.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionHandle.java new file mode 100644 index 000000000..2f2691df1 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionHandle.java @@ -0,0 +1,189 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.aspectj.apache.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: InstructionHandle.java,v 1.9 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 pos = -1; // byte code offset of instruction + private Set<InstructionTargeter> targeters = Collections.emptySet(); + + protected InstructionHandle(Instruction i) { + setInstruction(i); + } + + static final InstructionHandle getInstructionHandle(Instruction i) { + return new InstructionHandle(i); + } + + 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 (instruction != null) { + instruction.dispose(); + } + instruction = i; + } + + /** + * @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 pos; + } + + /** + * Set the position, i.e., the byte code offset of the contained instruction. + */ + void setPosition(int pos) { + this.pos = pos; + } + + /** + * Delete contents, i.e., remove user access and make handle reusable. + */ + // OPTIMIZE get rid of this? why do we need it + void dispose() { + next = prev = null; + instruction.dispose(); + instruction = null; + pos = -1; + removeAllTargeters(); + } + + /** + * Remove all targeters, if any. + */ + public void removeAllTargeters() { + targeters.clear(); + } + + /** + * Denote this handle isn't referenced anymore by t. + */ + public void removeTargeter(InstructionTargeter t) { + targeters.remove(t); + } + + /** + * Denote this handle is being referenced by t. + */ + public void addTargeter(InstructionTargeter t) { + if (targeters == Collections.EMPTY_SET) { + targeters = new HashSet<InstructionTargeter>(); + } + targeters.add(t); + } + + public boolean hasTargeters() { + return !targeters.isEmpty(); + } + + public Set<InstructionTargeter> getTargeters() { + return targeters; + } + + public Set<InstructionTargeter> getTargetersCopy() { + Set<InstructionTargeter> copy = new HashSet<InstructionTargeter>(); + copy.addAll(targeters); + return copy; + } + + /** + * @return a (verbose) string representation of the contained instruction. + */ + public String toString(boolean verbose) { + return Utility.format(pos, 4, false, ' ') + ": " + instruction.toString(verbose); + } + + public String toString() { + return toString(true); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionLV.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionLV.java new file mode 100644 index 000000000..73c278016 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionLV.java @@ -0,0 +1,278 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; + +/** + * Abstract super class for instructions dealing with local variables. + * + * @version $Id: InstructionLV.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class InstructionLV extends Instruction { + protected int lvar = -1; + + public InstructionLV(short opcode, int lvar) { + super(opcode); + this.lvar = lvar; + } + + public InstructionLV(short opcode) { + super(opcode); + } + + public void dump(DataOutputStream out) throws IOException { + if (lvar == -1) { + out.writeByte(opcode); + } else { + if (lvar < 4) { + if (opcode == ALOAD) { + out.writeByte(ALOAD_0 + lvar); + } else if (opcode == ASTORE) { + out.writeByte(ASTORE_0 + lvar); + } else if (opcode == ILOAD) { + out.writeByte(ILOAD_0 + lvar); + } else if (opcode == ISTORE) { + out.writeByte(ISTORE_0 + lvar); + } else if (opcode == DLOAD) { + out.writeByte(DLOAD_0 + lvar); + } else if (opcode == DSTORE) { + out.writeByte(DSTORE_0 + lvar); + } else if (opcode == FLOAD) { + out.writeByte(FLOAD_0 + lvar); + } else if (opcode == FSTORE) { + out.writeByte(FSTORE_0 + lvar); + } else if (opcode == LLOAD) { + out.writeByte(LLOAD_0 + lvar); + } else if (opcode == LSTORE) { + out.writeByte(LSTORE_0 + lvar); + } else { + if (wide()) { + out.writeByte(Constants.WIDE); + } + out.writeByte(opcode); + if (wide()) { + out.writeShort(lvar); + } else { + out.writeByte(lvar); + } + } + } else { + if (wide()) { + out.writeByte(Constants.WIDE); + } + out.writeByte(opcode); + if (wide()) { + out.writeShort(lvar); + } else { + out.writeByte(lvar); + } + } + } + } + + /** + * Long output format: + * + * 'name of opcode' "[" 'opcode number' "]" "(" 'length of instruction' ")" "<" 'local variable index' ">" + */ + 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) + (lvar != -1 && lvar < 4 ? "_" : " ") + lvar; + } + } + + public boolean isALOAD() { + return opcode == ALOAD || opcode >= ALOAD_0 && opcode <= ALOAD_3; + } + + public boolean isASTORE() { + return opcode == ASTORE || opcode >= ASTORE_0 && opcode <= ASTORE_3; + } + + public int getBaseOpcode() { + if (opcode >= ILOAD && opcode <= ALOAD || opcode >= ISTORE && opcode <= ASTORE) { + // not an optimized instruction + return opcode; + } + if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { + int ret = opcode - ILOAD_0; + ret = ret - ret % 4; + ret = ret / 4; + return ret + ILOAD; + } + int ret = opcode - ISTORE_0; + ret = ret - ret % 4; + ret = ret / 4; + return ret + ISTORE; + } + + /** + * @return local variable index referred by this instruction. + */ + // optimize! + public final int getIndex() { + if (lvar != -1) { + return lvar; + } + if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { + return (opcode - Constants.ILOAD_0) % 4; + } else if (opcode >= Constants.ISTORE_0 && opcode <= Constants.ASTORE_3) { + return (opcode - Constants.ISTORE_0) % 4; + } + return -1; + } + + public void setIndex(int i) { + // Switching the index for a load/store without a current index specified (ie. an aload_1 or istore_2) + // means we need to should adjust to a normal aload/istore opcode + if (getIndex() != i) { + if (opcode >= Constants.ILOAD_0 && opcode <= Constants.ALOAD_3) { + opcode = (short) (ILOAD + (opcode - ILOAD_0) / 4); + } else if (opcode >= Constants.ISTORE_0 && opcode <= Constants.ASTORE_3) { + opcode = (short) (ISTORE + (opcode - ISTORE_0) / 4); + } + this.lvar = i; + } + } + + public boolean canSetIndex() { + return true; + } + + public InstructionLV setIndexAndCopyIfNecessary(int newIndex) { + if (canSetIndex()) { + setIndex(newIndex); + return this; + } else { + if (getIndex() == newIndex) { + return this; + } + InstructionLV newInstruction = null; + int baseOpCode = getBaseOpcode(); + if (newIndex < 4) { + if (isStoreInstruction()) { + newInstruction = (InstructionLV) InstructionConstants.INSTRUCTIONS[(baseOpCode - Constants.ISTORE) * 4 + + Constants.ISTORE_0 + newIndex]; + } else { + newInstruction = (InstructionLV) InstructionConstants.INSTRUCTIONS[(baseOpCode - Constants.ILOAD) * 4 + + Constants.ILOAD_0 + newIndex]; + } + } else { + newInstruction = new InstructionLV((short) baseOpCode, newIndex); + } + // if (getBaseOpcode()!=newInstruction.getBaseOpcode() || newInstruction.getIndex()!=newIndex) { + // throw new + // RuntimeException("New Instruction created does not appear to be valid: originalBaseOpcode="+getBaseOpcode()+ + // " newBaseOpcode="+newInstruction.getBaseOpcode()); + // } + return newInstruction; + } + } + + public int getLength() { + int size = Constants.iLen[opcode]; + if (lvar == -1) { + return size; + } else { + if (lvar < 4) { + if (opcode == ALOAD || opcode == ASTORE) { + return 1; + } else if (opcode == ILOAD || opcode == ISTORE) { + return 1; + } else if (opcode == DLOAD || opcode == DSTORE) { + return 1; + } else if (opcode == FLOAD || opcode == FSTORE) { + return 1; + } else if (opcode == LLOAD || opcode == LSTORE) { + return 1; + } else { + if (wide()) { + return size + 2; + } + return size; + } + } else { + if (wide()) { + return size + 2; + } + return size; + } + } + } + + private final boolean wide() { + return lvar > Constants.MAX_BYTE; + } + + public boolean equals(Object other) { + if (!(other instanceof InstructionLV)) { + return false; + } + InstructionLV o = (InstructionLV) other; + return o.opcode == opcode && o.lvar == lvar; + } + + public int hashCode() { + return opcode * 37 + lvar; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionList.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionList.java new file mode 100644 index 000000000..b08a2b77c --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionList.java @@ -0,0 +1,1287 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +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.Set; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Constant; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.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: InstructionList.java,v 1.12 2011/09/02 22:33:04 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author Abraham Nevado + * @see Instruction + * @see InstructionHandle + * @see BranchHandle + */ +public class InstructionList implements Serializable { + private InstructionHandle start = null, end = null; + private int length = 0; + private int[] positions; // byte code offsets corresponding to instructions + + public InstructionList() { + } + + public InstructionList(Instruction i) { + append(i); + } + + public boolean isEmpty() { + return start == null; + } // && end == null + + public static InstructionHandle findHandle(InstructionHandle[] ihs, int[] pos, int count, int target) { + return findHandle(ihs, pos, count, target, false); + } + + /** + * 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, + boolean returnClosestIfNoExactMatch) { + int l = 0, r = count - 1; + // Do a binary search since the pos array is ordered + int i, j; + do { + i = (l + r) / 2; + j = pos[i]; + if (j == target) { + return ihs[i]; // found it + } else if (target < j) { + r = i - 1; // else constrain search area + } else { + l = i + 1; // target > j + } + } while (l <= r); + + if (returnClosestIfNoExactMatch) { + i = (l + r) / 2; + if (i < 0) { + i = 0; + } + return ihs[i]; + } + 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) { + InstructionHandle[] ihs = getInstructionHandles(); + return findHandle(ihs, positions, length, pos); + } + + public InstructionHandle[] getInstructionsAsArray() { + return getInstructionHandles(); + } + + public InstructionHandle findHandle(int pos, InstructionHandle[] instructionArray) { + return findHandle(instructionArray, positions, length, pos); + } + + public InstructionHandle findHandle(int pos, InstructionHandle[] instructionArray, boolean useClosestApproximationIfNoExactFound) { + return findHandle(instructionArray, positions, length, pos, useClosestApproximationIfNoExactFound); + } + + /** + * 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 InstructionBranch) { + ih = append((InstructionBranch) i); + } else { + ih = append(i); + } + + ih.setPosition(off); + ihs[count] = ih; + + count++; + } + } catch (IOException e) { + throw new ClassGenException(e.toString()); + } + + positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, positions, 0, count); + + /* + * Pass 2: Look for BranchInstruction and update their targets, i.e., convert offsets to instruction handles. + */ + // OPTIMIZE better way of doing this? keep little map from earlier from pos -> instruction handle? + for (int i = 0; i < count; i++) { + if (ihs[i] instanceof BranchHandle) { + InstructionBranch bi = (InstructionBranch) ihs[i].instruction; + int target = bi.positionOfThisInstruction + 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 InstructionSelect) { // Either LOOKUPSWITCH or TABLESWITCH + InstructionSelect s = (InstructionSelect) bi; + int[] indices = s.getIndices(); + + for (int j = 0; j < indices.length; j++) { + target = bi.positionOfThisInstruction + 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 appendTo where to append the instruction list + * @param appendee Instruction list to append to this one + * @return instruction handle pointing to the <B>first</B> appended instruction + */ + public InstructionHandle append(InstructionHandle appendTo, InstructionList appendee) { + assert appendee != null; + + if (appendee.isEmpty()) { + return appendTo; + } + + InstructionHandle next = appendTo.next; + InstructionHandle ret = appendee.start; + + appendTo.next = appendee.start; + appendee.start.prev = appendTo; + + appendee.end.next = next; + + if (next != null) { + next.prev = appendee.end; + } else { + end = appendee.end; // Update end ... + } + + length += appendee.length; // Update length + + appendee.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) { + assert il != null; + + 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; + } + + public InstructionHandle appendDUP() { + InstructionHandle ih = InstructionHandle.getInstructionHandle(InstructionConstants.DUP); + append(ih); + return ih; + } + + public InstructionHandle appendNOP() { + InstructionHandle ih = InstructionHandle.getInstructionHandle(InstructionConstants.NOP); + append(ih); + return ih; + } + + public InstructionHandle appendPOP() { + InstructionHandle ih = InstructionHandle.getInstructionHandle(InstructionConstants.POP); + 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(InstructionBranch 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 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, InstructionBranch 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 i 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(InstructionBranch 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 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 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, InstructionBranch 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 + 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; + } + } + } + + /** + * 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. + * + * If careAboutLostTargeters is true then this method will throw a 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, boolean careAboutLostTargeters) throws TargetLostException { + InstructionHandle first, last; // First and last deleted instruction + + if (prev == null && next == null) { // singleton list + first = last = start; + 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; + + if (!careAboutLostTargeters) { + return; + } + + ArrayList<InstructionHandle> target_vec = new ArrayList<InstructionHandle>(); + + 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--; + + Set<InstructionTargeter> targeters = ih.getTargeters(); + boolean isOK = false; + Iterator<InstructionTargeter> tIter = targeters.iterator(); + while (tIter.hasNext()) { + InstructionTargeter instructionTargeter = tIter.next(); + if (instructionTargeter.getClass().getName().endsWith("ShadowRange") + || instructionTargeter.getClass().getName().endsWith("ExceptionRange") + || instructionTargeter.getClass().getName().endsWith("LineNumberTag")) { + isOK = true; + } else { + System.out.println(instructionTargeter.getClass()); + } + } + if (!isOK) { + target_vec.add(ih); + buf.append(ih.toString(true) + " "); + ih.next = ih.prev = null; + } else { + ih.dispose(); + } + + // if (ih.hasTargeters()) { // Still got targeters? + // InstructionTargeter[] targeters = ih.getTargeters(); + // boolean isOK = false; + // for (int i = 0; i < targeters.length; i++) { + // InstructionTargeter instructionTargeter = targeters[i]; + // if (instructionTargeter.getClass().getName().endsWith("ShadowRange") + // || instructionTargeter.getClass().getName().endsWith("ExceptionRange") + // || instructionTargeter.getClass().getName().endsWith("LineNumberTag")) { + // isOK = true; + // } else { + // System.out.println(instructionTargeter.getClass()); + // } + // } + // if (!isOK) { + // target_vec.add(ih); + // buf.append(ih.toString(true) + " "); + // ih.next = ih.prev = null; + // } else { + // ih.dispose(); + // } + // } 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, false); + } + + /** + * 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, false); + } + + /** + * 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 maxAdditionalBytes = 0; + int index = 0, count = 0; + int[] pos = new int[length]; + + // Pass 0: Sanity checks + if (check) { + checkInstructionList(); + } + + // 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.opcode) { + case Constants.JSR: + case Constants.GOTO: + maxAdditionalBytes += 2; + break; + + case Constants.TABLESWITCH: + case Constants.LOOKUPSWITCH: + maxAdditionalBytes += 3; + break; + } + index += i.getLength(); + } + + // OPTIMIZE positions will only move around if there have been expanding instructions + // if (max_additional_bytes==0...) { + // + // } + + /* + * 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. + */ + boolean nonZeroOffset = false; + int offset = 0; + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + if (ih instanceof BranchHandle) { + offset += ((BranchHandle) ih).updatePosition(offset, maxAdditionalBytes); + if (offset != 0) { + nonZeroOffset = true; + } + } + } + if (nonZeroOffset) { + /* + * 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(); + } + } + + positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, positions, 0, count); + } + + private void checkInstructionList() { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + + if (i instanceof InstructionBranch) { // target instruction within list? + Instruction inst = ((InstructionBranch) 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 InstructionSelect) { + InstructionHandle[] targets = ((InstructionSelect) 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."); + } + + } + } + } + + /** + * 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 null; + } + byte[] byteCode = b.toByteArray(); + if (byteCode.length > Constants.MAX_CODE_SIZE) { + throw new ClassGenException("Code size too big: " + byteCode.length); + } + + return byteCode; + } + + /** + * @return an array of instructions without target information for branch instructions. + */ + public Instruction[] getInstructions() { + ByteSequence bytes = new ByteSequence(getByteCode()); + ArrayList<Instruction> instructions = new ArrayList<Instruction>(); + + try { + while (bytes.available() > 0) { + instructions.add(Instruction.readInstruction(bytes)); + } + } catch (IOException e) { + throw new ClassGenException(e.toString()); + } + + Instruction[] result = new Instruction[instructions.size()]; + instructions.toArray(result); + return result; + } + + @Override + 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) + "\n"); + } + + return buf.toString(); + } + + /** + * @return Enumeration that lists all instructions (handles) + */ + public Iterator iterator() { + return new Iterator() { + private InstructionHandle ih = start; + + public Object next() { + 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 positions; + } + + /** + * @return complete, i.e., deep copy of this list + */ + public InstructionList copy() { + HashMap<InstructionHandle, InstructionHandle> map = new HashMap<InstructionHandle, InstructionHandle>(); + 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 InstructionBranch) { + map.put(ih, il.append((InstructionBranch) 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 InstructionBranch) { + InstructionBranch bi = (InstructionBranch) i; + InstructionBranch bc = (InstructionBranch) c; + InstructionHandle itarget = bi.getTarget(); // old target + + // New target is in hash map + bc.setTarget(map.get(itarget)); + + if (bi instanceof InstructionSelect) { // Either LOOKUPSWITCH or TABLESWITCH + InstructionHandle[] itargets = ((InstructionSelect) bi).getTargets(); + InstructionHandle[] ctargets = ((InstructionSelect) bc).getTargets(); + + for (int j = 0; j < itargets.length; j++) { // Update all targets + ctargets[j] = 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(ConstantPool old_cp, ConstantPool new_cp) { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + if (i.isConstantPoolInstruction()) { + InstructionCP ci = (InstructionCP) 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 better 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 InstructionBranch) { + InstructionBranch b = (InstructionBranch) i; + InstructionHandle target = b.getTarget(); + + if (target == old_target) { + b.setTarget(new_target); + } + + if (b instanceof InstructionSelect) { // Either LOOKUPSWITCH or TABLESWITCH + InstructionHandle[] targets = ((InstructionSelect) b).getTargets(); + + for (int j = 0; j < targets.length; j++) { + if (targets[j] == old_target) { + ((InstructionSelect) 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); + } + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionSelect.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionSelect.java new file mode 100644 index 000000000..b4e00c027 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionSelect.java @@ -0,0 +1,291 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.util.ByteSequence; + +/** + * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions. + * + * @version $Id: InstructionSelect.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see LOOKUPSWITCH + * @see TABLESWITCH + * @see InstructionList + */ +public abstract class InstructionSelect extends InstructionBranch { + protected int[] match; // matches, i.e., case 1: ... + protected int[] indices; // target offsets + protected InstructionHandle[] targets; // target objects in instruction list + protected int fixedLength; // fixed length defined by subclasses + protected int matchLength; // number of cases + protected int padding = 0; // number of pad bytes for alignment + + protected short length; + + /** + * (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 target default instruction target + */ + InstructionSelect(short opcode, int[] match, InstructionHandle[] targets, InstructionHandle target) { + super(opcode, target); + + this.targets = targets; + for (int i = 0; i < targets.length; i++) { + notifyTarget(null, targets[i], this); + } + + this.match = match; + + if ((matchLength = match.length) != targets.length) { + throw new ClassGenException("Match and target array have not the same length"); + } + + indices = new int[matchLength]; + } + + 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 - positionOfThisInstruction; + } + + /** + * 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) { + positionOfThisInstruction += 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 - (positionOfThisInstruction + 1) % 4) % 4; + length = (short) (fixedLength + 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); + } + + targetIndex = getTargetOffset(); // Write default target offset + out.writeInt(targetIndex); + } + + public InstructionSelect(short opcode, ByteSequence bytes) throws IOException { + super(opcode); + 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) + targetIndex = 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 < matchLength; i++) { + String s = "null"; + + if (targets[i] != null) { + s = targets[i].getInstruction().toString(); + } + + buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})"); + } + } 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 (targetInstruction == 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 (targetInstruction == ih) { + return true; + } + + for (int i = 0; i < targets.length; i++) { + if (targets[i] == ih) { + return true; + } + } + + return false; + } + + /** + * 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; + } + + public boolean equals(Object other) { + return this == other; + } + + public int hashCode() { + return opcode * 37; + } + + /** + * @return array of match targets + */ + public InstructionHandle[] getTargets() { + return targets; + } + + public int getLength() { + return length; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionShort.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionShort.java new file mode 100644 index 000000000..99054cbff --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionShort.java @@ -0,0 +1,92 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * Instruction that needs one short + */ +public class InstructionShort extends Instruction { + private final short value; + + public InstructionShort(short opcode, short value) { + super(opcode); + this.value = value; + } + + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + out.writeShort(value); + } + + public String toString(boolean verbose) { + return super.toString(verbose) + " " + value; + } + + public boolean equals(Object other) { + if (!(other instanceof InstructionShort)) { + return false; + } + InstructionShort o = (InstructionShort) other; + return o.opcode == opcode && o.value == value; + } + + public int hashCode() { + return opcode * 37 + value; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionTargeter.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionTargeter.java new file mode 100644 index 000000000..950ed3fa9 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InstructionTargeter.java @@ -0,0 +1,70 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * Denote that a class targets InstructionHandles within an InstructionList. Namely + * the following implementers: + * + * @see BranchHandle + * @see LocalVariableGen + * @see CodeExceptionGen + * @version $Id: InstructionTargeter.java,v 1.3 2008/05/28 23:52:57 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public interface InstructionTargeter { + public boolean containsTarget(InstructionHandle ih); + public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeDynamic.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeDynamic.java new file mode 100644 index 000000000..b3c7ba85a --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeDynamic.java @@ -0,0 +1,129 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +package org.aspectj.apache.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantInvokeDynamic; +import org.aspectj.apache.bcel.classfile.ConstantNameAndType; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * INVOKEDYNAMIC + * + * @author Andy Clement + */ +public final class InvokeDynamic extends InvokeInstruction { + + public InvokeDynamic(int index, int zeroes) { + super(Constants.INVOKEDYNAMIC, index); + } + + public void dump(DataOutputStream out) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + out.writeShort(0); + } + + public String toString(ConstantPool cp) { + return super.toString(cp) + " " + index; + } + + public boolean equals(Object other) { + if (!(other instanceof InvokeDynamic)) { + return false; + } + InvokeDynamic o = (InvokeDynamic) other; + return o.opcode == opcode && o.index == index; + } + + public int hashCode() { + return opcode * 37 + index; + } + + public Type getReturnType(ConstantPool cp) { + return Type.getReturnType(getSignature(cp)); + } + + public Type[] getArgumentTypes(ConstantPool cp) { + return Type.getArgumentTypes(getSignature(cp)); + } + + public String getSignature(ConstantPool cp) { + if (signature == null) { + ConstantInvokeDynamic cid = (ConstantInvokeDynamic)cp.getConstant(index); + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cid.getNameAndTypeIndex()); + signature = cp.getConstantUtf8(cnat.getSignatureIndex()).getValue(); + } + return signature; + } + + @Override + public String getName(ConstantPool cp) { + if (name == null) { + ConstantInvokeDynamic cid = (ConstantInvokeDynamic) cp.getConstant(index); + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cid.getNameAndTypeIndex()); + name = cp.getConstantUtf8(cnat.getNameIndex()).getValue(); + } + return name; + } + + public String getClassName(ConstantPool cp) { + throw new IllegalStateException("there is no classname for invokedynamic"); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeInstruction.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeInstruction.java new file mode 100644 index 000000000..89cd43474 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/InvokeInstruction.java @@ -0,0 +1,137 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.util.StringTokenizer; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Constant; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * Super class for the INVOKExxx family of instructions. + * + * @version $Id: InvokeInstruction.java,v 1.6 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class InvokeInstruction extends FieldOrMethod { + + /** + * @param index to constant pool + */ + public 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(ConstantPool cpg) { + String signature = getSignature(cpg); + int sum = Type.getArgumentSizes(signature); + if (opcode != Constants.INVOKESTATIC) { + sum += 1; + } + 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(ConstantPool cpg) { + return getReturnType(cpg).getSize(); + } + + /** + * @return return type of referenced method. + */ + public Type getType(ConstantPool cpg) { + return getReturnType(cpg); + } + + /** + * @return name of referenced method. + */ + public String getMethodName(ConstantPool cpg) { + return getName(cpg); + } + + /** + * @return return type of referenced method. + */ + public Type getReturnType(ConstantPool cpg) { + return Type.getReturnType(getSignature(cpg)); + } + + /** + * @return argument types of referenced method. + */ + public Type[] getArgumentTypes(ConstantPool cpg) { + return Type.getArgumentTypes(getSignature(cpg)); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LOOKUPSWITCH.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LOOKUPSWITCH.java new file mode 100644 index 000000000..c8ebcba4c --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LOOKUPSWITCH.java @@ -0,0 +1,112 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.util.ByteSequence; + +/** + * LOOKUPSWITCH - Switch with unordered set of values + * + * @version $Id: LOOKUPSWITCH.java,v 1.5 2011/04/05 15:15:33 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class LOOKUPSWITCH extends InstructionSelect { + + public LOOKUPSWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target) { + super(LOOKUPSWITCH, match, targets, target); + // Alignment remainer assumed 0 here, until dump time + length = (short) (9 + matchLength * 8); + fixedLength = 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(matchLength); // npairs + + for (int i = 0; i < matchLength; i++) { + out.writeInt(match[i]); // match-offset pairs + out.writeInt(indices[i] = getTargetOffset(targets[i])); + } + } + + /** + * Read needed data (e.g. index) from file. + */ + public LOOKUPSWITCH(ByteSequence bytes) throws IOException { + super(Constants.LOOKUPSWITCH, bytes); // reads padding + + matchLength = bytes.readInt(); + fixedLength = (short) (9 + matchLength * 8); + length = (short) (fixedLength + padding); + + match = new int[matchLength]; + indices = new int[matchLength]; + targets = new InstructionHandle[matchLength]; + + for (int i = 0; i < matchLength; i++) { + match[i] = bytes.readInt(); + indices[i] = bytes.readInt(); + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberGen.java new file mode 100644 index 000000000..237720c7b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberGen.java @@ -0,0 +1,130 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.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: LineNumberGen.java,v 1.5 2008/05/28 23:53:00 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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) { + InstructionBranch.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; } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberTag.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberTag.java new file mode 100644 index 000000000..fe1d56c27 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LineNumberTag.java @@ -0,0 +1,44 @@ +/* ******************************************************************* + * Copyright (c) 2002 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * PARC initial implementation + * Andy Clement pushed down into bcel module + * ******************************************************************/ + + +package org.aspectj.apache.bcel.generic; + +/** + * we don't actually target instructions, but instructions target us. + */ +public class LineNumberTag extends Tag { + + private final int lineNumber; + + public LineNumberTag(int lineNumber) { + this.lineNumber = lineNumber; + } + + public int getLineNumber() { + return lineNumber; + } + + public String toString() { + return "line " + lineNumber; + } + + public boolean equals(Object other) { + if (!(other instanceof LineNumberTag)) return false; + return lineNumber == ((LineNumberTag)other).lineNumber; + } + + public int hashCode() { + return lineNumber; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableGen.java new file mode 100644 index 000000000..b701e7274 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableGen.java @@ -0,0 +1,220 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.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: LocalVariableGen.java,v 1.7 2008/08/28 00:04:23 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see LocalVariable + * @see MethodGen + */ +public class LocalVariableGen implements InstructionTargeter, 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 il instruction list (byte code) which this variable belongs to + * @param cp constant pool + */ + public LocalVariable getLocalVariable(ConstantPool 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); + } + + 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) { + InstructionBranch.notifyTarget(this.start, start, this); + this.start = start; + } + + public void setEnd(InstructionHandle end) { + InstructionBranch.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; + } + + /** + * 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; + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableTag.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableTag.java new file mode 100644 index 000000000..7a4fab4e9 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/LocalVariableTag.java @@ -0,0 +1,96 @@ +/* ******************************************************************* + * Copyright (c) 2002 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * PARC initial implementation + * Andy Clement pushed down into bcel module + * ******************************************************************/ + +package org.aspectj.apache.bcel.generic; + +public final class LocalVariableTag extends Tag { + private final String signature; + private String name; + private int slot; + private final int startPosition; + private boolean remapped = false; + + private int hashCode = 0; + private Type type; // not always known, in which case signature has to be used + + // AMC - pr101047, two local vars with the same name can share the same slot, but must in that case + // have different start positions. + public LocalVariableTag(String signature, String name, int slot, int startPosition) { + this.signature = signature; + this.name = name; + this.slot = slot; + this.startPosition = startPosition; + } + + public LocalVariableTag(Type type, String signature, String name, int slot, int startPosition) { + this.type = type; + this.signature = signature; + this.name = name; + this.slot = slot; + this.startPosition = startPosition; + } + + public String getName() { + return name; + } + + public int getSlot() { + return slot; + } + + public String getType() { + return signature; + } + + public Type getRealType() { + return type; + } + + public void updateSlot(int newSlot) { + this.slot = newSlot; + this.remapped = true; + this.hashCode = 0; + } + + public void setName(String name) { + this.name = name; + this.hashCode = 0; + } + + public boolean isRemapped() { + return this.remapped; + } + + public String toString() { + return "local " + slot + ": " + signature + " " + name; + } + + public boolean equals(Object other) { + if (!(other instanceof LocalVariableTag)) { + return false; + } + LocalVariableTag o = (LocalVariableTag) other; + return o.slot == slot && o.startPosition == startPosition && o.signature.equals(signature) && o.name.equals(name); + } + + public int hashCode() { + if (hashCode == 0) { + int ret = signature.hashCode(); + ret = 37 * ret + name.hashCode(); + ret = 37 * ret + slot; + ret = 37 * ret + startPosition; + hashCode = ret; + } + return hashCode; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java new file mode 100644 index 000000000..94a213a25 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MULTIANEWARRAY.java @@ -0,0 +1,183 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.ExceptionConstants; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * MULTIANEWARRAY - Create new mutidimensional array of references + * + * <PRE> + * Stack: ..., count1, [count2, ...] -> ..., arrayref + * </PRE> + * + * @version $Id: MULTIANEWARRAY.java,v 1.4 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class MULTIANEWARRAY extends InstructionCP { + private short dimensions; + + public MULTIANEWARRAY(int index, short dimensions) { + super(Constants.MULTIANEWARRAY, index); + this.dimensions = dimensions; + } + + /** + * 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(ConstantPool 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(ConstantPool 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); + // } + + public boolean equals(Object other) { + if (!(other instanceof MULTIANEWARRAY)) { + return false; + } + MULTIANEWARRAY o = (MULTIANEWARRAY) other; + return o.opcode == opcode && o.index == index && o.dimensions == dimensions; + } + + public int hashCode() { + return opcode * 37 + index * (dimensions + 17); + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MethodGen.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MethodGen.java new file mode 100644 index 000000000..3938beb35 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/MethodGen.java @@ -0,0 +1,1169 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.Attribute; +import org.aspectj.apache.bcel.classfile.Code; +import org.aspectj.apache.bcel.classfile.CodeException; +import org.aspectj.apache.bcel.classfile.ConstantPool; +import org.aspectj.apache.bcel.classfile.ExceptionTable; +import org.aspectj.apache.bcel.classfile.LineNumber; +import org.aspectj.apache.bcel.classfile.LineNumberTable; +import org.aspectj.apache.bcel.classfile.LocalVariable; +import org.aspectj.apache.bcel.classfile.LocalVariableTable; +import org.aspectj.apache.bcel.classfile.Method; +import org.aspectj.apache.bcel.classfile.Utility; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeAnnos; +import org.aspectj.apache.bcel.classfile.annotation.RuntimeParamAnnos; + +/** + * 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: MethodGen.java,v 1.17 2011/05/19 23:23:46 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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 classname; + private Type[] parameterTypes; + private String[] parameterNames; + private int maxLocals; + private int maxStack; + private InstructionList il; + + // Indicates whether to produce code attributes for LineNumberTable and LocalVariableTable, like javac -O + private boolean stripAttributes; + + private int highestLineNumber = 0; + + private ArrayList<LocalVariableGen> localVariablesList = new ArrayList<LocalVariableGen>(); + private ArrayList<LineNumberGen> lineNumbersList = new ArrayList<LineNumberGen>(); + private ArrayList<CodeExceptionGen> exceptionsList = new ArrayList<CodeExceptionGen>(); + private ArrayList<String> exceptionsThrown = new ArrayList<String>(); + private ArrayList<Attribute> codeAttributesList = new ArrayList<Attribute>(); + private List<AnnotationGen>[] param_annotations; // Array of lists containing AnnotationGen objects + private boolean hasParameterAnnotations = false; + private boolean haveUnpackedParameterAnnotations = false; + + /** + * 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, ConstantPool cp) { + + this.modifiers = access_flags; + this.type = return_type; + this.parameterTypes = arg_types; + this.parameterNames = arg_names; + this.name = method_name; + this.classname = class_name; + this.il = il; + this.cp = cp; + + // OPTIMIZE this code messes with the local variables - do we need it? + // 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); + // } + // } + // } + } + + public int getHighestlinenumber() { + return highestLineNumber; + } + + /** + * 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, ConstantPool cp) { + this(m, class_name, cp, false); + } + + // OPTIMIZE should always use tags and never anything else! + public MethodGen(Method m, String class_name, ConstantPool cp, boolean useTags) { + this(m.getModifiers(), + // OPTIMIZE implementation of getReturnType() and getArgumentTypes() on Method seems weak + m.getReturnType(), m.getArgumentTypes(), null /* may be overridden anyway */, m.getName(), class_name, ((m + .getModifiers() & (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 code = (Code) a; + setMaxStack(code.getMaxStack()); + setMaxLocals(code.getMaxLocals()); + + CodeException[] ces = code.getExceptionTable(); + + InstructionHandle[] arrayOfInstructions = il.getInstructionsAsArray(); + + // process the exception table + // - + if (ces != null) { + for (CodeException ce : ces) { + int type = ce.getCatchType(); + ObjectType catchType = null; + + if (type > 0) { + String cen = m.getConstantPool().getConstantString_CONSTANTClass(type); + catchType = 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, arrayOfInstructions);// il.findHandle(end_pc); + end = end.getPrev(); // Make it inclusive + } + + addExceptionHandler(il.findHandle(ce.getStartPC(), arrayOfInstructions), end, il.findHandle(ce + .getHandlerPC(), arrayOfInstructions), catchType); + } + } + + Attribute[] codeAttrs = code.getAttributes(); + for (int j = 0; j < codeAttrs.length; j++) { + a = codeAttrs[j]; + + if (a instanceof LineNumberTable) { + LineNumber[] ln = ((LineNumberTable) a).getLineNumberTable(); + if (useTags) { + // abracadabra, lets create tags rather than linenumbergens. + for (int k = 0; k < ln.length; k++) { + LineNumber l = ln[k]; + int lnum = l.getLineNumber(); + if (lnum > highestLineNumber) { + highestLineNumber = lnum; + } + LineNumberTag lt = new LineNumberTag(lnum); + il.findHandle(l.getStartPC(), arrayOfInstructions, true).addTargeter(lt); + } + } else { + for (int k = 0; k < ln.length; k++) { + LineNumber l = ln[k]; + addLineNumber(il.findHandle(l.getStartPC(), arrayOfInstructions, true), l.getLineNumber()); + } + } + } else if (a instanceof LocalVariableTable) { + + // Lets have a go at creating Tags directly + if (useTags) { + LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable(); + + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + Type t = Type.getType(l.getSignature()); + LocalVariableTag lvt = new LocalVariableTag(t, l.getSignature(), l.getName(), l.getIndex(), l + .getStartPC()); + InstructionHandle start = il.findHandle(l.getStartPC(), arrayOfInstructions, true); + byte b = t.getType(); + if (b != Constants.T_ADDRESS) { + int increment = t.getSize(); + if (l.getIndex() + increment > maxLocals) { + maxLocals = l.getIndex() + increment; + } + } + int end = l.getStartPC() + l.getLength(); + do { + start.addTargeter(lvt); + start = start.getNext(); + } while (start != null && start.getPosition() < end); + } + } else { + + LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable(); + + removeLocalVariables(); + + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + InstructionHandle start = il.findHandle(l.getStartPC(), arrayOfInstructions); + InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength(), arrayOfInstructions); + // AMC, this actually gives us the first instruction AFTER the range, + // so move back one... (findHandle can't cope with mid-instruction indices) + if (end != null) { + end = end.getPrev(); + } + // 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 RuntimeAnnos) { + RuntimeAnnos runtimeAnnotations = (RuntimeAnnos) a; + List<AnnotationGen> l = runtimeAnnotations.getAnnotations(); + annotationList.addAll(l); + // for (Iterator<AnnotationGen> it = l.iterator(); it.hasNext();) { + // AnnotationGen element = it.next(); + // addAnnotation(new AnnotationGen(element, cp, false)); + // } + } else { + addAttribute(a); + } + } + } + + public LocalVariableGen addLocalVariable(String name, Type type, int slot, InstructionHandle start, InstructionHandle end) { + int size = type.getSize(); + if (slot + size > maxLocals) { + maxLocals = slot + size; + } + LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end); + int i = localVariablesList.indexOf(l); + if (i >= 0) { + localVariablesList.set(i, l); // Overwrite if necessary + } else { + localVariablesList.add(l); + } + return l; + } + + /** + * 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, maxLocals, 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) { + localVariablesList.remove(l); + } + + /** + * Remove all local variables. + */ + public void removeLocalVariables() { + localVariablesList.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 = localVariablesList.size(); + LocalVariableGen[] lg = new LocalVariableGen[size]; + localVariablesList.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(ConstantPool 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); + } + + /** + * 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); + lineNumbersList.add(l); + return l; + } + + /** + * Remove a line number. + */ + public void removeLineNumber(LineNumberGen l) { + lineNumbersList.remove(l); + } + + /** + * Remove all line numbers. + */ + public void removeLineNumbers() { + lineNumbersList.clear(); + } + + /* + * @return array of line numbers + */ + public LineNumberGen[] getLineNumbers() { + LineNumberGen[] lg = new LineNumberGen[lineNumbersList.size()]; + lineNumbersList.toArray(lg); + return lg; + } + + /** + * @return 'LineNumberTable' attribute for all the local variables of this method. + */ + public LineNumberTable getLineNumberTable(ConstantPool cp) { + int size = lineNumbersList.size(); + LineNumber[] ln = new LineNumber[size]; + + for (int i = 0; i < size; i++) { + ln[i] = lineNumbersList.get(i).getLineNumber(); + } + + return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp); + } + + /** + * 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); + exceptionsList.add(c); + return c; + } + + /** + * Remove an exception handler. + */ + public void removeExceptionHandler(CodeExceptionGen c) { + exceptionsList.remove(c); + } + + /** + * Remove all line numbers. + */ + public void removeExceptionHandlers() { + exceptionsList.clear(); + } + + /* + * @return array of declared exception handlers + */ + public CodeExceptionGen[] getExceptionHandlers() { + CodeExceptionGen[] cg = new CodeExceptionGen[exceptionsList.size()]; + exceptionsList.toArray(cg); + return cg; + } + + /** + * @return code exceptions for `Code' attribute + */ + private CodeException[] getCodeExceptions() { + int size = exceptionsList.size(); + CodeException[] c_exc = new CodeException[size]; + + try { + for (int i = 0; i < size; i++) { + CodeExceptionGen c = exceptionsList.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) { + exceptionsThrown.add(class_name); + } + + /** + * Remove an exception. + */ + public void removeException(String c) { + exceptionsThrown.remove(c); + } + + /** + * Remove all exceptions. + */ + public void removeExceptions() { + exceptionsThrown.clear(); + } + + /* + * @return array of thrown exceptions + */ + public String[] getExceptions() { + String[] e = new String[exceptionsThrown.size()]; + exceptionsThrown.toArray(e); + return e; + } + + /** + * @return `Exceptions' attribute of all the exceptions thrown by this method. + */ + private ExceptionTable getExceptionTable(ConstantPool cp) { + int size = exceptionsThrown.size(); + int[] ex = new int[size]; + + try { + for (int i = 0; i < size; i++) { + ex[i] = cp.addClass(exceptionsThrown.get(i)); + } + } catch (ArrayIndexOutOfBoundsException e) { + } + + return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex, cp); + } + + /** + * 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) { + codeAttributesList.add(a); + } + + public void addParameterAnnotationsAsAttribute(ConstantPool 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]); + } + } + } + + /** + * Remove a code attribute. + */ + public void removeCodeAttribute(Attribute a) { + codeAttributesList.remove(a); + } + + /** + * Remove all code attributes. + */ + public void removeCodeAttributes() { + codeAttributesList.clear(); + } + + /** + * @return all attributes of this method. + */ + public Attribute[] getCodeAttributes() { + Attribute[] attributes = new Attribute[codeAttributesList.size()]; + codeAttributesList.toArray(attributes); + return attributes; + } + + /** + * 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) { + try { + byte_code = il.getByteCode(); + } catch (Exception e) { + throw new IllegalStateException("Unexpected problem whilst preparing bytecode for " + this.getClassName() + "." + + this.getName() + this.getSignature(), e); + } + } + + LineNumberTable lnt = null; + LocalVariableTable lvt = null; + // J5TODO: LocalVariableTypeTable support! + + /* + * Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) + */ + if ((localVariablesList.size() > 0) && !stripAttributes) { + addCodeAttribute(lvt = getLocalVariableTable(cp)); + } + + if ((lineNumbersList.size() > 0) && !stripAttributes) { + 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()) { + // Remove any stale code attribute + List<Attribute> attributes = getAttributes(); + for (int i = 0; i < attributes.size(); i++) { + Attribute a = attributes.get(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 + maxStack, maxLocals, byte_code, c_exc, code_attrs, cp); + + addAttribute(code); + } + + addAnnotationsAsAttribute(cp); + addParameterAnnotationsAsAttribute(cp); + + ExceptionTable et = null; + + if (exceptionsThrown.size() > 0) { + addAttribute(et = getExceptionTable(cp)); // Add `Exceptions' if there are "throws" clauses + } + + Method m = new Method(modifiers, name_index, signature_index, getAttributesImmutable(), cp); + + // Undo effects of adding attributes + // OPTIMIZE why redo this? is there a better way to clean up? + if (lvt != null) { + removeCodeAttribute(lvt); + } + if (lnt != null) { + removeCodeAttribute(lnt); + } + if (code != null) { + removeAttribute(code); + } + if (et != null) { + removeAttribute(et); + } + // J5TODO: Remove the annotation attributes that may have been added + return m; + } + + /** + * Set maximum number of local variables. + */ + public void setMaxLocals(int m) { + maxLocals = m; + } + + public int getMaxLocals() { + return maxLocals; + } + + /** + * Set maximum stack size for this method. + */ + public void setMaxStack(int m) { + maxStack = m; + } + + public int getMaxStack() { + return maxStack; + } + + /** + * @return class that contains this method + */ + public String getClassName() { + return classname; + } + + public void setClassName(String class_name) { + this.classname = class_name; + } + + public void setReturnType(Type return_type) { + setType(return_type); + } + + public Type getReturnType() { + return getType(); + } + + public void setArgumentTypes(Type[] arg_types) { + this.parameterTypes = arg_types; + } + + public Type[] getArgumentTypes() { + return this.parameterTypes; + }// OPTIMIZE dont need clone here? (Type[])arg_types.clone(); } + + public void setArgumentType(int i, Type type) { + parameterTypes[i] = type; + } + + public Type getArgumentType(int i) { + return parameterTypes[i]; + } + + public void setArgumentNames(String[] arg_names) { + this.parameterNames = arg_names; + } + + public String[] getArgumentNames() { + if (parameterNames != null) { + return parameterNames.clone(); + } else { + return new String[0]; + } + } + + public void setArgumentName(int i, String name) { + parameterNames[i] = name; + } + + public String getArgumentName(int i) { + return parameterNames[i]; + } + + public InstructionList getInstructionList() { + return il; + } + + public void setInstructionList(InstructionList il) { + this.il = il; + } + + @Override + public String getSignature() { + return Utility.toMethodSignature(type, parameterTypes); + } + + /** + * Computes max. stack size by performing control flow analysis. + */ + public void setMaxStack() { + if (il != null) { + maxStack = getMaxStack(cp, il, getExceptionHandlers()); + } else { + maxStack = 0; + } + } + + /** + * Compute maximum number of local variables based on the parameter count and bytecode usage of variables. + */ + public void setMaxLocals() { + setMaxLocals(false); + } + + /** + * Compute maximum number of local variables. + * + * @param respectLocalVariableTable if true and the local variable table indicates more are in use + * than the code suggests, respect the higher value from the local variable table data. + */ + public void setMaxLocals(boolean respectLocalVariableTable) { + if (il != null) { + int max = isStatic() ? 0 : 1; + + if (parameterTypes != null) { + for (int i = 0; i < parameterTypes.length; i++) { + max += parameterTypes[i].getSize(); + } + } + + for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { + Instruction ins = ih.getInstruction(); + + if ((ins instanceof InstructionLV) || (ins instanceof RET)) { + int index = ins.getIndex() + ins.getType(cp).getSize(); + + if (index > max) { + max = index; + } + } + } + if (!respectLocalVariableTable || max > maxLocals) { + maxLocals = max; + } + } else { + if (!respectLocalVariableTable) { + maxLocals = 0; + } + } + } + + public void stripAttributes(boolean flag) { + stripAttributes = 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<BranchTarget> branchTargets = new Stack<BranchTarget>(); + Hashtable<InstructionHandle, BranchTarget> visitedTargets = new Hashtable<InstructionHandle, BranchTarget>(); + + public void push(InstructionHandle target, int stackDepth) { + if (visited(target)) { + return; + } + + branchTargets.push(visit(target, stackDepth)); + } + + public BranchTarget pop() { + if (!branchTargets.empty()) { + BranchTarget bt = 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(ConstantPool cp, InstructionList il, CodeExceptionGen[] et) { + BranchStack branchTargets = new BranchStack(); + + int stackDepth = 0; + int maxStackDepth = 0; + + /* + * 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, max = et.length; i < max; i++) { + InstructionHandle handlerPos = et[i].getHandlerPC(); + if (handlerPos != null) { + // it must be at least 1 since there is an exception handler + maxStackDepth = 1; + branchTargets.push(handlerPos, 1); + } + } + + InstructionHandle ih = il.getStart(); + while (ih != null) { + Instruction instruction = ih.getInstruction(); + short opcode = instruction.opcode; + int prod = instruction.produceStack(cp); + int con = instruction.consumeStack(cp); + int delta = prod - con; + + stackDepth += delta; + if (stackDepth > maxStackDepth) { + maxStackDepth = stackDepth; + } + + // choose the next instruction based on whether current is a branch. + if (instruction instanceof InstructionBranch) { + InstructionBranch branch = (InstructionBranch) instruction; + if (instruction instanceof InstructionSelect) { + // explore all of the select's targets. the default target is handled below. + InstructionSelect select = (InstructionSelect) 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.isIfInstruction())) { + // 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; + } + + /** + * Return string representation close to declaration format, `public static void main(String[]) throws IOException', e.g. + * + * @return String representation of the method. + */ + @Override + public final String toString() { + String access = Utility.accessToString(modifiers); + String signature = Utility.toMethodSignature(type, parameterTypes); + + signature = Utility.methodSignatureToString(signature, name, access, true, getLocalVariableTable(cp)); + + StringBuffer buf = new StringBuffer(signature); + + if (exceptionsThrown.size() > 0) { + for (Iterator<String> e = exceptionsThrown.iterator(); e.hasNext();) { + buf.append("\n\t\tthrows " + e.next()); + } + } + + return buf.toString(); + } + + // 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<AnnotationGen> getAnnotationsOnParameter(int i) { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations || i > parameterTypes.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 + List<Attribute> attrs = getAttributes(); + RuntimeParamAnnos paramAnnVisAttr = null; + RuntimeParamAnnos paramAnnInvisAttr = null; + + for (Attribute attribute : attrs) { + if (attribute instanceof RuntimeParamAnnos) { + + if (!hasParameterAnnotations) { + param_annotations = new List[parameterTypes.length]; + for (int j = 0; j < parameterTypes.length; j++) { + param_annotations[j] = new ArrayList<AnnotationGen>(); + } + } + + hasParameterAnnotations = true; + RuntimeParamAnnos rpa = (RuntimeParamAnnos) attribute; + if (rpa.areVisible()) { + paramAnnVisAttr = rpa; + } else { + paramAnnInvisAttr = rpa; + } + for (int j = 0; j < parameterTypes.length; j++) { + // This returns Annotation[] ... + AnnotationGen[] annos = rpa.getAnnotationsOnParameter(j); + // ... which needs transforming into an AnnotationGen[] ... + // List<AnnotationGen> mutable = makeMutableVersion(immutableArray); + // ... then add these to any we already know about + for (AnnotationGen anAnnotation : annos) { + param_annotations[j].add(anAnnotation); + } + } + } + } + if (paramAnnVisAttr != null) { + removeAttribute(paramAnnVisAttr); + } + if (paramAnnInvisAttr != null) { + removeAttribute(paramAnnInvisAttr); + } + haveUnpackedParameterAnnotations = true; + } + + private List /* AnnotationGen */<AnnotationGen> makeMutableVersion(AnnotationGen[] mutableArray) { + List<AnnotationGen> result = new ArrayList<AnnotationGen>(); + for (int i = 0; i < mutableArray.length; i++) { + result.add(new AnnotationGen(mutableArray[i], getConstantPool(), false)); + } + return result; + } + + public void addParameterAnnotation(int parameterIndex, AnnotationGen annotation) { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations) { + param_annotations = new List[parameterTypes.length]; + hasParameterAnnotations = true; + } + List<AnnotationGen> existingAnnotations = param_annotations[parameterIndex]; + if (existingAnnotations != null) { + existingAnnotations.add(annotation); + } else { + List<AnnotationGen> l = new ArrayList<AnnotationGen>(); + l.add(annotation); + param_annotations[parameterIndex] = l; + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ObjectType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ObjectType.java new file mode 100644 index 000000000..544363f16 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ObjectType.java @@ -0,0 +1,161 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.Repository; +import org.aspectj.apache.bcel.classfile.JavaClass; + +/** + * Denotes reference such as java.lang.String. + * + * @version $Id: ObjectType.java,v 1.7 2009/09/28 16:39:46 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class ObjectType extends ReferenceType { + private String classname; + + /** + * @param class_name fully qualified class name, e.g. java.lang.String + */ + public ObjectType(String class_name) { + super(Constants.T_REFERENCE, toSignature(class_name));// "L" + class_name.replace('.', '/') + ";"); + this.classname = class_name;// .replace('/', '.'); + } + + /** + * @param classname eg. java.lang.String + * @param signature eg. Ljava/lang/String; + */ + public ObjectType(String classname, String signature) { + super(Constants.T_REFERENCE, signature); + this.classname = classname; + } + + private static String toSignature(String classname) { + StringBuffer sig = new StringBuffer(); + sig.append("L").append(classname.replace('.', '/')); + sig.append(";"); + return sig.toString(); + } + + /** + * @return name of referenced class + */ + public String getClassName() { + return classname; + } + + /** + * @return a hash code value for the object. + */ + @Override + public int hashCode() { + return classname.hashCode(); + } + + /** + * @return true if both type objects refer to the same class. + */ + @Override + public boolean equals(Object type) { + return (type instanceof ObjectType) ? ((ObjectType) type).classname.equals(classname) : false; + } + + /** + * If "this" doesn't reference a class, it references an interface or a non-existant entity. + */ + public boolean referencesClass() { + JavaClass jc = Repository.lookupClass(classname); + if (jc == null) { + return false; + } else { + return jc.isClass(); + } + } + + /** + * If "this" doesn't reference an interface, it references a class or a non-existant entity. + */ + public boolean referencesInterface() { + JavaClass jc = Repository.lookupClass(classname); + if (jc == null) { + return false; + } else { + return !jc.isClass(); + } + } + + public boolean subclassOf(ObjectType superclass) { + if (this.referencesInterface() || superclass.referencesInterface()) { + return false; + } + + return Repository.instanceOf(this.classname, superclass.classname); + } + + /** + * Java Virtual Machine Specification edition 2, 5.4.4 Access Control + */ + public boolean accessibleTo(ObjectType accessor) { + JavaClass jc = Repository.lookupClass(classname); + + if (jc.isPublic()) { + return true; + } else { + JavaClass acc = Repository.lookupClass(accessor.classname); + return acc.getPackageName().equals(jc.getPackageName()); + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/RET.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/RET.java new file mode 100644 index 000000000..0fd2f498d --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/RET.java @@ -0,0 +1,132 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.classfile.ConstantPool; + +/** + * RET - Return from subroutine + * + * <PRE> + * Stack: ..., -> ..., address + * </PRE> + * + * @version $Id: RET.java,v 1.5 2009/10/05 17:35:36 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public class RET extends Instruction { + private boolean wide; + private int index; // index to local variable containing the return address + + public RET(int index, boolean wide) { + super(Constants.RET); + this.index = index; + this.wide = wide; + // this.wide = index > org.aspectj.apache.bcel.Constants.MAX_BYTE; + } + + public void dump(DataOutputStream out) throws IOException { + if (wide) { + out.writeByte(Constants.WIDE); + } + out.writeByte(opcode); + if (wide) { + out.writeShort(index); + } else { + out.writeByte(index); + } + } + + public int getLength() { + if (wide) { + return 4; + } else { + return 2; + } + } + + public final int getIndex() { + return index; + } + + public final void setIndex(int index) { + this.index = index; + this.wide = index > Constants.MAX_BYTE; + } + + public String toString(boolean verbose) { + return super.toString(verbose) + " " + index; + } + + public Type getType(ConstantPool cp) { + return ReturnaddressType.NO_TARGET; + } + + public boolean equals(Object other) { + if (!(other instanceof RET)) { + return false; + } + RET o = (RET) other; + return o.opcode == opcode && o.index == index; + } + + public int hashCode() { + return opcode * 37 + index; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReferenceType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReferenceType.java new file mode 100644 index 000000000..1e290f5a4 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReferenceType.java @@ -0,0 +1,365 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.Repository; +import org.aspectj.apache.bcel.classfile.JavaClass; + +/** + * Super class for object and array types. + * + * @version $Id: ReferenceType.java,v 1.6 2009/09/09 22:18:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public abstract class ReferenceType extends Type { + + protected ReferenceType(byte t, String s) { + super(t, s); + } + + 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. + */ + public boolean isCastableTo(Type t) { + 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. + */ + public boolean isAssignmentCompatibleWith(Type t) { + 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).referencesClass()) { + /* + * 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).referencesClass()) { + 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).referencesInterface()) { + if (Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName())) { + return true; + } + } + } + + /* + * If this is an interface type, then: + */ + if (this instanceof ObjectType && ((ObjectType) this).referencesInterface()) { + /* + * If T is a class type, then T must be Object (2.4.7). + */ + if (T instanceof ObjectType && ((ObjectType) T).referencesClass()) { + 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).referencesInterface()) { + 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).referencesClass()) { + 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) this).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).referencesInterface()) { + 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". + */ + public ReferenceType getFirstCommonSuperclass(ReferenceType t) { + 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.lookupClass(thiz.getClassName()).getSuperClasses();// getSuperClasses(thiz.getClassName()); + JavaClass[] other_sups = Repository.lookupClass(other.getClassName()).getSuperClasses();// 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. + // */ + // public ReferenceType firstCommonSuperclass(ReferenceType t) { + // 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; + // } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReturnaddressType.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReturnaddressType.java new file mode 100644 index 000000000..a38ffedfd --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/ReturnaddressType.java @@ -0,0 +1,102 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.generic.InstructionHandle; + +/** + * Returnaddress, the type JSR or JSR_W instructions push upon the stack. + * + * see vmspec2 3.3.3 + * @version $Id: ReturnaddressType.java,v 1.3 2008/05/28 23:52:56 aclement Exp $ + * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase">Enver Haase</A> + */ +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; + } + + /** + * Returns if the two Returnaddresses refer to the same target. + */ + public boolean equals(Object rat){ + if(!(rat instanceof ReturnaddressType)) + return false; + + return ((ReturnaddressType)rat).returnTarget.equals(this.returnTarget); + } + + /** + * @return the target of this ReturnaddressType + */ + public InstructionHandle getTarget(){ + return returnTarget; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/SwitchBuilder.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/SwitchBuilder.java new file mode 100644 index 000000000..eac6bf364 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/SwitchBuilder.java @@ -0,0 +1,181 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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: SwitchBuilder.java,v 1.2 2008/05/28 23:52:57 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +public final class SwitchBuilder { + private int[] match; + private InstructionHandle[] targets; + private InstructionSelect 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 SwitchBuilder(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) // (almost) empty switch, or just default + if (match.length==0) { + instruction = new LOOKUPSWITCH(match,targets,target); + } else { + 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 SwitchBuilder(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++) { + int diff = (match[i]-match[i-1]); + if(diff > max_gap || diff<0) return false; + } + return true; + } + + public final InstructionSelect getInstruction() { + return instruction; + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TABLESWITCH.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TABLESWITCH.java new file mode 100644 index 000000000..5dc26346b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TABLESWITCH.java @@ -0,0 +1,138 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.util.ByteSequence; + +import com.sun.org.apache.bcel.internal.generic.SWITCH; + +/** + * TABLESWITCH - Switch within given range of values, i.e., low..high + * + * @version $Id: TABLESWITCH.java,v 1.5 2008/08/28 00:05:29 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @see SWITCH + */ +public class TABLESWITCH extends InstructionSelect { + + /** + * @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 target default branch + */ + public TABLESWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target) { + super(org.aspectj.apache.bcel.Constants.TABLESWITCH, match, targets, target); + + // if (match_length==0) { + // throw new RuntimeException("A tableswitch with no targets should be represented as a LOOKUPSWITCH"); + // } + + // Alignment remainder assumed 0 here, until dump time + length = (short) (13 + matchLength * 4); + fixedLength = 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 = matchLength > 0 ? match[0] : 0; + out.writeInt(low); + + int high = matchLength > 0 ? match[matchLength - 1] : 0; + out.writeInt(high); + + // See aj bug pr104720 + // if (match_length==0) out.writeInt(0); // following the switch you need to supply "HIGH-LOW+1" entries + + for (int i = 0; i < matchLength; i++) { + out.writeInt(indices[i] = getTargetOffset(targets[i])); + } + } + + /** + * Read needed data (e.g. index) from file. + */ + public TABLESWITCH(ByteSequence bytes) throws IOException { + super(Constants.TABLESWITCH, bytes); + + int low = bytes.readInt(); + int high = bytes.readInt(); + + matchLength = high - low + 1; + fixedLength = (short) (13 + matchLength * 4); + length = (short) (fixedLength + padding); + + match = new int[matchLength]; + indices = new int[matchLength]; + targets = new InstructionHandle[matchLength]; + + for (int i = low; i <= high; i++) { + match[i - low] = i; + } + + for (int i = 0; i < matchLength; i++) { + indices[i] = bytes.readInt(); + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Tag.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Tag.java new file mode 100644 index 000000000..1d6935e6d --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Tag.java @@ -0,0 +1,45 @@ +/* ******************************************************************* + * Copyright (c) 2002 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * PARC initial implementation + * Andy Clement pushed down into bcel module + * ******************************************************************/ + +package org.aspectj.apache.bcel.generic; + +/** + * A tag is an instruction-targeter that does not remember its target. Instruction handles will maintain a list of targeters but + * there won't be a way to get back from the tag to the instruction. Maintaining these backward/forward links just slows everything + * down. + */ +public abstract class Tag implements InstructionTargeter, Cloneable { + + public Tag() { + } + + // ---- from InstructionTargeter + public boolean containsTarget(InstructionHandle ih) { + return false; + } + + public void updateTarget(InstructionHandle oldHandle, InstructionHandle newHandle) { + oldHandle.removeTargeter(this); + if (newHandle != null) { + newHandle.addTargeter(this); + } + } + + public Tag copy() { + try { + return (Tag) clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException("Sanity check, can't clone me"); + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TargetLostException.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TargetLostException.java new file mode 100644 index 000000000..3a195705c --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/TargetLostException.java @@ -0,0 +1,101 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +/** + * 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: TargetLostException.java,v 1.3 2008/05/28 23:52:55 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + */ +// OPTIMIZE make unchecked, or get rid of it! +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; } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Type.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Type.java new file mode 100644 index 000000000..9ce007b4f --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/generic/Type.java @@ -0,0 +1,508 @@ +package org.aspectj.apache.bcel.generic; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.aspectj.apache.bcel.Constants; +import org.aspectj.apache.bcel.ConstantsInitializer; +import org.aspectj.apache.bcel.classfile.ClassFormatException; +import org.aspectj.apache.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: Type.java,v 1.14 2011/09/28 01:14:54 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * + * modified: AndyClement 2-mar-05: Removed unnecessary static and optimized + */ +public abstract class Type { + protected byte type; + protected String signature; + + /* 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 STRING = new ObjectType("java.lang.String"); + public static final ArrayType OBJECT_ARRAY = new ArrayType("java.lang.Object",1); + public static final ArrayType STRING_ARRAY = new ArrayType("java.lang.String",1); + public static final ArrayType CLASS_ARRAY = new ArrayType("java.lang.Class",1); + public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer"); + public static final ObjectType STRINGBUILDER = new ObjectType("java.lang.StringBuilder"); + public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable"); + public static final ObjectType CLASS = new ObjectType("java.lang.Class"); + public static final ObjectType INTEGER = new ObjectType("java.lang.Integer"); + public static final ObjectType EXCEPTION = new ObjectType("java.lang.Exception"); + public static final ObjectType LIST = new ObjectType("java.util.List"); + public static final ObjectType ITERATOR = new ObjectType("java.util.Iterator"); + 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>") { + }; + public static final Type[] STRINGARRAY1 = new Type[] { STRING }; + public static final Type[] STRINGARRAY2 = new Type[] { STRING, STRING }; + public static final Type[] STRINGARRAY3 = new Type[] { STRING, STRING, STRING }; + public static final Type[] STRINGARRAY4 = new Type[] { STRING, STRING, STRING, STRING }; + public static final Type[] STRINGARRAY5 = new Type[] { STRING, STRING, STRING, STRING, STRING }; + public static final Type[] STRINGARRAY6 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING }; + public static final Type[] STRINGARRAY7 = new Type[] { STRING, STRING, STRING, STRING, STRING, STRING, STRING }; + + private static Map<String, Type> commonTypes = new HashMap<String, Type>(); + + static { + commonTypes.put(STRING.getSignature(), STRING); + commonTypes.put(THROWABLE.getSignature(), THROWABLE); + commonTypes.put(VOID.getSignature(), VOID); + commonTypes.put(BOOLEAN.getSignature(), BOOLEAN); + commonTypes.put(BYTE.getSignature(), BYTE); + commonTypes.put(SHORT.getSignature(), SHORT); + commonTypes.put(CHAR.getSignature(), CHAR); + commonTypes.put(INT.getSignature(), INT); + commonTypes.put(LONG.getSignature(), LONG); + commonTypes.put(DOUBLE.getSignature(), DOUBLE); + commonTypes.put(FLOAT.getSignature(), FLOAT); + commonTypes.put(CLASS.getSignature(), CLASS); + commonTypes.put(OBJECT.getSignature(), OBJECT); + commonTypes.put(STRING_ARRAY.getSignature(), STRING_ARRAY); + commonTypes.put(CLASS_ARRAY.getSignature(), CLASS_ARRAY); + commonTypes.put(OBJECT_ARRAY.getSignature(), OBJECT_ARRAY); + commonTypes.put(INTEGER.getSignature(), INTEGER); + commonTypes.put(EXCEPTION.getSignature(), EXCEPTION); + commonTypes.put(STRINGBUFFER.getSignature(), STRINGBUFFER); + commonTypes.put(STRINGBUILDER.getSignature(), STRINGBUILDER); + commonTypes.put(LIST.getSignature(), LIST); + commonTypes.put(ITERATOR.getSignature(), ITERATOR); + ConstantsInitializer.initialize(); // needs calling because it will not have run properly the first time + } + + protected Type(byte t, String s) { + type = t; + signature = s; + } + + public String getSignature() { + return signature; + } + + 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[]' + */ + @Override + public String toString() { + return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility + .signatureToString(signature, false); + } + + public static final Type getType(String signature) { + Type t = commonTypes.get(signature); + if (t != null) { + return t; + } + byte type = Utility.typeOfSignature(signature); + if (type <= Constants.T_VOID) { + return BasicType.getType(type); + } else if (type == Constants.T_ARRAY) { + int dim = 0; + do { + dim++; + } while (signature.charAt(dim) == '['); + // Recurse, but just once, if the signature is ok + Type componentType = getType(signature.substring(dim)); + return new ArrayType(componentType, dim); + } else { // type == T_REFERENCE + // generics awareness + int nextAngly = signature.indexOf('<'); + // Format is 'Lblahblah;' + int index = signature.indexOf(';'); // Look for closing ';' + + String typeString = null; + if (nextAngly == -1 || nextAngly > index) { + typeString = signature.substring(1, index).replace('/', '.'); + } else { + boolean endOfSigReached = false; + int posn = nextAngly; + int genericDepth = 0; + while (!endOfSigReached) { + switch (signature.charAt(posn++)) { + case '<': + genericDepth++; + break; + case '>': + genericDepth--; + break; + case ';': + if (genericDepth == 0) { + endOfSigReached = true; + } + break; + default: + } + } + index = posn - 1; + typeString = signature.substring(1, nextAngly).replace('/', '.'); + } + // ObjectType doesn't currently store parameterized info + return new ObjectType(typeString); + } + } + + /** + * Convert signature to a Type object. + * + * @param signature signature string such as Ljava/lang/String; + * @return type object + */ + public static final TypeHolder getTypeInternal(String signature) throws StringIndexOutOfBoundsException { + byte type = Utility.typeOfSignature(signature); + + if (type <= Constants.T_VOID) { + return new TypeHolder(BasicType.getType(type), 1); + } else if (type == Constants.T_ARRAY) { + int dim = 0; + do { + dim++; + } while (signature.charAt(dim) == '['); + // Recurse, but just once, if the signature is ok + TypeHolder th = getTypeInternal(signature.substring(dim)); + return new TypeHolder(new ArrayType(th.getType(), dim), dim + th.getConsumed()); + } else { // type == T_REFERENCE + // Format is 'Lblahblah;' + int index = signature.indexOf(';'); // Look for closing ';' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + + // generics awareness + int nextAngly = signature.indexOf('<'); + String typeString = null; + if (nextAngly == -1 || nextAngly > index) { + typeString = signature.substring(1, index).replace('/', '.'); + } else { + boolean endOfSigReached = false; + int posn = nextAngly; + int genericDepth = 0; + while (!endOfSigReached) { + switch (signature.charAt(posn++)) { + case '<': + genericDepth++; + break; + case '>': + genericDepth--; + break; + case ';': + if (genericDepth == 0) { + endOfSigReached = true; + } + break; + default: + } + } + index = posn - 1; + typeString = signature.substring(1, nextAngly).replace('/', '.'); + } + // ObjectType doesn't currently store parameterized info + return new TypeHolder(new ObjectType(typeString), index + 1); + } + } + + /** + * 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); + } + } + + /** + * 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 + */ + // OPTIMIZE crap impl + public static Type[] getArgumentTypes(String signature) { + List<Type> argumentTypes = new ArrayList<Type>(); + 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) != ')') { + TypeHolder th = getTypeInternal(signature.substring(index)); + argumentTypes.add(th.getType()); + index += th.getConsumed(); // update position + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature); + } + + types = new Type[argumentTypes.size()]; + argumentTypes.toArray(types); + return types; + } + + /** + * Work out the type of each argument in the signature and return the cumulative sizes of all the types (size means number of + * stack slots it consumes, eg double=2, int=1). Unlike the call above, this does minimal unpacking + */ + public static int getArgumentSizes(String signature) { + int size = 0; + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + + int index = 1; // current string position + try { + while (signature.charAt(index) != ')') { + byte type = Utility.typeOfSignature(signature.charAt(index)); + if (type <= Constants.T_VOID) { + size += BasicType.getType(type).getSize(); + index++; + } else if (type == Constants.T_ARRAY) { + int dim = 0; + do { + dim++; + } while (signature.charAt(dim + index) == '['); + TypeHolder th = getTypeInternal(signature.substring(dim + index)); + size += 1; + index += dim + th.getConsumed(); + } else { // type == T_REFERENCE + // Format is 'Lblahblah;' + int index2 = signature.indexOf(';', index); // Look for closing ';' + + // generics awareness + int nextAngly = signature.indexOf('<', index); + if (nextAngly == -1 || nextAngly > index2) { + } else { + boolean endOfSigReached = false; + int posn = nextAngly; + int genericDepth = 0; + while (!endOfSigReached) { + switch (signature.charAt(posn++)) { + case '<': + genericDepth++; + break; + case '>': + genericDepth--; + break; + case ';': + if (genericDepth == 0) { + endOfSigReached = true; + } + break; + default: + } + } + index2 = posn - 1; + } + size++; + index = index2 + 1; + } + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature); + } + return size; + } + + /** + * Return the size of the type expressed in the signature. The signature should contain only one type. + */ + public static int getTypeSize(String signature) { + byte type = Utility.typeOfSignature(signature.charAt(0)); + if (type <= Constants.T_VOID) { + return BasicType.getType(type).getSize(); + } else if (type == Constants.T_ARRAY) { + return 1; + } else { // type == T_REFERENCE + return 1; + } + } + + /** + * 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 amazingly 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()); + } + } + + 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(); + } + + public static String getSignature(java.lang.reflect.Constructor<?> cons) { + StringBuffer sb = new StringBuffer("("); + Class<?>[] params = cons.getParameterTypes(); // avoid clone + + for (int j = 0; j < params.length; j++) { + sb.append(getType(params[j]).getSignature()); + } + + sb.append(")V"); + return sb.toString(); + } + + public static class TypeHolder { + private Type t; + private int consumed; + + public Type getType() { + return t; + } + + public int getConsumed() { + return consumed; + } + + public TypeHolder(Type t, int i) { + this.t = t; + this.consumed = i; + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ByteSequence.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ByteSequence.java new file mode 100644 index 000000000..072a7ba52 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ByteSequence.java @@ -0,0 +1,82 @@ +package org.aspectj.apache.bcel.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +import java.io.*; + +/** + * 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: ByteSequence.java,v 1.3 2008/05/28 23:52:53 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.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--; } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderReference.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderReference.java new file mode 100644 index 000000000..f6fcbf5f8 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderReference.java @@ -0,0 +1,67 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +package org.aspectj.apache.bcel.util; + +/** + * Implementors should provide access to a ClassLoader instance. The reference can be passed around and cached + * but will not cause the code that caches it to have a hard reference to the classloader, so it is easier + * to manage the classloader instance. The default implementation will just wrap a classloader object but + * more sophisticated implementations could keep a WeakReference to the loader. + */ +public interface ClassLoaderReference { + + java.lang.ClassLoader getClassLoader(); + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java new file mode 100644 index 000000000..e3c59556b --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java @@ -0,0 +1,394 @@ +package org.aspectj.apache.bcel.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.AbstractMap; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import org.aspectj.apache.bcel.classfile.ClassParser; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.util.ClassLoaderRepository.SoftHashMap.SpecialValue; + +/** + * The repository maintains information about which classes have been loaded. + * + * It loads its data from the ClassLoader implementation passed into its constructor. + * + * @see org.aspectj.apache.bcel.Repository + * + * @version $Id: ClassLoaderRepository.java,v 1.13 2009/09/09 19:56:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author David Dixon-Peugh + */ +public class ClassLoaderRepository implements Repository { + private static java.lang.ClassLoader bootClassLoader = null; + private ClassLoaderReference loaderRef; + + // Choice of cache... + private WeakHashMap<URL, SoftReference<JavaClass>> localCache = new WeakHashMap<URL, SoftReference<JavaClass>>(); + private static SoftHashMap /* <URL,JavaClass> */sharedCache = new SoftHashMap(Collections.synchronizedMap(new HashMap<Object, SpecialValue>())); + + // For fast translation of the classname *intentionally not static* + private SoftHashMap /* <String,URL> */nameMap = new SoftHashMap(new HashMap(), false); + + public static boolean useSharedCache = System.getProperty("org.aspectj.apache.bcel.useSharedCache", "true").equalsIgnoreCase("true"); + + private static int cacheHitsShared = 0; + private static int missSharedEvicted = 0; // Misses in shared cache access due to reference GC + private long timeManipulatingURLs = 0L; + private long timeSpentLoading = 0L; + private int classesLoadedCount = 0; + private int misses = 0; + private int cacheHitsLocal = 0; + private int missLocalEvicted = 0; // Misses in local cache access due to reference GC + + public ClassLoaderRepository(java.lang.ClassLoader loader) { + this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader()); + } + + public ClassLoaderRepository(ClassLoaderReference loaderRef) { + this.loaderRef = loaderRef; + } + + private static synchronized java.lang.ClassLoader getBootClassLoader() { + if (bootClassLoader == null) { + bootClassLoader = new URLClassLoader(new URL[0]); + } + return bootClassLoader; + } + + // Can track back to its key + public static class SoftHashMap extends AbstractMap { + private Map<Object, SpecialValue> map; + boolean recordMiss = true; // only interested in recording miss stats sometimes + private ReferenceQueue rq = new ReferenceQueue(); + + public SoftHashMap(Map<Object, SpecialValue> map) { + this.map = map; + } + + public SoftHashMap() { + this(new HashMap()); + } + + public SoftHashMap(Map map, boolean b) { + this(map); + this.recordMiss = b; + } + + class SpecialValue extends SoftReference { + private final Object key; + + SpecialValue(Object k, Object v) { + super(v, rq); + this.key = k; + } + } + + private void processQueue() { + SpecialValue sv = null; + while ((sv = (SpecialValue) rq.poll()) != null) { + map.remove(sv.key); + } + } + + @Override + public Object get(Object key) { + SpecialValue value = map.get(key); + if (value == null) + return null; + if (value.get() == null) { + // it got GC'd + map.remove(value.key); + if (recordMiss) + missSharedEvicted++; + return null; + } else { + return value.get(); + } + } + + @Override + public Object put(Object k, Object v) { + processQueue(); + return map.put(k, new SpecialValue(k, v)); + } + + @Override + public Set entrySet() { + return map.entrySet(); + } + + @Override + public void clear() { + processQueue(); + map.clear(); + } + + @Override + public int size() { + processQueue(); + return map.size(); + } + + @Override + public Object remove(Object k) { + processQueue(); + SpecialValue value = map.remove(k); + if (value == null) + return null; + if (value.get() != null) { + return value.get(); + } + return null; + } + } + + /** + * Store a new JavaClass into this repository as a soft reference and return the reference + */ + private void storeClassAsReference(URL url, JavaClass clazz) { + if (useSharedCache) { + clazz.setRepository(null); // can't risk setting repository, we'll get in a pickle! + sharedCache.put(url, clazz); + } else { + clazz.setRepository(this); + localCache.put(url, new SoftReference<JavaClass>(clazz)); + } + } + + /** + * Store a new JavaClass into this Repository. + */ + public void storeClass(JavaClass clazz) { + storeClassAsReference(toURL(clazz.getClassName()), clazz); + } + + /** + * Remove class from repository + */ + public void removeClass(JavaClass clazz) { + if (useSharedCache) + sharedCache.remove(toURL(clazz.getClassName())); + else + localCache.remove(toURL(clazz.getClassName())); + } + + /** + * Find an already defined JavaClass in the local cache. + */ + public JavaClass findClass(String className) { + if (useSharedCache) + return findClassShared(toURL(className)); + else + return findClassLocal(toURL(className)); + } + + private JavaClass findClassLocal(URL url) { + Object o = localCache.get(url); + if (o != null) { + o = ((Reference) o).get(); + if (o != null) { + return (JavaClass) o; + } else { + missLocalEvicted++; + } + } + return null; + } + + /** + * Find an already defined JavaClass in the shared cache. + */ + private JavaClass findClassShared(URL url) { + return (JavaClass) sharedCache.get(url); + } + + private URL toURL(String className) { + URL url = (URL) nameMap.get(className); + if (url == null) { + String classFile = className.replace('.', '/'); + url = loaderRef.getClassLoader().getResource(classFile + ".class"); + nameMap.put(className, url); + } + return url; + } + + /** + * Lookup a JavaClass object from the Class Name provided. + */ + public JavaClass loadClass(String className) throws ClassNotFoundException { + + // translate to a URL + long time = System.currentTimeMillis(); + java.net.URL url = toURL(className); + timeManipulatingURLs += (System.currentTimeMillis() - time); + if (url == null) + throw new ClassNotFoundException(className + " not found - unable to determine URL"); + + JavaClass clazz = null; + + // Look in the appropriate cache + if (useSharedCache) { + clazz = findClassShared(url); + if (clazz != null) { + cacheHitsShared++; + return clazz; + } + } else { + clazz = findClassLocal(url); + if (clazz != null) { + cacheHitsLocal++; + return clazz; + } + } + + // Didn't find it in either cache + misses++; + + try { + // Load it + String classFile = className.replace('.', '/'); + InputStream is = (useSharedCache ? url.openStream() : loaderRef.getClassLoader().getResourceAsStream( + classFile + ".class")); + if (is == null) { + throw new ClassNotFoundException(className + " not found using url " + url); + } + ClassParser parser = new ClassParser(is, className); + clazz = parser.parse(); + + // Cache it + storeClassAsReference(url, clazz); + + timeSpentLoading += (System.currentTimeMillis() - time); + classesLoadedCount++; + return clazz; + } catch (IOException e) { + throw new ClassNotFoundException(e.toString()); + } + } + + /** + * Produce a report on cache usage. + */ + public String report() { + StringBuffer sb = new StringBuffer(); + sb.append("BCEL repository report."); + if (useSharedCache) + sb.append(" (shared cache)"); + else + sb.append(" (local cache)"); + sb.append(" Total time spent loading: " + timeSpentLoading + "ms."); + sb.append(" Time spent manipulating URLs: " + timeManipulatingURLs + "ms."); + sb.append(" Classes loaded: " + classesLoadedCount + "."); + if (useSharedCache) { + sb.append(" Shared cache size: " + sharedCache.size()); + sb.append(" Shared cache (hits/missDueToEviction): (" + cacheHitsShared + "/" + missSharedEvicted + ")."); + } else { + sb.append(" Local cache size: " + localCache.size()); + sb.append(" Local cache (hits/missDueToEviction): (" + cacheHitsLocal + "/" + missLocalEvicted + ")."); + } + return sb.toString(); + } + + /** + * Returns an array of the stats, for testing, the order is fixed: 0=time spent loading (static) 1=time spent manipulating URLs + * (static) 2=classes loaded (static) 3=cache hits shared (static) 4=misses in shared due to eviction (static) 5=cache hits + * local 6=misses in local due to eviction 7=shared cache size + */ + public long[] reportStats() { + return new long[] { timeSpentLoading, timeManipulatingURLs, classesLoadedCount, cacheHitsShared, missSharedEvicted, + cacheHitsLocal, missLocalEvicted, sharedCache.size() }; + } + + /** + * Reset statistics and clear all caches + */ + public void reset() { + timeManipulatingURLs = 0L; + timeSpentLoading = 0L; + classesLoadedCount = 0; + cacheHitsLocal = 0; + cacheHitsShared = 0; + missSharedEvicted = 0; + missLocalEvicted = 0; + misses = 0; + clear(); + } + + public JavaClass loadClass(Class clazz) throws ClassNotFoundException { + return loadClass(clazz.getName()); + } + + /** Clear all entries from the local cache */ + public void clear() { + if (useSharedCache) + sharedCache.clear(); + else + localCache.clear(); + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassPath.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassPath.java new file mode 100644 index 000000000..b7db332d2 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassPath.java @@ -0,0 +1,584 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001, 2017 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ +package org.aspectj.apache.bcel.util; + +import java.io.ByteArrayInputStream; +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.URI; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Responsible for loading (class) files from the CLASSPATH. Inspired by + * sun.tools.ClassPath. + * + * @author M. Dahm + * @author Mario Ivankovits + * @author Andy Clement + */ +public class ClassPath implements Serializable { + private static final String JRT_FS = "jrt-fs.jar"; + + private static ClassPath SYSTEM_CLASS_PATH = null; + + private PathEntry[] paths; + private String class_path; + + public static ClassPath getSystemClassPath() { + if (SYSTEM_CLASS_PATH == null) { + SYSTEM_CLASS_PATH = new ClassPath(); + } + return SYSTEM_CLASS_PATH; + } + + /** + * Search for classes in given path. + */ + public ClassPath(String class_path) { + this.class_path = class_path; + + ArrayList<PathEntry> vec = new ArrayList<PathEntry>(); + + 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 if (file.getName().endsWith("jrt-fs.jar")) { // TODO a bit crude... + vec.add(new JImage()); + } 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 + */ + @Deprecated + public ClassPath() { + this(getClassPath()); + } + + /** + * @return used class path string + */ + @Override + public String toString() { + return class_path; + } + + @Override + public int hashCode() { + return class_path.hashCode(); + } + + @Override + 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, ArrayList<String> 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"); + String vm_version = System.getProperty("java.version"); + + ArrayList<String> list = new ArrayList<String>(); + + getPathComponents(class_path, list); + getPathComponents(boot_path, list); + + ArrayList<String> dirs = new ArrayList<String>(); + getPathComponents(ext_path, dirs); + + for (Iterator<String> e = dirs.iterator(); e.hasNext();) { + File ext_dir = new File(e.next()); + String[] extensions = ext_dir.list(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + name = name.toLowerCase(); + return name.endsWith(".zip") || name.endsWith(".jar"); + } + }); + + if (extensions != null) + for (int i = 0; i < extensions.length; i++) + list.add(ext_path + File.separatorChar + extensions[i]); + } + + StringBuffer buf = new StringBuffer(); + + for (Iterator<String> e = list.iterator(); e.hasNext();) { + buf.append(e.next()); + + if (e.hasNext()) + buf.append(File.pathSeparatorChar); + } + + // On Java9 the sun.boot.class.path won't be set. System classes accessible through JRT filesystem + if (vm_version.startsWith("9") || vm_version.startsWith("10") || vm_version.startsWith("11")) { + buf.insert(0, File.pathSeparatorChar); + buf.insert(0, System.getProperty("java.home") + File.separator + "lib" + File.separator + JRT_FS); + } + + 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, ".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 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 { + InputStream is = getInputStream(name, suffix); + + if (is == null) + throw new IOException("Couldn't find: " + name + suffix); + + DataInputStream dis = new DataInputStream(is); + byte[] bytes = new byte[is.available()]; + dis.readFully(bytes); + dis.close(); + is.close(); + + return bytes; + } + + /** + * @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; + } + + /** + * 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; + } + + @Override + 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() { + @Override + public InputStream getInputStream() throws IOException { + return new FileInputStream(file); + } + + @Override + public String getPath() { + try { + return file.getCanonicalPath(); + } catch (IOException e) { + return null; + } + + } + + @Override + public long getTime() { + return file.lastModified(); + } + + @Override + public long getSize() { + return file.length(); + } + + @Override + public String getBase() { + return dir; + } + + } : null; + } + + @Override + public String toString() { + return dir; + } + } + + private static class JImage extends PathEntry { + + private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$ + private static String MODULES_PATH = "modules"; //$NON-NLS-1$ + private static String JAVA_BASE_PATH = "java.base"; //$NON-NLS-1$ + + private java.nio.file.FileSystem fs; + private final Map<String, Path> fileMap; + + JImage() { + fs = FileSystems.getFileSystem(JRT_URI); + fileMap = buildFileMap(); + } + + private Map<String, Path> buildFileMap() { + final Map<String, Path> fileMap = new HashMap<>(); + final java.nio.file.PathMatcher matcher = fs.getPathMatcher("glob:*.class"); + Iterable<java.nio.file.Path> roots = fs.getRootDirectories(); + for (java.nio.file.Path path : roots) { + try { + Files.walkFileTree(path, new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (file.getNameCount() > 2 + && matcher.matches(file.getFileName())) { + Path classPath = file.subpath(2, file.getNameCount()); + fileMap.put(classPath.toString(), file); + } + + return FileVisitResult.CONTINUE; + } + }); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + return fileMap; + } + + private static class ByteBasedClassFile implements ClassFile { + + private byte[] bytes; + private ByteArrayInputStream bais; + private String path; + private String base; + private long time; + private long size; + + public ByteBasedClassFile(byte[] bytes, String path, String base, long time, long size) { + this.bytes = bytes; + this.path = path; + this.base = base; + this.time = time; + this.size = size; + } + + @Override + public InputStream getInputStream() throws IOException { + // TODO too costly to keep these in inflated form in memory? + this.bais = new ByteArrayInputStream(bytes); + return this.bais; + } + + @Override + public String getPath() { + return this.path; + } + + @Override + public String getBase() { + return this.base; + } + + @Override + public long getTime() { + return this.time; + } + + @Override + public long getSize() { + return this.size; + } + + } + + @Override + ClassFile getClassFile(String name, String suffix) throws IOException { + // Class files are in here under names like this: + // /modules/java.base/java/lang/Object.class (jdk9 b74) + // so within a modules top level qualifier and then the java.base module + String fileName = name.replace('.', '/') + suffix; + Path p = fileMap.get(fileName); + if (p == null) { + return null; + } + byte[] bs = Files.readAllBytes(p); + BasicFileAttributeView bfav = Files.getFileAttributeView(p, BasicFileAttributeView.class); + BasicFileAttributes bfas = bfav.readAttributes(); + long time = bfas.lastModifiedTime().toMillis(); + long size = bfas.size(); + ClassFile cf = new ByteBasedClassFile(bs, "jimage",fileName,time,size); + return cf; + } + } + + private static class Zip extends PathEntry { + private ZipFile zip; + + Zip(ZipFile z) { + zip = z; + } + + @Override + ClassFile getClassFile(String name, String suffix) throws IOException { + final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix); + + return (entry != null) ? new ClassFile() { + @Override + public InputStream getInputStream() throws IOException { + return zip.getInputStream(entry); + } + + @Override + public String getPath() { + return entry.toString(); + } + + @Override + public long getTime() { + return entry.getTime(); + } + + @Override + public long getSize() { + return entry.getSize(); + } + + @Override + public String getBase() { + return zip.getName(); + } + } : null; + } + } +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java new file mode 100644 index 000000000..259991308 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java @@ -0,0 +1,75 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +package org.aspectj.apache.bcel.util; + +/** + * Simplistic ClassLoaderReference that merely delegates to a classloader. More sophisticated ones could allow for the + * loader to be weakly referenced. + * + * @author Andy Clement + */ +public class DefaultClassLoaderReference implements ClassLoaderReference { + + private java.lang.ClassLoader loader; + + public DefaultClassLoaderReference(java.lang.ClassLoader classLoader) { + this.loader = classLoader; + } + + public java.lang.ClassLoader getClassLoader() { + return loader; + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java new file mode 100644 index 000000000..a53b9dc35 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java @@ -0,0 +1,268 @@ +package org.aspectj.apache.bcel.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.aspectj.apache.bcel.classfile.ClassParser; +import org.aspectj.apache.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.aspectj.apache.bcel.Repository + * + * @version $Id: NonCachingClassLoaderRepository.java,v 1.6 2009/09/09 19:56:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author David Dixon-Peugh + * + */ +public class NonCachingClassLoaderRepository implements Repository { + private static java.lang.ClassLoader bootClassLoader = null; + + private final ClassLoaderReference loaderRef; + private final Map<String, JavaClass> loadedClasses = new SoftHashMap(); + + public static class SoftHashMap extends AbstractMap { + private Map<Object, SpecialValue> map; + private ReferenceQueue rq = new ReferenceQueue(); + + public SoftHashMap(Map<Object, SpecialValue> map) { + this.map = map; + } + + public SoftHashMap() { + this(new HashMap<Object,SpecialValue>()); + } + + public SoftHashMap(Map<Object,SpecialValue> map, boolean b) { + this(map); + } + + class SpecialValue extends SoftReference { + private final Object key; + + SpecialValue(Object k, Object v) { + super(v, rq); + this.key = k; + } + } + + private void processQueue() { + SpecialValue sv = null; + while ((sv = (SpecialValue) rq.poll()) != null) { + map.remove(sv.key); + } + } + + @Override + public Object get(Object key) { + SpecialValue value = map.get(key); + if (value == null) + return null; + if (value.get() == null) { + // it got GC'd + map.remove(value.key); + return null; + } else { + return value.get(); + } + } + + @Override + public Object put(Object k, Object v) { + processQueue(); + return map.put(k, new SpecialValue(k, v)); + } + + @Override + public Set entrySet() { + return map.entrySet(); + } + + @Override + public void clear() { + processQueue(); + Set<Object> keys = map.keySet(); + for (Iterator<Object> iterator = keys.iterator(); iterator.hasNext();) { + Object name = iterator.next(); + map.remove(name); + } + } + + @Override + public int size() { + processQueue(); + return map.size(); + } + + @Override + public Object remove(Object k) { + processQueue(); + SpecialValue value = map.remove(k); + if (value == null) + return null; + if (value.get() != null) { + return value.get(); + } + return null; + } + } + + public NonCachingClassLoaderRepository(java.lang.ClassLoader loader) { + this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader()); + } + + public NonCachingClassLoaderRepository(ClassLoaderReference loaderRef) { + this.loaderRef = loaderRef; + } + + private static synchronized java.lang.ClassLoader getBootClassLoader() { + if (bootClassLoader == null) { + bootClassLoader = new URLClassLoader(new URL[0]); + } + return bootClassLoader; + } + + /** + * Store a new JavaClass into this Repository. + */ + public void storeClass(JavaClass clazz) { + synchronized (loadedClasses) { + loadedClasses.put(clazz.getClassName(), clazz); + } + clazz.setRepository(this); + } + + /** + * Remove class from repository + */ + public void removeClass(JavaClass clazz) { + synchronized (loadedClasses) { + loadedClasses.remove(clazz.getClassName()); + } + } + + /** + * Find an already defined JavaClass. + */ + public JavaClass findClass(String className) { + synchronized (loadedClasses) { + if (loadedClasses.containsKey(className)) { + return loadedClasses.get(className); + } else { + return null; + } + } + } + + /** + * Clear all entries from cache. + */ + public void clear() { + synchronized (loadedClasses) { + loadedClasses.clear(); + } + } + + /** + * Lookup a JavaClass object from the Class Name provided. + */ + public JavaClass loadClass(String className) throws ClassNotFoundException { + + JavaClass javaClass = findClass(className); + if (javaClass != null) { + return javaClass; + } + + javaClass = loadJavaClass(className); + storeClass(javaClass); + + return javaClass; + } + + public JavaClass loadClass(Class clazz) throws ClassNotFoundException { + return loadClass(clazz.getName()); + } + + private JavaClass loadJavaClass(String className) throws ClassNotFoundException { + String classFile = className.replace('.', '/'); + try { + InputStream is = loaderRef.getClassLoader().getResourceAsStream(classFile + ".class"); + + if (is == null) { + throw new ClassNotFoundException(className + " not found."); + } + + ClassParser parser = new ClassParser(is, className); + return parser.parse(); + } catch (IOException e) { + throw new ClassNotFoundException(e.toString()); + } + } + +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/Repository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/Repository.java new file mode 100644 index 000000000..eea889e61 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/Repository.java @@ -0,0 +1,98 @@ +package org.aspectj.apache.bcel.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import org.aspectj.apache.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.aspectj.apache.bcel.Repository + * @version $Id: Repository.java,v 1.5 2009/09/09 19:56:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author David Dixon-Peugh + */ +public interface Repository { + /** + * 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(); +} diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/SyntheticRepository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/SyntheticRepository.java new file mode 100644 index 000000000..ea0e49216 --- /dev/null +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/SyntheticRepository.java @@ -0,0 +1,195 @@ +package org.aspectj.apache.bcel.util; + +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.WeakHashMap; + +import org.aspectj.apache.bcel.classfile.ClassParser; +import org.aspectj.apache.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.aspectj.apache.bcel.Repository + * + * @version $Id: SyntheticRepository.java,v 1.8 2009/09/09 19:56:20 aclement Exp $ + * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> + * @author David Dixon-Peugh + */ +public class SyntheticRepository implements Repository { + private static final String DEFAULT_PATH = ClassPath.getClassPath(); + + private static HashMap<ClassPath, SyntheticRepository> _instances = new HashMap<ClassPath, SyntheticRepository>(); // CLASSPATH + // X + // REPOSITORY + + private ClassPath _path = null; + private WeakHashMap<String, JavaClass> _loadedClasses = new WeakHashMap<String, JavaClass>(); // CLASSNAME X JAVACLASS + + private SyntheticRepository(ClassPath path) { + _path = path; + } + + public static SyntheticRepository getInstance() { + return getInstance(ClassPath.getSystemClassPath()); + } + + public static SyntheticRepository getInstance(ClassPath classPath) { + SyntheticRepository rep = _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(), 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) { + return _loadedClasses.get(className); + } + + /** + * Load a JavaClass object for the given class name using the CLASSPATH environment variable. + */ + 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 + + try { + return loadClass(_path.getInputStream(className), className); + } catch (IOException e) { + throw new ClassNotFoundException("Exception while looking for class " + className + ": " + e.toString()); + } + } + + /** + * Try to find class source via getResourceAsStream(). + * + * @see Class + * @return JavaClass object for given runtime class + */ + public JavaClass loadClass(Class clazz) throws ClassNotFoundException { + String className = clazz.getName(); + String name = className; + int i = name.lastIndexOf('.'); + + if (i > 0) { + name = name.substring(i + 1); + } + + return loadClass(clazz.getResourceAsStream(name + ".class"), className); + } + + private JavaClass loadClass(InputStream is, String className) throws ClassNotFoundException { + JavaClass clazz = findClass(className); + + if (clazz != null) { + return clazz; + } + + try { + if (is != null) { + ClassParser parser = new ClassParser(is, className); + clazz = parser.parse(); + + storeClass(clazz); + + return clazz; + } + } catch (IOException e) { + throw new ClassNotFoundException("Exception while looking for class " + className + ": " + e.toString()); + } + + throw new ClassNotFoundException("SyntheticRepository could not load " + className); + } + + /** + * Clear all entries from cache. + */ + public void clear() { + _loadedClasses.clear(); + } +} |