From eebd1b81eed21e27dc0b30ece635aeda644ce635 Mon Sep 17 00:00:00 2001 From: markt Date: Fri, 4 Dec 2009 17:49:49 +0000 Subject: [PATCH] Import a a package renamed Jakarta BCEL trunk to do the annotation scanning. There is a lot of fat still to be trimmed. This was done as an svn copy so future updates should be simple via svn merge. git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@887296 13f79535-47bb-0310-9956-ffa450edef68 --- java/org/apache/tomcat/util/bcel/Constants.java | 1467 +++++++++++++++++++ .../tomcat/util/bcel/ExceptionConstants.java | 76 + java/org/apache/tomcat/util/bcel/Repository.java | 261 ++++ .../tomcat/util/bcel/classfile/AccessFlags.java | 238 +++ .../util/bcel/classfile/AnnotationDefault.java | 115 ++ .../bcel/classfile/AnnotationElementValue.java | 43 + .../util/bcel/classfile/AnnotationEntry.java | 152 ++ .../tomcat/util/bcel/classfile/Annotations.java | 127 ++ .../util/bcel/classfile/ArrayElementValue.java | 67 + .../tomcat/util/bcel/classfile/Attribute.java | 323 +++++ .../util/bcel/classfile/AttributeReader.java | 58 + .../util/bcel/classfile/ClassElementValue.java | 44 + .../util/bcel/classfile/ClassFormatException.java | 41 + .../tomcat/util/bcel/classfile/ClassParser.java | 302 ++++ .../apache/tomcat/util/bcel/classfile/Code.java | 352 +++++ .../tomcat/util/bcel/classfile/CodeException.java | 215 +++ .../tomcat/util/bcel/classfile/Constant.java | 188 +++ .../tomcat/util/bcel/classfile/ConstantCP.java | 132 ++ .../tomcat/util/bcel/classfile/ConstantClass.java | 129 ++ .../tomcat/util/bcel/classfile/ConstantDouble.java | 120 ++ .../util/bcel/classfile/ConstantFieldref.java | 69 + .../tomcat/util/bcel/classfile/ConstantFloat.java | 121 ++ .../util/bcel/classfile/ConstantInteger.java | 120 ++ .../bcel/classfile/ConstantInterfaceMethodref.java | 69 + .../tomcat/util/bcel/classfile/ConstantLong.java | 120 ++ .../util/bcel/classfile/ConstantMethodref.java | 69 + .../util/bcel/classfile/ConstantNameAndType.java | 149 ++ .../tomcat/util/bcel/classfile/ConstantObject.java | 32 + .../tomcat/util/bcel/classfile/ConstantPool.java | 353 +++++ .../tomcat/util/bcel/classfile/ConstantString.java | 128 ++ .../tomcat/util/bcel/classfile/ConstantUtf8.java | 117 ++ .../tomcat/util/bcel/classfile/ConstantValue.java | 156 ++ .../tomcat/util/bcel/classfile/Deprecated.java | 140 ++ .../util/bcel/classfile/DescendingVisitor.java | 445 ++++++ .../tomcat/util/bcel/classfile/ElementValue.java | 142 ++ .../util/bcel/classfile/ElementValuePair.java | 75 + .../tomcat/util/bcel/classfile/EmptyVisitor.java | 191 +++ .../util/bcel/classfile/EnclosingMethod.java | 87 ++ .../util/bcel/classfile/EnumElementValue.java | 62 + .../tomcat/util/bcel/classfile/ExceptionTable.java | 180 +++ .../apache/tomcat/util/bcel/classfile/Field.java | 190 +++ .../tomcat/util/bcel/classfile/FieldOrMethod.java | 290 ++++ .../tomcat/util/bcel/classfile/InnerClass.java | 215 +++ .../tomcat/util/bcel/classfile/InnerClasses.java | 150 ++ .../tomcat/util/bcel/classfile/JavaClass.java | 933 ++++++++++++ .../tomcat/util/bcel/classfile/LineNumber.java | 141 ++ .../util/bcel/classfile/LineNumberTable.java | 208 +++ .../tomcat/util/bcel/classfile/LocalVariable.java | 249 ++++ .../util/bcel/classfile/LocalVariableTable.java | 197 +++ .../bcel/classfile/LocalVariableTypeTable.java | 135 ++ .../apache/tomcat/util/bcel/classfile/Method.java | 254 ++++ .../apache/tomcat/util/bcel/classfile/Node.java | 28 + .../tomcat/util/bcel/classfile/PMGClass.java | 168 +++ .../bcel/classfile/ParameterAnnotationEntry.java | 77 + .../util/bcel/classfile/ParameterAnnotations.java | 114 ++ .../classfile/RuntimeInvisibleAnnotations.java | 66 + .../RuntimeInvisibleParameterAnnotations.java | 53 + .../bcel/classfile/RuntimeVisibleAnnotations.java | 66 + .../RuntimeVisibleParameterAnnotations.java | 53 + .../tomcat/util/bcel/classfile/Signature.java | 274 ++++ .../util/bcel/classfile/SimpleElementValue.java | 209 +++ .../tomcat/util/bcel/classfile/SourceFile.java | 146 ++ .../tomcat/util/bcel/classfile/StackMap.java | 153 ++ .../tomcat/util/bcel/classfile/StackMapEntry.java | 212 +++ .../tomcat/util/bcel/classfile/StackMapTable.java | 153 ++ .../util/bcel/classfile/StackMapTableEntry.java | 285 ++++ .../tomcat/util/bcel/classfile/StackMapType.java | 162 +++ .../tomcat/util/bcel/classfile/Synthetic.java | 150 ++ .../apache/tomcat/util/bcel/classfile/Unknown.java | 188 +++ .../apache/tomcat/util/bcel/classfile/Utility.java | 1525 ++++++++++++++++++++ .../apache/tomcat/util/bcel/classfile/Visitor.java | 108 ++ .../apache/tomcat/util/bcel/classfile/package.html | 14 + .../apache/tomcat/util/bcel/generic/AALOAD.java | 50 + .../apache/tomcat/util/bcel/generic/AASTORE.java | 50 + .../tomcat/util/bcel/generic/ACONST_NULL.java | 57 + .../org/apache/tomcat/util/bcel/generic/ALOAD.java | 57 + .../apache/tomcat/util/bcel/generic/ANEWARRAY.java | 79 + .../apache/tomcat/util/bcel/generic/ARETURN.java | 51 + .../tomcat/util/bcel/generic/ARRAYLENGTH.java | 57 + .../apache/tomcat/util/bcel/generic/ASTORE.java | 57 + .../apache/tomcat/util/bcel/generic/ATHROW.java | 58 + .../util/bcel/generic/AllocationInstruction.java | 26 + .../bcel/generic/AnnotationElementValueGen.java | 60 + .../util/bcel/generic/AnnotationEntryGen.java | 190 +++ .../util/bcel/generic/ArithmeticInstruction.java | 94 ++ .../util/bcel/generic/ArrayElementValueGen.java | 109 ++ .../tomcat/util/bcel/generic/ArrayInstruction.java | 81 ++ .../apache/tomcat/util/bcel/generic/ArrayType.java | 127 ++ .../apache/tomcat/util/bcel/generic/BALOAD.java | 50 + .../apache/tomcat/util/bcel/generic/BASTORE.java | 50 + .../apache/tomcat/util/bcel/generic/BIPUSH.java | 105 ++ .../tomcat/util/bcel/generic/BREAKPOINT.java | 43 + .../apache/tomcat/util/bcel/generic/BasicType.java | 81 ++ .../tomcat/util/bcel/generic/BranchHandle.java | 121 ++ .../util/bcel/generic/BranchInstruction.java | 230 +++ .../apache/tomcat/util/bcel/generic/CALOAD.java | 50 + .../apache/tomcat/util/bcel/generic/CASTORE.java | 50 + .../apache/tomcat/util/bcel/generic/CHECKCAST.java | 84 ++ .../tomcat/util/bcel/generic/CPInstruction.java | 138 ++ .../util/bcel/generic/ClassElementValueGen.java | 80 + .../apache/tomcat/util/bcel/generic/ClassGen.java | 611 ++++++++ .../util/bcel/generic/ClassGenException.java | 40 + .../tomcat/util/bcel/generic/ClassObserver.java | 29 + .../tomcat/util/bcel/generic/CodeExceptionGen.java | 184 +++ .../util/bcel/generic/CompoundInstruction.java | 38 + .../tomcat/util/bcel/generic/ConstantPoolGen.java | 783 ++++++++++ .../util/bcel/generic/ConstantPushInstruction.java | 32 + .../util/bcel/generic/ConversionInstruction.java | 76 + java/org/apache/tomcat/util/bcel/generic/D2F.java | 50 + java/org/apache/tomcat/util/bcel/generic/D2I.java | 50 + java/org/apache/tomcat/util/bcel/generic/D2L.java | 50 + java/org/apache/tomcat/util/bcel/generic/DADD.java | 51 + .../apache/tomcat/util/bcel/generic/DALOAD.java | 50 + .../apache/tomcat/util/bcel/generic/DASTORE.java | 50 + .../org/apache/tomcat/util/bcel/generic/DCMPG.java | 55 + .../org/apache/tomcat/util/bcel/generic/DCMPL.java | 55 + .../apache/tomcat/util/bcel/generic/DCONST.java | 80 + java/org/apache/tomcat/util/bcel/generic/DDIV.java | 51 + .../org/apache/tomcat/util/bcel/generic/DLOAD.java | 57 + java/org/apache/tomcat/util/bcel/generic/DMUL.java | 51 + java/org/apache/tomcat/util/bcel/generic/DNEG.java | 48 + java/org/apache/tomcat/util/bcel/generic/DREM.java | 51 + .../apache/tomcat/util/bcel/generic/DRETURN.java | 50 + .../apache/tomcat/util/bcel/generic/DSTORE.java | 57 + java/org/apache/tomcat/util/bcel/generic/DSUB.java | 51 + java/org/apache/tomcat/util/bcel/generic/DUP.java | 47 + java/org/apache/tomcat/util/bcel/generic/DUP2.java | 47 + .../apache/tomcat/util/bcel/generic/DUP2_X1.java | 45 + .../apache/tomcat/util/bcel/generic/DUP2_X2.java | 45 + .../apache/tomcat/util/bcel/generic/DUP_X1.java | 45 + .../apache/tomcat/util/bcel/generic/DUP_X2.java | 45 + .../tomcat/util/bcel/generic/ElementValueGen.java | 168 +++ .../util/bcel/generic/ElementValuePairGen.java | 93 ++ .../tomcat/util/bcel/generic/EmptyVisitor.java | 745 ++++++++++ .../util/bcel/generic/EnumElementValueGen.java | 119 ++ .../tomcat/util/bcel/generic/ExceptionThrower.java | 42 + java/org/apache/tomcat/util/bcel/generic/F2D.java | 50 + java/org/apache/tomcat/util/bcel/generic/F2I.java | 50 + java/org/apache/tomcat/util/bcel/generic/F2L.java | 50 + java/org/apache/tomcat/util/bcel/generic/FADD.java | 50 + .../apache/tomcat/util/bcel/generic/FALOAD.java | 50 + .../apache/tomcat/util/bcel/generic/FASTORE.java | 50 + .../org/apache/tomcat/util/bcel/generic/FCMPG.java | 54 + .../org/apache/tomcat/util/bcel/generic/FCMPL.java | 54 + .../apache/tomcat/util/bcel/generic/FCONST.java | 82 ++ java/org/apache/tomcat/util/bcel/generic/FDIV.java | 50 + .../org/apache/tomcat/util/bcel/generic/FLOAD.java | 57 + java/org/apache/tomcat/util/bcel/generic/FMUL.java | 50 + java/org/apache/tomcat/util/bcel/generic/FNEG.java | 48 + java/org/apache/tomcat/util/bcel/generic/FREM.java | 50 + .../apache/tomcat/util/bcel/generic/FRETURN.java | 50 + .../apache/tomcat/util/bcel/generic/FSTORE.java | 57 + java/org/apache/tomcat/util/bcel/generic/FSUB.java | 50 + .../apache/tomcat/util/bcel/generic/FieldGen.java | 374 +++++ .../util/bcel/generic/FieldGenOrMethodGen.java | 153 ++ .../tomcat/util/bcel/generic/FieldInstruction.java | 80 + .../tomcat/util/bcel/generic/FieldObserver.java | 29 + .../tomcat/util/bcel/generic/FieldOrMethod.java | 128 ++ .../apache/tomcat/util/bcel/generic/GETFIELD.java | 81 ++ .../apache/tomcat/util/bcel/generic/GETSTATIC.java | 79 + java/org/apache/tomcat/util/bcel/generic/GOTO.java | 89 ++ .../apache/tomcat/util/bcel/generic/GOTO_W.java | 79 + .../tomcat/util/bcel/generic/GotoInstruction.java | 38 + java/org/apache/tomcat/util/bcel/generic/I2B.java | 50 + java/org/apache/tomcat/util/bcel/generic/I2C.java | 50 + java/org/apache/tomcat/util/bcel/generic/I2D.java | 50 + java/org/apache/tomcat/util/bcel/generic/I2F.java | 50 + java/org/apache/tomcat/util/bcel/generic/I2L.java | 50 + java/org/apache/tomcat/util/bcel/generic/I2S.java | 48 + java/org/apache/tomcat/util/bcel/generic/IADD.java | 50 + .../apache/tomcat/util/bcel/generic/IALOAD.java | 51 + java/org/apache/tomcat/util/bcel/generic/IAND.java | 48 + .../apache/tomcat/util/bcel/generic/IASTORE.java | 51 + .../apache/tomcat/util/bcel/generic/ICONST.java | 78 + java/org/apache/tomcat/util/bcel/generic/IDIV.java | 60 + java/org/apache/tomcat/util/bcel/generic/IFEQ.java | 64 + java/org/apache/tomcat/util/bcel/generic/IFGE.java | 64 + java/org/apache/tomcat/util/bcel/generic/IFGT.java | 64 + java/org/apache/tomcat/util/bcel/generic/IFLE.java | 64 + java/org/apache/tomcat/util/bcel/generic/IFLT.java | 64 + java/org/apache/tomcat/util/bcel/generic/IFNE.java | 64 + .../apache/tomcat/util/bcel/generic/IFNONNULL.java | 64 + .../apache/tomcat/util/bcel/generic/IFNULL.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ACMPEQ.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ACMPNE.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPEQ.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPGE.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPGT.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPLE.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPLT.java | 64 + .../apache/tomcat/util/bcel/generic/IF_ICMPNE.java | 64 + java/org/apache/tomcat/util/bcel/generic/IINC.java | 158 ++ .../org/apache/tomcat/util/bcel/generic/ILOAD.java | 57 + .../apache/tomcat/util/bcel/generic/IMPDEP1.java | 43 + .../apache/tomcat/util/bcel/generic/IMPDEP2.java | 43 + java/org/apache/tomcat/util/bcel/generic/IMUL.java | 50 + java/org/apache/tomcat/util/bcel/generic/INEG.java | 48 + .../tomcat/util/bcel/generic/INSTANCEOF.java | 73 + .../tomcat/util/bcel/generic/INVOKEINTERFACE.java | 132 ++ .../tomcat/util/bcel/generic/INVOKESPECIAL.java | 77 + .../tomcat/util/bcel/generic/INVOKESTATIC.java | 74 + .../tomcat/util/bcel/generic/INVOKEVIRTUAL.java | 76 + java/org/apache/tomcat/util/bcel/generic/IOR.java | 48 + java/org/apache/tomcat/util/bcel/generic/IREM.java | 60 + .../apache/tomcat/util/bcel/generic/IRETURN.java | 50 + java/org/apache/tomcat/util/bcel/generic/ISHL.java | 48 + java/org/apache/tomcat/util/bcel/generic/ISHR.java | 48 + .../apache/tomcat/util/bcel/generic/ISTORE.java | 57 + java/org/apache/tomcat/util/bcel/generic/ISUB.java | 50 + .../org/apache/tomcat/util/bcel/generic/IUSHR.java | 48 + java/org/apache/tomcat/util/bcel/generic/IXOR.java | 48 + .../tomcat/util/bcel/generic/IfInstruction.java | 48 + .../util/bcel/generic/IndexedInstruction.java | 32 + .../tomcat/util/bcel/generic/Instruction.java | 548 +++++++ .../util/bcel/generic/InstructionComparator.java | 69 + .../util/bcel/generic/InstructionConstants.java | 286 ++++ .../util/bcel/generic/InstructionFactory.java | 748 ++++++++++ .../util/bcel/generic/InstructionHandle.java | 290 ++++ .../tomcat/util/bcel/generic/InstructionList.java | 1277 ++++++++++++++++ .../util/bcel/generic/InstructionListObserver.java | 29 + .../util/bcel/generic/InstructionTargeter.java | 35 + .../util/bcel/generic/InvokeInstruction.java | 116 ++ java/org/apache/tomcat/util/bcel/generic/JSR.java | 86 ++ .../org/apache/tomcat/util/bcel/generic/JSR_W.java | 79 + .../tomcat/util/bcel/generic/JsrInstruction.java | 79 + java/org/apache/tomcat/util/bcel/generic/L2D.java | 48 + java/org/apache/tomcat/util/bcel/generic/L2F.java | 48 + java/org/apache/tomcat/util/bcel/generic/L2I.java | 48 + java/org/apache/tomcat/util/bcel/generic/LADD.java | 49 + .../apache/tomcat/util/bcel/generic/LALOAD.java | 50 + java/org/apache/tomcat/util/bcel/generic/LAND.java | 49 + .../apache/tomcat/util/bcel/generic/LASTORE.java | 50 + java/org/apache/tomcat/util/bcel/generic/LCMP.java | 55 + .../apache/tomcat/util/bcel/generic/LCONST.java | 80 + java/org/apache/tomcat/util/bcel/generic/LDC.java | 148 ++ .../apache/tomcat/util/bcel/generic/LDC2_W.java | 82 ++ .../org/apache/tomcat/util/bcel/generic/LDC_W.java | 54 + java/org/apache/tomcat/util/bcel/generic/LDIV.java | 57 + .../org/apache/tomcat/util/bcel/generic/LLOAD.java | 54 + java/org/apache/tomcat/util/bcel/generic/LMUL.java | 49 + java/org/apache/tomcat/util/bcel/generic/LNEG.java | 48 + .../tomcat/util/bcel/generic/LOOKUPSWITCH.java | 95 ++ java/org/apache/tomcat/util/bcel/generic/LOR.java | 48 + java/org/apache/tomcat/util/bcel/generic/LREM.java | 56 + .../apache/tomcat/util/bcel/generic/LRETURN.java | 48 + java/org/apache/tomcat/util/bcel/generic/LSHL.java | 48 + java/org/apache/tomcat/util/bcel/generic/LSHR.java | 48 + .../apache/tomcat/util/bcel/generic/LSTORE.java | 54 + java/org/apache/tomcat/util/bcel/generic/LSUB.java | 49 + .../org/apache/tomcat/util/bcel/generic/LUSHR.java | 48 + java/org/apache/tomcat/util/bcel/generic/LXOR.java | 48 + .../tomcat/util/bcel/generic/LineNumberGen.java | 108 ++ .../apache/tomcat/util/bcel/generic/LoadClass.java | 50 + .../tomcat/util/bcel/generic/LoadInstruction.java | 63 + .../tomcat/util/bcel/generic/LocalVariableGen.java | 208 +++ .../bcel/generic/LocalVariableInstruction.java | 202 +++ .../tomcat/util/bcel/generic/MONITORENTER.java | 53 + .../tomcat/util/bcel/generic/MONITOREXIT.java | 53 + .../tomcat/util/bcel/generic/MULTIANEWARRAY.java | 146 ++ .../apache/tomcat/util/bcel/generic/MethodGen.java | 1246 ++++++++++++++++ .../tomcat/util/bcel/generic/MethodObserver.java | 29 + java/org/apache/tomcat/util/bcel/generic/NEW.java | 76 + .../apache/tomcat/util/bcel/generic/NEWARRAY.java | 120 ++ java/org/apache/tomcat/util/bcel/generic/NOP.java | 43 + .../tomcat/util/bcel/generic/NamedAndTyped.java | 38 + .../tomcat/util/bcel/generic/ObjectType.java | 155 ++ java/org/apache/tomcat/util/bcel/generic/POP.java | 48 + java/org/apache/tomcat/util/bcel/generic/POP2.java | 48 + java/org/apache/tomcat/util/bcel/generic/PUSH.java | 178 +++ .../apache/tomcat/util/bcel/generic/PUTFIELD.java | 80 + .../apache/tomcat/util/bcel/generic/PUTSTATIC.java | 79 + .../tomcat/util/bcel/generic/PopInstruction.java | 29 + .../tomcat/util/bcel/generic/PushInstruction.java | 34 + java/org/apache/tomcat/util/bcel/generic/RET.java | 139 ++ .../apache/tomcat/util/bcel/generic/RETURN.java | 48 + .../tomcat/util/bcel/generic/ReferenceType.java | 330 +++++ .../util/bcel/generic/ReturnInstruction.java | 79 + .../util/bcel/generic/ReturnaddressType.java | 82 ++ .../apache/tomcat/util/bcel/generic/SALOAD.java | 48 + .../apache/tomcat/util/bcel/generic/SASTORE.java | 48 + .../apache/tomcat/util/bcel/generic/SIPUSH.java | 103 ++ java/org/apache/tomcat/util/bcel/generic/SWAP.java | 47 + .../apache/tomcat/util/bcel/generic/SWITCH.java | 153 ++ .../apache/tomcat/util/bcel/generic/Select.java | 236 +++ .../util/bcel/generic/SimpleElementValueGen.java | 245 ++++ .../tomcat/util/bcel/generic/StackConsumer.java | 30 + .../tomcat/util/bcel/generic/StackInstruction.java | 48 + .../tomcat/util/bcel/generic/StackProducer.java | 31 + .../tomcat/util/bcel/generic/StoreInstruction.java | 63 + .../tomcat/util/bcel/generic/TABLESWITCH.java | 107 ++ .../util/bcel/generic/TargetLostException.java | 67 + java/org/apache/tomcat/util/bcel/generic/Type.java | 369 +++++ .../tomcat/util/bcel/generic/TypedInstruction.java | 29 + .../util/bcel/generic/UnconditionalBranch.java | 29 + .../bcel/generic/VariableLengthInstruction.java | 32 + .../apache/tomcat/util/bcel/generic/Visitor.java | 568 ++++++++ .../apache/tomcat/util/bcel/generic/package.html | 16 + java/org/apache/tomcat/util/bcel/package.html | 17 + .../tomcat/util/bcel/util/AttributeHTML.java | 211 +++ .../tomcat/util/bcel/util/BCELComparator.java | 45 + .../apache/tomcat/util/bcel/util/BCELFactory.java | 332 +++++ .../apache/tomcat/util/bcel/util/BCELifier.java | 268 ++++ .../apache/tomcat/util/bcel/util/ByteSequence.java | 68 + .../apache/tomcat/util/bcel/util/Class2HTML.java | 231 +++ .../apache/tomcat/util/bcel/util/ClassLoader.java | 184 +++ .../util/bcel/util/ClassLoaderRepository.java | 121 ++ .../apache/tomcat/util/bcel/util/ClassPath.java | 485 +++++++ .../apache/tomcat/util/bcel/util/ClassQueue.java | 52 + .../org/apache/tomcat/util/bcel/util/ClassSet.java | 69 + .../apache/tomcat/util/bcel/util/ClassStack.java | 52 + .../apache/tomcat/util/bcel/util/ClassVector.java | 57 + .../org/apache/tomcat/util/bcel/util/CodeHTML.java | 567 ++++++++ .../apache/tomcat/util/bcel/util/ConstantHTML.java | 233 +++ .../tomcat/util/bcel/util/InstructionFinder.java | 428 ++++++ .../apache/tomcat/util/bcel/util/JavaWrapper.java | 117 ++ .../apache/tomcat/util/bcel/util/MethodHTML.java | 156 ++ .../apache/tomcat/util/bcel/util/Repository.java | 73 + .../tomcat/util/bcel/util/SyntheticRepository.java | 202 +++ java/org/apache/tomcat/util/bcel/util/package.html | 25 + 319 files changed, 41106 insertions(+) create mode 100644 java/org/apache/tomcat/util/bcel/Constants.java create mode 100644 java/org/apache/tomcat/util/bcel/ExceptionConstants.java create mode 100644 java/org/apache/tomcat/util/bcel/Repository.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/AccessFlags.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/AnnotationDefault.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/AnnotationElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Annotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ArrayElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Attribute.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/AttributeReader.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ClassElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ClassFormatException.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ClassParser.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Code.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/CodeException.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Constant.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantCP.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantFieldref.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantInterfaceMethodref.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantMethodref.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantNameAndType.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantObject.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantPool.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantString.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantUtf8.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ConstantValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Deprecated.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/DescendingVisitor.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ElementValuePair.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/EmptyVisitor.java create mode 100755 java/org/apache/tomcat/util/bcel/classfile/EnclosingMethod.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/EnumElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ExceptionTable.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Field.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/FieldOrMethod.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/InnerClass.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/InnerClasses.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/JavaClass.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/LineNumber.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/LineNumberTable.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/LocalVariable.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/LocalVariableTable.java create mode 100755 java/org/apache/tomcat/util/bcel/classfile/LocalVariableTypeTable.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Method.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Node.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/PMGClass.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotationEntry.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleAnnotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleParameterAnnotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleAnnotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleParameterAnnotations.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Signature.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/SimpleElementValue.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/SourceFile.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/StackMap.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/StackMapEntry.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/StackMapTable.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/StackMapTableEntry.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/StackMapType.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Synthetic.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Unknown.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Utility.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/Visitor.java create mode 100644 java/org/apache/tomcat/util/bcel/classfile/package.html create mode 100644 java/org/apache/tomcat/util/bcel/generic/AALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/AASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ACONST_NULL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ANEWARRAY.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ARETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ARRAYLENGTH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ATHROW.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/AllocationInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/AnnotationElementValueGen.java create mode 100755 java/org/apache/tomcat/util/bcel/generic/AnnotationEntryGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ArithmeticInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ArrayElementValueGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ArrayInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ArrayType.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BIPUSH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BREAKPOINT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BasicType.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BranchHandle.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/BranchInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CHECKCAST.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CPInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ClassElementValueGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ClassGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ClassGenException.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ClassObserver.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CodeExceptionGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/CompoundInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ConstantPoolGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ConstantPushInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ConversionInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/D2F.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/D2I.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/D2L.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DADD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DCMPG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DCMPL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DCONST.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DDIV.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DLOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DMUL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DNEG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DREM.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DRETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DSTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DSUB.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP2.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP2_X1.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP2_X2.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP_X1.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/DUP_X2.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ElementValueGen.java create mode 100755 java/org/apache/tomcat/util/bcel/generic/ElementValuePairGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/EmptyVisitor.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/EnumElementValueGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ExceptionThrower.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/F2D.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/F2I.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/F2L.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FADD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FCMPG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FCMPL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FCONST.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FDIV.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FLOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FMUL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FNEG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FREM.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FRETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FSTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FSUB.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FieldGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FieldGenOrMethodGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FieldInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FieldObserver.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/FieldOrMethod.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/GETFIELD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/GETSTATIC.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/GOTO.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/GOTO_W.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/GotoInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2B.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2C.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2D.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2F.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2L.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/I2S.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IADD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IAND.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ICONST.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IDIV.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFEQ.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFGE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFGT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFLE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFLT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFNE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFNONNULL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IFNULL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ACMPEQ.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ACMPNE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPEQ.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPGE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPGT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPLE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPLT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IF_ICMPNE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IINC.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ILOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IMPDEP1.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IMPDEP2.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IMUL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INEG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INSTANCEOF.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INVOKEINTERFACE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INVOKESPECIAL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INVOKESTATIC.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/INVOKEVIRTUAL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IOR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IREM.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IRETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ISHL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ISHR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ISTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ISUB.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IUSHR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IXOR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IfInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/IndexedInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/Instruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionComparator.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionConstants.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionFactory.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionHandle.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionList.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionListObserver.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InstructionTargeter.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/InvokeInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/JSR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/JSR_W.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/JsrInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/L2D.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/L2F.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/L2I.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LADD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LAND.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LCMP.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LCONST.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LDC.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LDC2_W.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LDC_W.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LDIV.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LLOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LMUL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LNEG.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LOOKUPSWITCH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LOR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LREM.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LRETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LSHL.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LSHR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LSTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LSUB.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LUSHR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LXOR.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LineNumberGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LoadClass.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LoadInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LocalVariableGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/LocalVariableInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/MONITORENTER.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/MONITOREXIT.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/MULTIANEWARRAY.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/MethodGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/MethodObserver.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/NEW.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/NEWARRAY.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/NOP.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/NamedAndTyped.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ObjectType.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/POP.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/POP2.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/PUSH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/PUTFIELD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/PUTSTATIC.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/PopInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/PushInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/RET.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/RETURN.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ReferenceType.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ReturnInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/ReturnaddressType.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SALOAD.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SASTORE.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SIPUSH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SWAP.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SWITCH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/Select.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/SimpleElementValueGen.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/StackConsumer.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/StackInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/StackProducer.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/StoreInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/TABLESWITCH.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/TargetLostException.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/Type.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/TypedInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/UnconditionalBranch.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/VariableLengthInstruction.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/Visitor.java create mode 100644 java/org/apache/tomcat/util/bcel/generic/package.html create mode 100644 java/org/apache/tomcat/util/bcel/package.html create mode 100644 java/org/apache/tomcat/util/bcel/util/AttributeHTML.java create mode 100644 java/org/apache/tomcat/util/bcel/util/BCELComparator.java create mode 100644 java/org/apache/tomcat/util/bcel/util/BCELFactory.java create mode 100644 java/org/apache/tomcat/util/bcel/util/BCELifier.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ByteSequence.java create mode 100644 java/org/apache/tomcat/util/bcel/util/Class2HTML.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassLoader.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassLoaderRepository.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassPath.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassQueue.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassSet.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassStack.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ClassVector.java create mode 100644 java/org/apache/tomcat/util/bcel/util/CodeHTML.java create mode 100644 java/org/apache/tomcat/util/bcel/util/ConstantHTML.java create mode 100644 java/org/apache/tomcat/util/bcel/util/InstructionFinder.java create mode 100644 java/org/apache/tomcat/util/bcel/util/JavaWrapper.java create mode 100644 java/org/apache/tomcat/util/bcel/util/MethodHTML.java create mode 100644 java/org/apache/tomcat/util/bcel/util/Repository.java create mode 100644 java/org/apache/tomcat/util/bcel/util/SyntheticRepository.java create mode 100644 java/org/apache/tomcat/util/bcel/util/package.html diff --git a/java/org/apache/tomcat/util/bcel/Constants.java b/java/org/apache/tomcat/util/bcel/Constants.java new file mode 100644 index 000000000..5a029730d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/Constants.java @@ -0,0 +1,1467 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel; + +/** + * Constants for the project, mostly defined in the JVM specification. + * + * @version $Id$ + * @author M. Dahm + */ +public interface Constants { + + /** Major version number of class files for Java 1.1. + * @see #MINOR_1_1 + * */ + public final static short MAJOR_1_1 = 45; + + /** Minor version number of class files for Java 1.1. + * @see #MAJOR_1_1 + * */ + public final static short MINOR_1_1 = 3; + + /** Major version number of class files for Java 1.2. + * @see #MINOR_1_2 + * */ + public final static short MAJOR_1_2 = 46; + + /** Minor version number of class files for Java 1.2. + * @see #MAJOR_1_2 + * */ + public final static short MINOR_1_2 = 0; + + /** Major version number of class files for Java 1.2. + * @see #MINOR_1_2 + * */ + public final static short MAJOR_1_3 = 47; + + /** Minor version number of class files for Java 1.3. + * @see #MAJOR_1_3 + * */ + public final static short MINOR_1_3 = 0; + + /** Major version number of class files for Java 1.3. + * @see #MINOR_1_3 + * */ + public final static short MAJOR_1_4 = 48; + + /** Minor version number of class files for Java 1.4. + * @see #MAJOR_1_4 + * */ + public final static short MINOR_1_4 = 0; + + /** Major version number of class files for Java 1.4. + * @see #MINOR_1_4 + * */ + public final static short MAJOR_1_5 = 49; + + /** Minor version number of class files for Java 1.5. + * @see #MAJOR_1_5 + * */ + public final static short MINOR_1_5 = 0; + + /** Major version number of class files for Java 1.5. + * @see #MINOR_1_5 + * */ + public final static short MAJOR_1_6 = 50; + + /** Minor version number of class files for Java 1.6. + * @see #MAJOR_1_6 + * */ + public final static short MINOR_1_6 = 0; + + /** Default major version number. Class file is for Java 1.1. + * @see #MAJOR_1_1 + * */ + public final static short MAJOR = MAJOR_1_1; + + /** Default major version number. Class file is for Java 1.1. + * @see #MAJOR_1_1 + * */ + public final static short MINOR = MINOR_1_1; + + /** Maximum value for an unsigned short. + */ + public final static int MAX_SHORT = 65535; // 2^16 - 1 + + /** Maximum value for an unsigned byte. + */ + public final static int MAX_BYTE = 255; // 2^8 - 1 + + /** One of the access flags for fields, methods, or classes. + * @see Flag definitions for Fields in the Java Virtual Machine Specification (2nd edition). + * @see Flag definitions for Methods in the Java Virtual Machine Specification (2nd edition). + * @see Flag definitions for Classes in the Java Virtual Machine Specification (2nd edition). + */ + public final static short ACC_PUBLIC = 0x0001; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_PRIVATE = 0x0002; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_PROTECTED = 0x0004; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_STATIC = 0x0008; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_FINAL = 0x0010; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_SYNCHRONIZED = 0x0020; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_SYPER = 0x0020; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_VOLATILE = 0x0040; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_BRIDGE = 0x0040; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_TRANSIENT = 0x0080; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_VARARGS = 0x0080; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_NATIVE = 0x0100; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_INTERFACE = 0x0200; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_ABSTRACT = 0x0400; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_STRICT = 0x0800; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_SYNTHETIC = 0x1000; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_ANNOTATION = 0x2000; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_ENUM = 0x4000; + + // Applies to classes compiled by new compilers only + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short ACC_SUPER = 0x0020; + + /** One of the access flags for fields, methods, or classes. + * @see #ACC_PUBLIC + */ + public final static short MAX_ACC_FLAG = ACC_ENUM; + + /** The names of the access flags. */ + public final static String[] ACCESS_NAMES = { + "public", "private", "protected", "static", "final", "synchronized", + "volatile", "transient", "native", "interface", "abstract", "strictfp", + "synthetic", "annotation", "enum" + }; + + /** Marks a constant pool entry as type UTF-8. */ + public final static byte CONSTANT_Utf8 = 1; + + /** Marks a constant pool entry as type Integer. */ + public final static byte CONSTANT_Integer = 3; + + /** Marks a constant pool entry as type Float. */ + public final static byte CONSTANT_Float = 4; + + /** Marks a constant pool entry as type Long. */ + public final static byte CONSTANT_Long = 5; + + /** Marks a constant pool entry as type Double. */ + public final static byte CONSTANT_Double = 6; + + /** Marks a constant pool entry as a Class. */ + public final static byte CONSTANT_Class = 7; + + /** Marks a constant pool entry as a Field Reference. */ + public final static byte CONSTANT_Fieldref = 9; + + /** Marks a constant pool entry as type String. */ + public final static byte CONSTANT_String = 8; + + /** Marks a constant pool entry as a Method Reference. */ + public final static byte CONSTANT_Methodref = 10; + + /** Marks a constant pool entry as an Interface Method Reference. */ + public final static byte CONSTANT_InterfaceMethodref = 11; + + /** Marks a constant pool entry as a name and type. */ + public final static byte CONSTANT_NameAndType = 12; + + /** The names of the types of entries in a constant pool. */ + public final static String[] CONSTANT_NAMES = { + "", "CONSTANT_Utf8", "", "CONSTANT_Integer", + "CONSTANT_Float", "CONSTANT_Long", "CONSTANT_Double", + "CONSTANT_Class", "CONSTANT_String", "CONSTANT_Fieldref", + "CONSTANT_Methodref", "CONSTANT_InterfaceMethodref", + "CONSTANT_NameAndType" }; + + /** The name of the static initializer, also called "class + * initialization method" or "interface initialization + * method". This is "<clinit>". + */ + public final static String STATIC_INITIALIZER_NAME = ""; + + /** The name of every constructor method in a class, also called + * "instance initialization method". This is "<init>". + */ + public final static String CONSTRUCTOR_NAME = ""; + + /** The names of the interfaces implemented by arrays */ + public final static String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"}; + + /** + * One of the limitations of the Java Virtual Machine. + * @see The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10. + */ + public static final int MAX_CP_ENTRIES = 65535; + + /** + * One of the limitations of the Java Virtual Machine. + * @see The Java Virtual Machine Specification, Second Edition, page 152, chapter 4.10. + */ + public static final int MAX_CODE_SIZE = 65536; //bytes + + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short NOP = 0; + + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ACONST_NULL = 1; + + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_M1 = 2; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_0 = 3; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_1 = 4; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_2 = 5; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_3 = 6; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_4 = 7; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ICONST_5 = 8; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LCONST_0 = 9; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LCONST_1 = 10; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FCONST_0 = 11; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FCONST_1 = 12; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FCONST_2 = 13; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DCONST_0 = 14; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DCONST_1 = 15; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short BIPUSH = 16; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short SIPUSH = 17; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LDC = 18; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LDC_W = 19; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LDC2_W = 20; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ILOAD = 21; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LLOAD = 22; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FLOAD = 23; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DLOAD = 24; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ALOAD = 25; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ILOAD_0 = 26; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ILOAD_1 = 27; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ILOAD_2 = 28; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ILOAD_3 = 29; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LLOAD_0 = 30; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LLOAD_1 = 31; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LLOAD_2 = 32; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LLOAD_3 = 33; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FLOAD_0 = 34; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FLOAD_1 = 35; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FLOAD_2 = 36; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FLOAD_3 = 37; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DLOAD_0 = 38; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DLOAD_1 = 39; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DLOAD_2 = 40; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DLOAD_3 = 41; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ALOAD_0 = 42; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ALOAD_1 = 43; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ALOAD_2 = 44; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ALOAD_3 = 45; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IALOAD = 46; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LALOAD = 47; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FALOAD = 48; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DALOAD = 49; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short AALOAD = 50; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short BALOAD = 51; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short CALOAD = 52; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short SALOAD = 53; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISTORE = 54; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSTORE = 55; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSTORE = 56; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSTORE = 57; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ASTORE = 58; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISTORE_0 = 59; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISTORE_1 = 60; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISTORE_2 = 61; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISTORE_3 = 62; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSTORE_0 = 63; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSTORE_1 = 64; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSTORE_2 = 65; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSTORE_3 = 66; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSTORE_0 = 67; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSTORE_1 = 68; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSTORE_2 = 69; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSTORE_3 = 70; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSTORE_0 = 71; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSTORE_1 = 72; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSTORE_2 = 73; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSTORE_3 = 74; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ASTORE_0 = 75; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ASTORE_1 = 76; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ASTORE_2 = 77; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ASTORE_3 = 78; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IASTORE = 79; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LASTORE = 80; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FASTORE = 81; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DASTORE = 82; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short AASTORE = 83; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short BASTORE = 84; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short CASTORE = 85; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short SASTORE = 86; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short POP = 87; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short POP2 = 88; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP = 89; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP_X1 = 90; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP_X2 = 91; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP2 = 92; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP2_X1 = 93; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DUP2_X2 = 94; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short SWAP = 95; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IADD = 96; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LADD = 97; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FADD = 98; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DADD = 99; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISUB = 100; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSUB = 101; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FSUB = 102; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DSUB = 103; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IMUL = 104; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LMUL = 105; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FMUL = 106; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DMUL = 107; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IDIV = 108; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LDIV = 109; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FDIV = 110; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DDIV = 111; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IREM = 112; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LREM = 113; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FREM = 114; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DREM = 115; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INEG = 116; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LNEG = 117; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FNEG = 118; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DNEG = 119; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISHL = 120; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSHL = 121; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ISHR = 122; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LSHR = 123; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IUSHR = 124; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LUSHR = 125; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IAND = 126; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LAND = 127; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IOR = 128; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LOR = 129; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IXOR = 130; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LXOR = 131; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IINC = 132; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2L = 133; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2F = 134; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2D = 135; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short L2I = 136; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short L2F = 137; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short L2D = 138; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short F2I = 139; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short F2L = 140; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short F2D = 141; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short D2I = 142; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short D2L = 143; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short D2F = 144; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2B = 145; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INT2BYTE = 145; // Old notion + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2C = 146; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INT2CHAR = 146; // Old notion + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short I2S = 147; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INT2SHORT = 147; // Old notion + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LCMP = 148; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FCMPL = 149; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FCMPG = 150; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DCMPL = 151; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DCMPG = 152; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFEQ = 153; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFNE = 154; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFLT = 155; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFGE = 156; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFGT = 157; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFLE = 158; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPEQ = 159; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPNE = 160; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPLT = 161; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPGE = 162; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPGT = 163; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ICMPLE = 164; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ACMPEQ = 165; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IF_ACMPNE = 166; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short GOTO = 167; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short JSR = 168; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short RET = 169; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short TABLESWITCH = 170; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LOOKUPSWITCH = 171; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IRETURN = 172; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short LRETURN = 173; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short FRETURN = 174; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short DRETURN = 175; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ARETURN = 176; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short RETURN = 177; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short GETSTATIC = 178; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short PUTSTATIC = 179; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short GETFIELD = 180; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short PUTFIELD = 181; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKEVIRTUAL = 182; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKESPECIAL = 183; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0 + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKESTATIC = 184; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKEINTERFACE = 185; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INVOKEDYNAMIC = 186; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short NEW = 187; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short NEWARRAY = 188; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ANEWARRAY = 189; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ARRAYLENGTH = 190; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short ATHROW = 191; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short CHECKCAST = 192; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short INSTANCEOF = 193; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short MONITORENTER = 194; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short MONITOREXIT = 195; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short WIDE = 196; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short MULTIANEWARRAY = 197; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFNULL = 198; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short IFNONNULL = 199; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short GOTO_W = 200; + /** Java VM opcode. + * @see Opcode definitions in The Java Virtual Machine Specification */ + public static final short JSR_W = 201; + + /** JVM internal opcode. + * @see Reserved opcodes in the Java Virtual Machine Specification */ + public static final short BREAKPOINT = 202; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short LDC_QUICK = 203; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short LDC_W_QUICK = 204; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short LDC2_W_QUICK = 205; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short GETFIELD_QUICK = 206; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short PUTFIELD_QUICK = 207; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short GETFIELD2_QUICK = 208; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short PUTFIELD2_QUICK = 209; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short GETSTATIC_QUICK = 210; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short PUTSTATIC_QUICK = 211; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short GETSTATIC2_QUICK = 212; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short PUTSTATIC2_QUICK = 213; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKEVIRTUAL_QUICK = 214; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKENONVIRTUAL_QUICK = 215; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKESUPER_QUICK = 216; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKESTATIC_QUICK = 217; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKEINTERFACE_QUICK = 218; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKEVIRTUALOBJECT_QUICK = 219; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short NEW_QUICK = 221; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short ANEWARRAY_QUICK = 222; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short MULTIANEWARRAY_QUICK = 223; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short CHECKCAST_QUICK = 224; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INSTANCEOF_QUICK = 225; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short INVOKEVIRTUAL_QUICK_W = 226; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short GETFIELD_QUICK_W = 227; + /** JVM internal opcode. + * @see Specification of _quick opcodes in the Java Virtual Machine Specification (version 1) + * @see Why the _quick opcodes were removed from the second version of the Java Virtual Machine Specification. */ + public static final short PUTFIELD_QUICK_W = 228; + /** JVM internal opcode. + * @see Reserved opcodes in the Java Virtual Machine Specification */ + public static final short IMPDEP1 = 254; + /** JVM internal opcode. + * @see Reserved opcodes in the Java Virtual Machine Specification */ + public static final short IMPDEP2 = 255; + + /** + * BCEL virtual instruction for pushing an arbitrary data type onto the stack. Will be converted to the appropriate JVM + * opcode when the class is dumped. + */ + public static final short PUSH = 4711; + /** + * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH. Will be converted to the appropriate JVM + * opcode when the class is dumped. + */ + public static final short SWITCH = 4712; + + /** Illegal opcode. */ + public static final short UNDEFINED = -1; + /** Illegal opcode. */ + public static final short UNPREDICTABLE = -2; + /** Illegal opcode. */ + public static final short RESERVED = -3; + /** Mnemonic for an illegal opcode. */ + public static final String ILLEGAL_OPCODE = ""; + /** Mnemonic for an illegal type. */ + public static final String ILLEGAL_TYPE = ""; + + /** Boolean data type. */ + public static final byte T_BOOLEAN = 4; + /** Char data type. */ + public static final byte T_CHAR = 5; + /** Float data type. */ + public static final byte T_FLOAT = 6; + /** Double data type. */ + public static final byte T_DOUBLE = 7; + /** Byte data type. */ + public static final byte T_BYTE = 8; + /** Short data type. */ + public static final byte T_SHORT = 9; + /** Int data type. */ + public static final byte T_INT = 10; + /** Long data type. */ + public static final byte T_LONG = 11; + + /** Void data type (non-standard). */ + public static final byte T_VOID = 12; // Non-standard + /** Array data type. */ + public static final byte T_ARRAY = 13; + /** Object data type. */ + public static final byte T_OBJECT = 14; + /** Reference data type (deprecated). */ + public static final byte T_REFERENCE = 14; // Deprecated + /** Unknown data type. */ + public static final byte T_UNKNOWN = 15; + /** Address data type. */ + public static final byte T_ADDRESS = 16; + + /** The primitive type names corresponding to the T_XX constants, + * e.g., TYPE_NAMES[T_INT] = "int" + */ + public static final String[] TYPE_NAMES = { + ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, + "boolean", "char", "float", "double", "byte", "short", "int", "long", + "void", "array", "object", "unknown", "address" + }; + + /** The primitive class names corresponding to the T_XX constants, + * e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer" + */ + public static final String[] CLASS_TYPE_NAMES = { + ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, + "java.lang.Boolean", "java.lang.Character", "java.lang.Float", + "java.lang.Double", "java.lang.Byte", "java.lang.Short", + "java.lang.Integer", "java.lang.Long", "java.lang.Void", + ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE + }; + + /** The signature characters corresponding to primitive types, + * e.g., SHORT_TYPE_NAMES[T_INT] = "I" + */ + public static final String[] SHORT_TYPE_NAMES = { + ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, + "Z", "C", "F", "D", "B", "S", "I", "J", + "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE + }; + + /** + * Number of byte code operands for each opcode, i.e., number of bytes after the tag byte + * itself. Indexed by opcode, so NO_OF_OPERANDS[BIPUSH] = the number of operands for a bipush + * instruction. + */ + public static final short[] NO_OF_OPERANDS = { + 0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/, + 0/*iconst_1*/, 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/, + 0/*iconst_5*/, 0/*lconst_0*/, 0/*lconst_1*/, 0/*fconst_0*/, + 0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, 0/*dconst_1*/, + 1/*bipush*/, 2/*sipush*/, 1/*ldc*/, 2/*ldc_w*/, 2/*ldc2_w*/, + 1/*iload*/, 1/*lload*/, 1/*fload*/, 1/*dload*/, 1/*aload*/, + 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, 0/*iload_3*/, + 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, + 0/*fload_0*/, 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, + 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, 0/*dload_3*/, + 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, + 0/*iaload*/, 0/*laload*/, 0/*faload*/, 0/*daload*/, + 0/*aaload*/, 0/*baload*/, 0/*caload*/, 0/*saload*/, + 1/*istore*/, 1/*lstore*/, 1/*fstore*/, 1/*dstore*/, + 1/*astore*/, 0/*istore_0*/, 0/*istore_1*/, 0/*istore_2*/, + 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, 0/*lstore_2*/, + 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/, + 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, + 0/*dstore_3*/, 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, + 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, 0/*fastore*/, + 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, + 0/*sastore*/, 0/*pop*/, 0/*pop2*/, 0/*dup*/, 0/*dup_x1*/, + 0/*dup_x2*/, 0/*dup2*/, 0/*dup2_x1*/, 0/*dup2_x2*/, 0/*swap*/, + 0/*iadd*/, 0/*ladd*/, 0/*fadd*/, 0/*dadd*/, 0/*isub*/, + 0/*lsub*/, 0/*fsub*/, 0/*dsub*/, 0/*imul*/, 0/*lmul*/, + 0/*fmul*/, 0/*dmul*/, 0/*idiv*/, 0/*ldiv*/, 0/*fdiv*/, + 0/*ddiv*/, 0/*irem*/, 0/*lrem*/, 0/*frem*/, 0/*drem*/, + 0/*ineg*/, 0/*lneg*/, 0/*fneg*/, 0/*dneg*/, 0/*ishl*/, + 0/*lshl*/, 0/*ishr*/, 0/*lshr*/, 0/*iushr*/, 0/*lushr*/, + 0/*iand*/, 0/*land*/, 0/*ior*/, 0/*lor*/, 0/*ixor*/, 0/*lxor*/, + 2/*iinc*/, 0/*i2l*/, 0/*i2f*/, 0/*i2d*/, 0/*l2i*/, 0/*l2f*/, + 0/*l2d*/, 0/*f2i*/, 0/*f2l*/, 0/*f2d*/, 0/*d2i*/, 0/*d2l*/, + 0/*d2f*/, 0/*i2b*/, 0/*i2c*/, 0/*i2s*/, 0/*lcmp*/, 0/*fcmpl*/, + 0/*fcmpg*/, 0/*dcmpl*/, 0/*dcmpg*/, 2/*ifeq*/, 2/*ifne*/, + 2/*iflt*/, 2/*ifge*/, 2/*ifgt*/, 2/*ifle*/, 2/*if_icmpeq*/, + 2/*if_icmpne*/, 2/*if_icmplt*/, 2/*if_icmpge*/, 2/*if_icmpgt*/, + 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, 2/*goto*/, + 2/*jsr*/, 1/*ret*/, UNPREDICTABLE/*tableswitch*/, UNPREDICTABLE/*lookupswitch*/, + 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/, + 0/*dreturn*/, 0/*areturn*/, 0/*return*/, + 2/*getstatic*/, 2/*putstatic*/, 2/*getfield*/, + 2/*putfield*/, 2/*invokevirtual*/, 2/*invokespecial*/, 2/*invokestatic*/, + 4/*invokeinterface*/, UNDEFINED, 2/*new*/, + 1/*newarray*/, 2/*anewarray*/, + 0/*arraylength*/, 0/*athrow*/, 2/*checkcast*/, + 2/*instanceof*/, 0/*monitorenter*/, + 0/*monitorexit*/, UNPREDICTABLE/*wide*/, 3/*multianewarray*/, + 2/*ifnull*/, 2/*ifnonnull*/, 4/*goto_w*/, + 4/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, RESERVED/*impdep1*/, RESERVED/*impdep2*/ + }; + + /** + * How the byte code operands are to be interpreted for each opcode. + * Indexed by opcode. TYPE_OF_OPERANDS[ILOAD] = an array of shorts + * describing the data types for the instruction. + */ + public static final short[][] TYPE_OF_OPERANDS = { + {}/*nop*/, {}/*aconst_null*/, {}/*iconst_m1*/, {}/*iconst_0*/, + {}/*iconst_1*/, {}/*iconst_2*/, {}/*iconst_3*/, {}/*iconst_4*/, + {}/*iconst_5*/, {}/*lconst_0*/, {}/*lconst_1*/, {}/*fconst_0*/, + {}/*fconst_1*/, {}/*fconst_2*/, {}/*dconst_0*/, {}/*dconst_1*/, + {T_BYTE}/*bipush*/, {T_SHORT}/*sipush*/, {T_BYTE}/*ldc*/, + {T_SHORT}/*ldc_w*/, {T_SHORT}/*ldc2_w*/, + {T_BYTE}/*iload*/, {T_BYTE}/*lload*/, {T_BYTE}/*fload*/, + {T_BYTE}/*dload*/, {T_BYTE}/*aload*/, {}/*iload_0*/, + {}/*iload_1*/, {}/*iload_2*/, {}/*iload_3*/, {}/*lload_0*/, + {}/*lload_1*/, {}/*lload_2*/, {}/*lload_3*/, {}/*fload_0*/, + {}/*fload_1*/, {}/*fload_2*/, {}/*fload_3*/, {}/*dload_0*/, + {}/*dload_1*/, {}/*dload_2*/, {}/*dload_3*/, {}/*aload_0*/, + {}/*aload_1*/, {}/*aload_2*/, {}/*aload_3*/, {}/*iaload*/, + {}/*laload*/, {}/*faload*/, {}/*daload*/, {}/*aaload*/, + {}/*baload*/, {}/*caload*/, {}/*saload*/, {T_BYTE}/*istore*/, + {T_BYTE}/*lstore*/, {T_BYTE}/*fstore*/, {T_BYTE}/*dstore*/, + {T_BYTE}/*astore*/, {}/*istore_0*/, {}/*istore_1*/, + {}/*istore_2*/, {}/*istore_3*/, {}/*lstore_0*/, {}/*lstore_1*/, + {}/*lstore_2*/, {}/*lstore_3*/, {}/*fstore_0*/, {}/*fstore_1*/, + {}/*fstore_2*/, {}/*fstore_3*/, {}/*dstore_0*/, {}/*dstore_1*/, + {}/*dstore_2*/, {}/*dstore_3*/, {}/*astore_0*/, {}/*astore_1*/, + {}/*astore_2*/, {}/*astore_3*/, {}/*iastore*/, {}/*lastore*/, + {}/*fastore*/, {}/*dastore*/, {}/*aastore*/, {}/*bastore*/, + {}/*castore*/, {}/*sastore*/, {}/*pop*/, {}/*pop2*/, {}/*dup*/, + {}/*dup_x1*/, {}/*dup_x2*/, {}/*dup2*/, {}/*dup2_x1*/, + {}/*dup2_x2*/, {}/*swap*/, {}/*iadd*/, {}/*ladd*/, {}/*fadd*/, + {}/*dadd*/, {}/*isub*/, {}/*lsub*/, {}/*fsub*/, {}/*dsub*/, + {}/*imul*/, {}/*lmul*/, {}/*fmul*/, {}/*dmul*/, {}/*idiv*/, + {}/*ldiv*/, {}/*fdiv*/, {}/*ddiv*/, {}/*irem*/, {}/*lrem*/, + {}/*frem*/, {}/*drem*/, {}/*ineg*/, {}/*lneg*/, {}/*fneg*/, + {}/*dneg*/, {}/*ishl*/, {}/*lshl*/, {}/*ishr*/, {}/*lshr*/, + {}/*iushr*/, {}/*lushr*/, {}/*iand*/, {}/*land*/, {}/*ior*/, + {}/*lor*/, {}/*ixor*/, {}/*lxor*/, {T_BYTE, T_BYTE}/*iinc*/, + {}/*i2l*/, {}/*i2f*/, {}/*i2d*/, {}/*l2i*/, {}/*l2f*/, {}/*l2d*/, + {}/*f2i*/, {}/*f2l*/, {}/*f2d*/, {}/*d2i*/, {}/*d2l*/, {}/*d2f*/, + {}/*i2b*/, {}/*i2c*/,{}/*i2s*/, {}/*lcmp*/, {}/*fcmpl*/, + {}/*fcmpg*/, {}/*dcmpl*/, {}/*dcmpg*/, {T_SHORT}/*ifeq*/, + {T_SHORT}/*ifne*/, {T_SHORT}/*iflt*/, {T_SHORT}/*ifge*/, + {T_SHORT}/*ifgt*/, {T_SHORT}/*ifle*/, {T_SHORT}/*if_icmpeq*/, + {T_SHORT}/*if_icmpne*/, {T_SHORT}/*if_icmplt*/, + {T_SHORT}/*if_icmpge*/, {T_SHORT}/*if_icmpgt*/, + {T_SHORT}/*if_icmple*/, {T_SHORT}/*if_acmpeq*/, + {T_SHORT}/*if_acmpne*/, {T_SHORT}/*goto*/, {T_SHORT}/*jsr*/, + {T_BYTE}/*ret*/, {}/*tableswitch*/, {}/*lookupswitch*/, + {}/*ireturn*/, {}/*lreturn*/, {}/*freturn*/, {}/*dreturn*/, + {}/*areturn*/, {}/*return*/, {T_SHORT}/*getstatic*/, + {T_SHORT}/*putstatic*/, {T_SHORT}/*getfield*/, + {T_SHORT}/*putfield*/, {T_SHORT}/*invokevirtual*/, + {T_SHORT}/*invokespecial*/, {T_SHORT}/*invokestatic*/, + {T_SHORT, T_BYTE, T_BYTE}/*invokeinterface*/, {}, + {T_SHORT}/*new*/, {T_BYTE}/*newarray*/, + {T_SHORT}/*anewarray*/, {}/*arraylength*/, {}/*athrow*/, + {T_SHORT}/*checkcast*/, {T_SHORT}/*instanceof*/, + {}/*monitorenter*/, {}/*monitorexit*/, {T_BYTE}/*wide*/, + {T_SHORT, T_BYTE}/*multianewarray*/, {T_SHORT}/*ifnull*/, + {T_SHORT}/*ifnonnull*/, {T_INT}/*goto_w*/, {T_INT}/*jsr_w*/, + {}/*breakpoint*/, {}, {}, {}, {}, {}, {}, {}, + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, + {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, + {}/*impdep1*/, {}/*impdep2*/ + }; + + /** + * Names of opcodes. Indexed by opcode. OPCODE_NAMES[ALOAD] = "aload". + */ + public static final String[] OPCODE_NAMES = { + "nop", "aconst_null", "iconst_m1", "iconst_0", "iconst_1", + "iconst_2", "iconst_3", "iconst_4", "iconst_5", "lconst_0", + "lconst_1", "fconst_0", "fconst_1", "fconst_2", "dconst_0", + "dconst_1", "bipush", "sipush", "ldc", "ldc_w", "ldc2_w", "iload", + "lload", "fload", "dload", "aload", "iload_0", "iload_1", "iload_2", + "iload_3", "lload_0", "lload_1", "lload_2", "lload_3", "fload_0", + "fload_1", "fload_2", "fload_3", "dload_0", "dload_1", "dload_2", + "dload_3", "aload_0", "aload_1", "aload_2", "aload_3", "iaload", + "laload", "faload", "daload", "aaload", "baload", "caload", "saload", + "istore", "lstore", "fstore", "dstore", "astore", "istore_0", + "istore_1", "istore_2", "istore_3", "lstore_0", "lstore_1", + "lstore_2", "lstore_3", "fstore_0", "fstore_1", "fstore_2", + "fstore_3", "dstore_0", "dstore_1", "dstore_2", "dstore_3", + "astore_0", "astore_1", "astore_2", "astore_3", "iastore", "lastore", + "fastore", "dastore", "aastore", "bastore", "castore", "sastore", + "pop", "pop2", "dup", "dup_x1", "dup_x2", "dup2", "dup2_x1", + "dup2_x2", "swap", "iadd", "ladd", "fadd", "dadd", "isub", "lsub", + "fsub", "dsub", "imul", "lmul", "fmul", "dmul", "idiv", "ldiv", + "fdiv", "ddiv", "irem", "lrem", "frem", "drem", "ineg", "lneg", + "fneg", "dneg", "ishl", "lshl", "ishr", "lshr", "iushr", "lushr", + "iand", "land", "ior", "lor", "ixor", "lxor", "iinc", "i2l", "i2f", + "i2d", "l2i", "l2f", "l2d", "f2i", "f2l", "f2d", "d2i", "d2l", "d2f", + "i2b", "i2c", "i2s", "lcmp", "fcmpl", "fcmpg", + "dcmpl", "dcmpg", "ifeq", "ifne", "iflt", "ifge", "ifgt", "ifle", + "if_icmpeq", "if_icmpne", "if_icmplt", "if_icmpge", "if_icmpgt", + "if_icmple", "if_acmpeq", "if_acmpne", "goto", "jsr", "ret", + "tableswitch", "lookupswitch", "ireturn", "lreturn", "freturn", + "dreturn", "areturn", "return", "getstatic", "putstatic", "getfield", + "putfield", "invokevirtual", "invokespecial", "invokestatic", + "invokeinterface", ILLEGAL_OPCODE, "new", "newarray", "anewarray", + "arraylength", "athrow", "checkcast", "instanceof", "monitorenter", + "monitorexit", "wide", "multianewarray", "ifnull", "ifnonnull", + "goto_w", "jsr_w", "breakpoint", ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, ILLEGAL_OPCODE, + ILLEGAL_OPCODE, "impdep1", "impdep2" + }; + + /** + * Number of words consumed on operand stack by instructions. + * Indexed by opcode. CONSUME_STACK[FALOAD] = number of words + * consumed from the stack by a faload instruction. + */ + public static final int[] CONSUME_STACK = { + 0/*nop*/, 0/*aconst_null*/, 0/*iconst_m1*/, 0/*iconst_0*/, 0/*iconst_1*/, + 0/*iconst_2*/, 0/*iconst_3*/, 0/*iconst_4*/, 0/*iconst_5*/, 0/*lconst_0*/, + 0/*lconst_1*/, 0/*fconst_0*/, 0/*fconst_1*/, 0/*fconst_2*/, 0/*dconst_0*/, + 0/*dconst_1*/, 0/*bipush*/, 0/*sipush*/, 0/*ldc*/, 0/*ldc_w*/, 0/*ldc2_w*/, 0/*iload*/, + 0/*lload*/, 0/*fload*/, 0/*dload*/, 0/*aload*/, 0/*iload_0*/, 0/*iload_1*/, 0/*iload_2*/, + 0/*iload_3*/, 0/*lload_0*/, 0/*lload_1*/, 0/*lload_2*/, 0/*lload_3*/, 0/*fload_0*/, + 0/*fload_1*/, 0/*fload_2*/, 0/*fload_3*/, 0/*dload_0*/, 0/*dload_1*/, 0/*dload_2*/, + 0/*dload_3*/, 0/*aload_0*/, 0/*aload_1*/, 0/*aload_2*/, 0/*aload_3*/, 2/*iaload*/, + 2/*laload*/, 2/*faload*/, 2/*daload*/, 2/*aaload*/, 2/*baload*/, 2/*caload*/, 2/*saload*/, + 1/*istore*/, 2/*lstore*/, 1/*fstore*/, 2/*dstore*/, 1/*astore*/, 1/*istore_0*/, + 1/*istore_1*/, 1/*istore_2*/, 1/*istore_3*/, 2/*lstore_0*/, 2/*lstore_1*/, + 2/*lstore_2*/, 2/*lstore_3*/, 1/*fstore_0*/, 1/*fstore_1*/, 1/*fstore_2*/, + 1/*fstore_3*/, 2/*dstore_0*/, 2/*dstore_1*/, 2/*dstore_2*/, 2/*dstore_3*/, + 1/*astore_0*/, 1/*astore_1*/, 1/*astore_2*/, 1/*astore_3*/, 3/*iastore*/, 4/*lastore*/, + 3/*fastore*/, 4/*dastore*/, 3/*aastore*/, 3/*bastore*/, 3/*castore*/, 3/*sastore*/, + 1/*pop*/, 2/*pop2*/, 1/*dup*/, 2/*dup_x1*/, 3/*dup_x2*/, 2/*dup2*/, 3/*dup2_x1*/, + 4/*dup2_x2*/, 2/*swap*/, 2/*iadd*/, 4/*ladd*/, 2/*fadd*/, 4/*dadd*/, 2/*isub*/, 4/*lsub*/, + 2/*fsub*/, 4/*dsub*/, 2/*imul*/, 4/*lmul*/, 2/*fmul*/, 4/*dmul*/, 2/*idiv*/, 4/*ldiv*/, + 2/*fdiv*/, 4/*ddiv*/, 2/*irem*/, 4/*lrem*/, 2/*frem*/, 4/*drem*/, 1/*ineg*/, 2/*lneg*/, + 1/*fneg*/, 2/*dneg*/, 2/*ishl*/, 3/*lshl*/, 2/*ishr*/, 3/*lshr*/, 2/*iushr*/, 3/*lushr*/, + 2/*iand*/, 4/*land*/, 2/*ior*/, 4/*lor*/, 2/*ixor*/, 4/*lxor*/, 0/*iinc*/, + 1/*i2l*/, 1/*i2f*/, 1/*i2d*/, 2/*l2i*/, 2/*l2f*/, 2/*l2d*/, 1/*f2i*/, 1/*f2l*/, + 1/*f2d*/, 2/*d2i*/, 2/*d2l*/, 2/*d2f*/, 1/*i2b*/, 1/*i2c*/, 1/*i2s*/, + 4/*lcmp*/, 2/*fcmpl*/, 2/*fcmpg*/, 4/*dcmpl*/, 4/*dcmpg*/, 1/*ifeq*/, 1/*ifne*/, + 1/*iflt*/, 1/*ifge*/, 1/*ifgt*/, 1/*ifle*/, 2/*if_icmpeq*/, 2/*if_icmpne*/, 2/*if_icmplt*/, + 2 /*if_icmpge*/, 2/*if_icmpgt*/, 2/*if_icmple*/, 2/*if_acmpeq*/, 2/*if_acmpne*/, + 0/*goto*/, 0/*jsr*/, 0/*ret*/, 1/*tableswitch*/, 1/*lookupswitch*/, 1/*ireturn*/, + 2/*lreturn*/, 1/*freturn*/, 2/*dreturn*/, 1/*areturn*/, 0/*return*/, 0/*getstatic*/, + UNPREDICTABLE/*putstatic*/, 1/*getfield*/, UNPREDICTABLE/*putfield*/, + UNPREDICTABLE/*invokevirtual*/, UNPREDICTABLE/*invokespecial*/, + UNPREDICTABLE/*invokestatic*/, + UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 0/*new*/, 1/*newarray*/, 1/*anewarray*/, + 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 1/*monitorenter*/, + 1/*monitorexit*/, 0/*wide*/, UNPREDICTABLE/*multianewarray*/, 1/*ifnull*/, 1/*ifnonnull*/, + 0/*goto_w*/, 0/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/ + }; + + /** + * Number of words produced onto operand stack by instructions. + * Indexed by opcode. CONSUME_STACK[DALOAD] = number of words + * consumed from the stack by a daload instruction. + */ + public static final int[] PRODUCE_STACK = { + 0/*nop*/, 1/*aconst_null*/, 1/*iconst_m1*/, 1/*iconst_0*/, 1/*iconst_1*/, + 1/*iconst_2*/, 1/*iconst_3*/, 1/*iconst_4*/, 1/*iconst_5*/, 2/*lconst_0*/, + 2/*lconst_1*/, 1/*fconst_0*/, 1/*fconst_1*/, 1/*fconst_2*/, 2/*dconst_0*/, + 2/*dconst_1*/, 1/*bipush*/, 1/*sipush*/, 1/*ldc*/, 1/*ldc_w*/, 2/*ldc2_w*/, 1/*iload*/, + 2/*lload*/, 1/*fload*/, 2/*dload*/, 1/*aload*/, 1/*iload_0*/, 1/*iload_1*/, 1/*iload_2*/, + 1/*iload_3*/, 2/*lload_0*/, 2/*lload_1*/, 2/*lload_2*/, 2/*lload_3*/, 1/*fload_0*/, + 1/*fload_1*/, 1/*fload_2*/, 1/*fload_3*/, 2/*dload_0*/, 2/*dload_1*/, 2/*dload_2*/, + 2/*dload_3*/, 1/*aload_0*/, 1/*aload_1*/, 1/*aload_2*/, 1/*aload_3*/, 1/*iaload*/, + 2/*laload*/, 1/*faload*/, 2/*daload*/, 1/*aaload*/, 1/*baload*/, 1/*caload*/, 1/*saload*/, + 0/*istore*/, 0/*lstore*/, 0/*fstore*/, 0/*dstore*/, 0/*astore*/, 0/*istore_0*/, + 0/*istore_1*/, 0/*istore_2*/, 0/*istore_3*/, 0/*lstore_0*/, 0/*lstore_1*/, + 0/*lstore_2*/, 0/*lstore_3*/, 0/*fstore_0*/, 0/*fstore_1*/, 0/*fstore_2*/, + 0/*fstore_3*/, 0/*dstore_0*/, 0/*dstore_1*/, 0/*dstore_2*/, 0/*dstore_3*/, + 0/*astore_0*/, 0/*astore_1*/, 0/*astore_2*/, 0/*astore_3*/, 0/*iastore*/, 0/*lastore*/, + 0/*fastore*/, 0/*dastore*/, 0/*aastore*/, 0/*bastore*/, 0/*castore*/, 0/*sastore*/, + 0/*pop*/, 0/*pop2*/, 2/*dup*/, 3/*dup_x1*/, 4/*dup_x2*/, 4/*dup2*/, 5/*dup2_x1*/, + 6/*dup2_x2*/, 2/*swap*/, 1/*iadd*/, 2/*ladd*/, 1/*fadd*/, 2/*dadd*/, 1/*isub*/, 2/*lsub*/, + 1/*fsub*/, 2/*dsub*/, 1/*imul*/, 2/*lmul*/, 1/*fmul*/, 2/*dmul*/, 1/*idiv*/, 2/*ldiv*/, + 1/*fdiv*/, 2/*ddiv*/, 1/*irem*/, 2/*lrem*/, 1/*frem*/, 2/*drem*/, 1/*ineg*/, 2/*lneg*/, + 1/*fneg*/, 2/*dneg*/, 1/*ishl*/, 2/*lshl*/, 1/*ishr*/, 2/*lshr*/, 1/*iushr*/, 2/*lushr*/, + 1/*iand*/, 2/*land*/, 1/*ior*/, 2/*lor*/, 1/*ixor*/, 2/*lxor*/, + 0/*iinc*/, 2/*i2l*/, 1/*i2f*/, 2/*i2d*/, 1/*l2i*/, 1/*l2f*/, 2/*l2d*/, 1/*f2i*/, + 2/*f2l*/, 2/*f2d*/, 1/*d2i*/, 2/*d2l*/, 1/*d2f*/, + 1/*i2b*/, 1/*i2c*/, 1/*i2s*/, 1/*lcmp*/, 1/*fcmpl*/, 1/*fcmpg*/, + 1/*dcmpl*/, 1/*dcmpg*/, 0/*ifeq*/, 0/*ifne*/, 0/*iflt*/, 0/*ifge*/, 0/*ifgt*/, 0/*ifle*/, + 0/*if_icmpeq*/, 0/*if_icmpne*/, 0/*if_icmplt*/, 0/*if_icmpge*/, 0/*if_icmpgt*/, + 0/*if_icmple*/, 0/*if_acmpeq*/, 0/*if_acmpne*/, 0/*goto*/, 1/*jsr*/, 0/*ret*/, + 0/*tableswitch*/, 0/*lookupswitch*/, 0/*ireturn*/, 0/*lreturn*/, 0/*freturn*/, + 0/*dreturn*/, 0/*areturn*/, 0/*return*/, UNPREDICTABLE/*getstatic*/, 0/*putstatic*/, + UNPREDICTABLE/*getfield*/, 0/*putfield*/, UNPREDICTABLE/*invokevirtual*/, + UNPREDICTABLE/*invokespecial*/, UNPREDICTABLE/*invokestatic*/, + UNPREDICTABLE/*invokeinterface*/, UNDEFINED, 1/*new*/, 1/*newarray*/, 1/*anewarray*/, + 1/*arraylength*/, 1/*athrow*/, 1/*checkcast*/, 1/*instanceof*/, 0/*monitorenter*/, + 0/*monitorexit*/, 0/*wide*/, 1/*multianewarray*/, 0/*ifnull*/, 0/*ifnonnull*/, + 0/*goto_w*/, 1/*jsr_w*/, 0/*breakpoint*/, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNPREDICTABLE/*impdep1*/, UNPREDICTABLE/*impdep2*/ + }; + + /** Attributes and their corresponding names. + */ + public static final byte ATTR_UNKNOWN = -1; + public static final byte ATTR_SOURCE_FILE = 0; + public static final byte ATTR_CONSTANT_VALUE = 1; + public static final byte ATTR_CODE = 2; + public static final byte ATTR_EXCEPTIONS = 3; + public static final byte ATTR_LINE_NUMBER_TABLE = 4; + public static final byte ATTR_LOCAL_VARIABLE_TABLE = 5; + public static final byte ATTR_INNER_CLASSES = 6; + public static final byte ATTR_SYNTHETIC = 7; + public static final byte ATTR_DEPRECATED = 8; + public static final byte ATTR_PMG = 9; + public static final byte ATTR_SIGNATURE = 10; + public static final byte ATTR_STACK_MAP = 11; + public static final byte ATTR_RUNTIME_VISIBLE_ANNOTATIONS = 12; + public static final byte ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS = 13; + public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = 14; + public static final byte ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS = 15; + public static final byte ATTR_ANNOTATION_DEFAULT = 16; + public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 17; + public static final byte ATTR_ENCLOSING_METHOD = 18; + public static final byte ATTR_STACK_MAP_TABLE = 19; + + public static final short KNOWN_ATTRIBUTES = 20; + + // TOFO: FIXXXXX + public static final String[] ATTRIBUTE_NAMES = { + "SourceFile", "ConstantValue", "Code", "Exceptions", + "LineNumberTable", "LocalVariableTable", + "InnerClasses", "Synthetic", "Deprecated", + "PMGClass", "Signature", "StackMap", + "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", + "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", + "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", "StackMapTable" + }; + + /** Constants used in the StackMap attribute. + */ + public static final byte ITEM_Bogus = 0; + public static final byte ITEM_Integer = 1; + public static final byte ITEM_Float = 2; + public static final byte ITEM_Double = 3; + public static final byte ITEM_Long = 4; + public static final byte ITEM_Null = 5; + public static final byte ITEM_InitObject = 6; + public static final byte ITEM_Object = 7; + public static final byte ITEM_NewObject = 8; + + public static final String[] ITEM_NAMES = { + "Bogus", "Integer", "Float", "Double", "Long", + "Null", "InitObject", "Object", "NewObject" + }; + + /** Constants used to identify StackMapEntry types. + * + * For those types which can specify a range, the + * constant names the lowest value. + */ + public static final int SAME_FRAME = 0; + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; + public static final int CHOP_FRAME = 248; + public static final int SAME_FRAME_EXTENDED = 251; + public static final int APPEND_FRAME = 252; + public static final int FULL_FRAME = 255; + + /** Constants that define the maximum value of + * those constants which store ranges. */ + + public static final int SAME_FRAME_MAX = 63; + public static final int SAME_LOCALS_1_STACK_ITEM_FRAME_MAX = 127; + public static final int CHOP_FRAME_MAX = 250; + public static final int APPEND_FRAME_MAX = 254; +} diff --git a/java/org/apache/tomcat/util/bcel/ExceptionConstants.java b/java/org/apache/tomcat/util/bcel/ExceptionConstants.java new file mode 100644 index 000000000..c39955083 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/ExceptionConstants.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel; + +/** + * Exception constants. + * + * @version $Id$ + * @author E. Haase + */ +public interface ExceptionConstants { + + /** The mother of all exceptions + */ + public static final Class THROWABLE = Throwable.class; + /** Super class of any run-time exception + */ + public static final Class RUNTIME_EXCEPTION = RuntimeException.class; + /** Super class of any linking exception (aka Linkage Error) + */ + public static final Class LINKING_EXCEPTION = LinkageError.class; + /** Linking Exceptions + */ + public static final Class CLASS_CIRCULARITY_ERROR = ClassCircularityError.class; + public static final Class CLASS_FORMAT_ERROR = ClassFormatError.class; + public static final Class EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class; + public static final Class INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class; + public static final Class ABSTRACT_METHOD_ERROR = AbstractMethodError.class; + public static final Class ILLEGAL_ACCESS_ERROR = IllegalAccessError.class; + public static final Class INSTANTIATION_ERROR = InstantiationError.class; + public static final Class NO_SUCH_FIELD_ERROR = NoSuchFieldError.class; + public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class; + public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class; + public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class; + public static final Class VERIFY_ERROR = VerifyError.class; + /* UnsupportedClassVersionError is new in JDK 1.2 */ + //public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class; + /** Run-Time Exceptions + */ + public static final Class NULL_POINTER_EXCEPTION = NullPointerException.class; + public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class; + public static final Class ARITHMETIC_EXCEPTION = ArithmeticException.class; + public static final Class NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class; + public static final Class CLASS_CAST_EXCEPTION = ClassCastException.class; + public static final Class ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class; + /** Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual + * Machine Specification + */ + public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = { + NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR, + EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR + }; // Chapter 5.1 + public static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = { + NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR + }; // Chapter 5.2 + public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below) + public static final Class[] EXCS_STRING_RESOLUTION = new Class[0]; + // Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.) + public static final Class[] EXCS_ARRAY_EXCEPTION = { + NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION + }; +} diff --git a/java/org/apache/tomcat/util/bcel/Repository.java b/java/org/apache/tomcat/util/bcel/Repository.java new file mode 100644 index 000000000..6719a36b1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/Repository.java @@ -0,0 +1,261 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel; + +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.JavaClass; +import org.apache.tomcat.util.bcel.util.ClassPath; +import org.apache.tomcat.util.bcel.util.SyntheticRepository; + +/** + * The repository maintains informations about class interdependencies, e.g., + * whether a class is a sub-class of another. Delegates actual class loading + * to SyntheticRepository with current class path by default. + * + * @see org.apache.tomcat.util.bcel.util.Repository + * @see org.apache.tomcat.util.bcel.util.SyntheticRepository + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class Repository { + + private static org.apache.tomcat.util.bcel.util.Repository _repository = SyntheticRepository.getInstance(); + + + /** @return currently used repository instance + */ + public static org.apache.tomcat.util.bcel.util.Repository getRepository() { + return _repository; + } + + + /** Set repository instance to be used for class loading + */ + public static void setRepository( org.apache.tomcat.util.bcel.util.Repository rep ) { + _repository = rep; + } + + + /** Lookup class somewhere found on your CLASSPATH, or whereever the + * repository instance looks for it. + * + * @return class object for given fully qualified class name + * @throws ClassNotFoundException if the class could not be found or + * parsed correctly + */ + public static JavaClass lookupClass( String class_name ) throws ClassNotFoundException { + return _repository.loadClass(class_name); + } + + + /** + * Try to find class source using the internal repository instance. + * @see Class + * @return JavaClass object for given runtime class + * @throws ClassNotFoundException if the class could not be found or + * parsed correctly + */ + public static JavaClass lookupClass( Class clazz ) throws ClassNotFoundException { + return _repository.loadClass(clazz); + } + + + /** + * @return class file object for given Java class by looking on the + * system class path; returns null if the class file can't be + * found + */ + public static ClassPath.ClassFile lookupClassFile( String class_name ) { + try { + ClassPath path = _repository.getClassPath(); + if (path == null) { + return null; + } + return path.getClassFile(class_name); + } catch (IOException e) { + return null; + } + } + + + /** Clear the repository. + */ + public static void clearCache() { + _repository.clear(); + } + + + /** + * Add clazz to repository if there isn't an equally named class already in there. + * + * @return old entry in repository + */ + public static JavaClass addClass( JavaClass clazz ) { + JavaClass old = _repository.findClass(clazz.getClassName()); + _repository.storeClass(clazz); + return old; + } + + + /** + * Remove class with given (fully qualified) name from repository. + */ + public static void removeClass( String clazz ) { + _repository.removeClass(_repository.findClass(clazz)); + } + + + /** + * Remove given class from repository. + */ + public static void removeClass( JavaClass clazz ) { + _repository.removeClass(clazz); + } + + + /** + * @return list of super classes of clazz in ascending order, i.e., + * Object is always the last element + * @throws ClassNotFoundException if any of the superclasses can't be found + */ + public static JavaClass[] getSuperClasses( JavaClass clazz ) throws ClassNotFoundException { + return clazz.getSuperClasses(); + } + + + /** + * @return list of super classes of clazz in ascending order, i.e., + * Object is always the last element. + * @throws ClassNotFoundException if the named class or any of its + * superclasses can't be found + */ + public static JavaClass[] getSuperClasses( String class_name ) throws ClassNotFoundException { + JavaClass jc = lookupClass(class_name); + return getSuperClasses(jc); + } + + + /** + * @return all interfaces implemented by class and its super + * classes and the interfaces that those interfaces extend, and so on. + * (Some people call this a transitive hull). + * @throws ClassNotFoundException if any of the class's + * superclasses or superinterfaces can't be found + */ + public static JavaClass[] getInterfaces( JavaClass clazz ) throws ClassNotFoundException { + return clazz.getAllInterfaces(); + } + + + /** + * @return all interfaces implemented by class and its super + * classes and the interfaces that extend those interfaces, and so on + * @throws ClassNotFoundException if the named class can't be found, + * or if any of its superclasses or superinterfaces can't be found + */ + public static JavaClass[] getInterfaces( String class_name ) throws ClassNotFoundException { + return getInterfaces(lookupClass(class_name)); + } + + + /** + * Equivalent to runtime "instanceof" operator. + * @return true, if clazz is an instance of super_class + * @throws ClassNotFoundException if any superclasses or superinterfaces + * of clazz can't be found + */ + public static boolean instanceOf( JavaClass clazz, JavaClass super_class ) + throws ClassNotFoundException { + return clazz.instanceOf(super_class); + } + + + /** + * @return true, if clazz is an instance of super_class + * @throws ClassNotFoundException if either clazz or super_class + * can't be found + */ + public static boolean instanceOf( String clazz, String super_class ) + throws ClassNotFoundException { + return instanceOf(lookupClass(clazz), lookupClass(super_class)); + } + + + /** + * @return true, if clazz is an instance of super_class + * @throws ClassNotFoundException if super_class can't be found + */ + public static boolean instanceOf( JavaClass clazz, String super_class ) + throws ClassNotFoundException { + return instanceOf(clazz, lookupClass(super_class)); + } + + + /** + * @return true, if clazz is an instance of super_class + * @throws ClassNotFoundException if clazz can't be found + */ + public static boolean instanceOf( String clazz, JavaClass super_class ) + throws ClassNotFoundException { + return instanceOf(lookupClass(clazz), super_class); + } + + + /** + * @return true, if clazz is an implementation of interface inter + * @throws ClassNotFoundException if any superclasses or superinterfaces + * of clazz can't be found + */ + public static boolean implementationOf( JavaClass clazz, JavaClass inter ) + throws ClassNotFoundException { + return clazz.implementationOf(inter); + } + + + /** + * @return true, if clazz is an implementation of interface inter + * @throws ClassNotFoundException if clazz, inter, or any superclasses + * or superinterfaces of clazz can't be found + */ + public static boolean implementationOf( String clazz, String inter ) + throws ClassNotFoundException { + return implementationOf(lookupClass(clazz), lookupClass(inter)); + } + + + /** + * @return true, if clazz is an implementation of interface inter + * @throws ClassNotFoundException if inter or any superclasses + * or superinterfaces of clazz can't be found + */ + public static boolean implementationOf( JavaClass clazz, String inter ) + throws ClassNotFoundException { + return implementationOf(clazz, lookupClass(inter)); + } + + + /** + * @return true, if clazz is an implementation of interface inter + * @throws ClassNotFoundException if clazz or any superclasses or + * superinterfaces of clazz can't be found + */ + public static boolean implementationOf( String clazz, JavaClass inter ) + throws ClassNotFoundException { + return implementationOf(lookupClass(clazz), inter); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/AccessFlags.java b/java/org/apache/tomcat/util/bcel/classfile/AccessFlags.java new file mode 100644 index 000000000..694cafedb --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/AccessFlags.java @@ -0,0 +1,238 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Super class for all objects that have modifiers like private, final, ... + * I.e. classes, fields, and methods. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class AccessFlags implements java.io.Serializable { + + protected int access_flags; + + + public AccessFlags() { + } + + + /** + * @param a inital access flags + */ + public AccessFlags(int a) { + access_flags = a; + } + + + /** + * @return Access flags of the object aka. "modifiers". + */ + public final int getAccessFlags() { + return access_flags; + } + + + /** + * @return Access flags of the object aka. "modifiers". + */ + public final int getModifiers() { + return access_flags; + } + + + /** Set access flags aka "modifiers". + * @param access_flags Access flags of the object. + */ + public final void setAccessFlags( int access_flags ) { + this.access_flags = access_flags; + } + + + /** Set access flags aka "modifiers". + * @param access_flags Access flags of the object. + */ + public final void setModifiers( int access_flags ) { + setAccessFlags(access_flags); + } + + + private final void setFlag( int flag, boolean set ) { + if ((access_flags & flag) != 0) { // Flag is set already + if (!set) { + access_flags ^= flag; + } + } else { // Flag not set + if (set) { + access_flags |= flag; + } + } + } + + + public final void isPublic( boolean flag ) { + setFlag(Constants.ACC_PUBLIC, flag); + } + + + public final boolean isPublic() { + return (access_flags & Constants.ACC_PUBLIC) != 0; + } + + + public final void isPrivate( boolean flag ) { + setFlag(Constants.ACC_PRIVATE, flag); + } + + + public final boolean isPrivate() { + return (access_flags & Constants.ACC_PRIVATE) != 0; + } + + + public final void isProtected( boolean flag ) { + setFlag(Constants.ACC_PROTECTED, flag); + } + + + public final boolean isProtected() { + return (access_flags & Constants.ACC_PROTECTED) != 0; + } + + + public final void isStatic( boolean flag ) { + setFlag(Constants.ACC_STATIC, flag); + } + + + public final boolean isStatic() { + return (access_flags & Constants.ACC_STATIC) != 0; + } + + + public final void isFinal( boolean flag ) { + setFlag(Constants.ACC_FINAL, flag); + } + + + public final boolean isFinal() { + return (access_flags & Constants.ACC_FINAL) != 0; + } + + + public final void isSynchronized( boolean flag ) { + setFlag(Constants.ACC_SYNCHRONIZED, flag); + } + + + public final boolean isSynchronized() { + return (access_flags & Constants.ACC_SYNCHRONIZED) != 0; + } + + + public final void isVolatile( boolean flag ) { + setFlag(Constants.ACC_VOLATILE, flag); + } + + + public final boolean isVolatile() { + return (access_flags & Constants.ACC_VOLATILE) != 0; + } + + + public final void isTransient( boolean flag ) { + setFlag(Constants.ACC_TRANSIENT, flag); + } + + + public final boolean isTransient() { + return (access_flags & Constants.ACC_TRANSIENT) != 0; + } + + + public final void isNative( boolean flag ) { + setFlag(Constants.ACC_NATIVE, flag); + } + + + public final boolean isNative() { + return (access_flags & Constants.ACC_NATIVE) != 0; + } + + + public final void isInterface( boolean flag ) { + setFlag(Constants.ACC_INTERFACE, flag); + } + + + public final boolean isInterface() { + return (access_flags & Constants.ACC_INTERFACE) != 0; + } + + + public final void isAbstract( boolean flag ) { + setFlag(Constants.ACC_ABSTRACT, flag); + } + + + public final boolean isAbstract() { + return (access_flags & Constants.ACC_ABSTRACT) != 0; + } + + + public final void isStrictfp( boolean flag ) { + setFlag(Constants.ACC_STRICT, flag); + } + + + public final boolean isStrictfp() { + return (access_flags & Constants.ACC_STRICT) != 0; + } + + + public final void isSynthetic( boolean flag ) { + setFlag(Constants.ACC_SYNTHETIC, flag); + } + + + public final boolean isSynthetic() { + return (access_flags & Constants.ACC_SYNTHETIC) != 0; + } + + + public final void isAnnotation( boolean flag ) { + setFlag(Constants.ACC_ANNOTATION, flag); + } + + + public final boolean isAnnotation() { + return (access_flags & Constants.ACC_ANNOTATION) != 0; + } + + + public final void isEnum( boolean flag ) { + setFlag(Constants.ACC_ENUM, flag); + } + + + public final boolean isEnum() { + return (access_flags & Constants.ACC_ENUM) != 0; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/AnnotationDefault.java b/java/org/apache/tomcat/util/bcel/classfile/AnnotationDefault.java new file mode 100644 index 000000000..b70b78734 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/AnnotationDefault.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents the default value of a annotation for a method info + * + * @version $Id: AnnotationDefault 1 2005-02-13 03:15:08Z dbrosius $ + * @author D. Brosius + * @since 5.3 + */ +public class AnnotationDefault extends Attribute +{ + ElementValue default_value; + + /** + * @param annotation_type + * the subclass type of the annotation + * @param name_index + * Index pointing to the name Code + * @param length + * Content length in bytes + * @param file + * Input stream + * @param constant_pool + * Array of constants + */ + public AnnotationDefault(int name_index, int length, + DataInputStream file, ConstantPool constant_pool) + throws IOException + { + this(name_index, length, (ElementValue) null, + constant_pool); + default_value = ElementValue.readElementValue(file, constant_pool); + } + + /** + * @param annotation_type + * the subclass type of the annotation + * @param name_index + * Index pointing to the name Code + * @param length + * Content length in bytes + * @param defaultValue + * the annotation's default value + * @param constant_pool + * Array of constants + */ + public AnnotationDefault(int name_index, int length, + ElementValue defaultValue, ConstantPool constant_pool) + { + super(Constants.ATTR_ANNOTATION_DEFAULT, name_index, length, constant_pool); + setDefaultValue(defaultValue); + } + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v + * Visitor object + */ + public void accept(Visitor v) + { + // v.visitAnnotationDefault(this); + } + + /** + * @param defaultValue + * the default value of this methodinfo's annotation + */ + public final void setDefaultValue(ElementValue defaultValue) + { + default_value = defaultValue; + } + + /** + * @return the default value + */ + public final ElementValue getDefaultValue() + { + return default_value; + } + + public Attribute copy(ConstantPool _constant_pool) + { + throw new RuntimeException("Not implemented yet!"); + } + + public final void dump(DataOutputStream dos) throws IOException + { + super.dump(dos); + default_value.dump(dos); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/AnnotationElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/AnnotationElementValue.java new file mode 100644 index 000000000..b27f45049 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/AnnotationElementValue.java @@ -0,0 +1,43 @@ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class AnnotationElementValue extends ElementValue +{ + // For annotation element values, this is the annotation + private AnnotationEntry annotationEntry; + + public AnnotationElementValue(int type, AnnotationEntry annotationEntry, + ConstantPool cpool) + { + super(type, cpool); + if (type != ANNOTATION) + throw new RuntimeException( + "Only element values of type annotation can be built with this ctor - type specified: " + type); + this.annotationEntry = annotationEntry; + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ANNOTATION == '@') + annotationEntry.dump(dos); + } + + public String stringifyValue() + { + StringBuffer sb = new StringBuffer(); + sb.append(annotationEntry.toString()); + return sb.toString(); + } + + public String toString() + { + return stringifyValue(); + } + + public AnnotationEntry getAnnotationEntry() + { + return annotationEntry; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java b/java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java new file mode 100644 index 000000000..81bd934fd --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/AnnotationEntry.java @@ -0,0 +1,152 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents one annotation in the annotation table + * + * @version $Id: AnnotationEntry + * @author D. Brosius + * @since 5.3 + */ +public class AnnotationEntry implements Node, Constants, Serializable { + + private int type_index; + private int num_element_value_pairs; + private List element_value_pairs; + private ConstantPool constant_pool; + private boolean isRuntimeVisible; + + + /** + * Construct object from file stream. + * @param file Input stream + */ + public AnnotationEntry(int type_index, ConstantPool constant_pool, boolean isRuntimeVisible) { + this.type_index = type_index; + + this.constant_pool = constant_pool; + this.isRuntimeVisible = isRuntimeVisible; + } + + public static AnnotationEntry read(DataInputStream file, ConstantPool constant_pool, boolean isRuntimeVisible) throws IOException + { + AnnotationEntry annotationEntry = new AnnotationEntry(file.readUnsignedShort(), constant_pool, isRuntimeVisible); + annotationEntry.num_element_value_pairs = (file.readUnsignedShort()); + annotationEntry.element_value_pairs = new ArrayList(); + for (int i = 0; i < annotationEntry.num_element_value_pairs; i++) { + annotationEntry.element_value_pairs.add(new ElementValuePair(file.readUnsignedShort(), ElementValue.readElementValue(file, constant_pool), constant_pool)); + } + return annotationEntry; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + // v.visitAnnotationEntry(this); + } + + + /** + * @return the annotation type name + */ + public String getAnnotationType() { + ConstantUtf8 c; + c = (ConstantUtf8) constant_pool.getConstant(type_index, CONSTANT_Utf8); + return c.getBytes(); + } + + /** + * @return the annotation type index + */ + public int getAnnotationTypeIndex() + { + return type_index; + } + + + /** + * @return the number of element value pairs in this annotation entry + */ + public final int getNumElementValuePairs() { + return num_element_value_pairs; + } + + + /** + * @return the element value pairs in this annotation entry + */ + public ElementValuePair[] getElementValuePairs() { + // TOFO return List + return (ElementValuePair[]) element_value_pairs.toArray(new ElementValuePair[element_value_pairs.size()]); + } + + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeShort(type_index); // u2 index of type name in cpool + dos.writeShort(element_value_pairs.size()); // u2 element_value pair count + for (int i = 0 ; i 0) + { + result.append("("); + for (int i = 0; i < getElementValuePairs().length; i++) + { + ElementValuePair element = getElementValuePairs()[i]; + result.append(element.toShortString()); + } + result.append(")"); + } + return result.toString(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Annotations.java b/java/org/apache/tomcat/util/bcel/classfile/Annotations.java new file mode 100644 index 000000000..214ebef6d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Annotations.java @@ -0,0 +1,127 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * base class for annotations + * + * @version $Id: Annotations + * @author D. Brosius + * @since 5.3 + */ +public abstract class Annotations extends Attribute { + + private int annotation_table_length; + private AnnotationEntry[] annotation_table; // Table of annotations + private boolean isRuntimeVisible; + + + /** + * @param annotation_type the subclass type of the annotation + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + */ + public Annotations(byte annotation_type, int name_index, int length, DataInputStream file, + ConstantPool constant_pool, boolean isRuntimeVisible) throws IOException { + this(annotation_type, name_index, length, (AnnotationEntry[]) null, constant_pool, isRuntimeVisible); + annotation_table_length = (file.readUnsignedShort()); + annotation_table = new AnnotationEntry[annotation_table_length]; + for (int i = 0; i < annotation_table_length; i++) { + annotation_table[i] = AnnotationEntry.read(file, constant_pool, isRuntimeVisible); + } + } + + + /** + * @param annotation_type the subclass type of the annotation + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param annotation_table the actual annotations + * @param constant_pool Array of constants + */ + public Annotations(byte annotation_type, int name_index, int length, + AnnotationEntry[] annotation_table, ConstantPool constant_pool , boolean isRuntimeVisible) { + super(annotation_type, name_index, length, constant_pool); + setAnnotationTable(annotation_table); + this.isRuntimeVisible = isRuntimeVisible; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitAnnotation(this); + } + + + /** + * @param annotation_table the entries to set in this annotation + */ + public final void setAnnotationTable( AnnotationEntry[] annotation_table ) { + this.annotation_table = annotation_table; + annotation_table_length = (annotation_table == null) ? 0 : annotation_table.length; + } + + + // TODO: update method names + /** + * @return the annotation entry table + */ + /* + public final AnnotationEntry[] getAnnotationTable() { + return annotation_table; + }*/ + + + /** + * returns the array of annotation entries in this annotation + */ + public AnnotationEntry[] getAnnotationEntries() { + return annotation_table; + } + + + /** + * @return the number of annotation entries in this annotation + */ + public final int getNumAnnotations() { + return annotation_table_length; + } + + public boolean isRuntimeVisible() + { + return isRuntimeVisible; + } + + protected void writeAnnotations(DataOutputStream dos) throws IOException + { + dos.writeShort(annotation_table_length); + for (int i = 0; i < annotation_table_length; i++) + annotation_table[i].dump(dos); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ArrayElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/ArrayElementValue.java new file mode 100644 index 000000000..5a3e5dbaa --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ArrayElementValue.java @@ -0,0 +1,67 @@ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class ArrayElementValue extends ElementValue +{ + // For array types, this is the array + private ElementValue[] evalues; + + public String toString() + { + StringBuffer sb = new StringBuffer(); + sb.append("{"); + for (int i = 0; i < evalues.length; i++) + { + sb.append(evalues[i].toString()); + if ((i + 1) < evalues.length) + sb.append(","); + } + sb.append("}"); + return sb.toString(); + } + + public ArrayElementValue(int type, ElementValue[] datums, ConstantPool cpool) + { + super(type, cpool); + if (type != ARRAY) + throw new RuntimeException( + "Only element values of type array can be built with this ctor - type specified: " + type); + this.evalues = datums; + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ARRAY == '[') + dos.writeShort(evalues.length); + for (int i = 0; i < evalues.length; i++) + { + evalues[i].dump(dos); + } + } + + public String stringifyValue() + { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (int i = 0; i < evalues.length; i++) + { + sb.append(evalues[i].stringifyValue()); + if ((i + 1) < evalues.length) + sb.append(","); + } + sb.append("]"); + return sb.toString(); + } + + public ElementValue[] getElementValuesArray() + { + return evalues; + } + + public int getElementValuesArraySize() + { + return evalues.length; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Attribute.java b/java/org/apache/tomcat/util/bcel/classfile/Attribute.java new file mode 100644 index 000000000..cb01223c3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Attribute.java @@ -0,0 +1,323 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; + +/** + * Abstract super class for Attribute objects. Currently the + * ConstantValue, SourceFile, Code, + * Exceptiontable, LineNumberTable, + * LocalVariableTable, InnerClasses and + * Synthetic attributes are supported. The Unknown + * attribute stands for non-standard-attributes. + * + * @version $Id$ + * @author M. Dahm + * @see ConstantValue + * @see SourceFile + * @see Code + * @see Unknown + * @see ExceptionTable + * @see LineNumberTable + * @see LocalVariableTable + * @see InnerClasses + * @see Synthetic + * @see Deprecated + * @see Signature + */ +public abstract class Attribute implements Cloneable, Node, Serializable +{ + protected int name_index; // Points to attribute name in constant pool + + protected int length; // Content length of attribute field + + protected byte tag; // Tag to distiguish subclasses + + protected ConstantPool constant_pool; + + protected Attribute(byte tag, int name_index, int length, + ConstantPool constant_pool) + { + this.tag = tag; + this.name_index = name_index; + this.length = length; + this.constant_pool = constant_pool; + } + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v + * Visitor object + */ + public abstract void accept(Visitor v); + + /** + * Dump attribute to file stream in binary format. + * + * @param file + * Output file stream + * @throws IOException + */ + public void dump(DataOutputStream file) throws IOException + { + file.writeShort(name_index); + file.writeInt(length); + } + + private static Map readers = new HashMap(); + + /** + * Add an Attribute reader capable of parsing (user-defined) attributes + * named "name". You should not add readers for the standard attributes such + * as "LineNumberTable", because those are handled internally. + * + * @param name + * the name of the attribute as stored in the class file + * @param r + * the reader object + */ + public static void addAttributeReader(String name, AttributeReader r) + { + readers.put(name, r); + } + + /** + * Remove attribute reader + * + * @param name + * the name of the attribute as stored in the class file + */ + public static void removeAttributeReader(String name) + { + readers.remove(name); + } + + /* + * Class method reads one attribute from the input data stream. This method + * must not be accessible from the outside. It is called by the Field and + * Method constructor methods. + * + * @see Field + * @see Method @param file Input stream @param constant_pool Array of + * constants @return Attribute @throws IOException @throws + * ClassFormatException + */ + public static final Attribute readAttribute(DataInputStream file, + ConstantPool constant_pool) throws IOException, + ClassFormatException + { + ConstantUtf8 c; + String name; + int name_index; + int length; + byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute + // Get class name from constant pool via `name_index' indirection + name_index = file.readUnsignedShort(); + c = (ConstantUtf8) constant_pool.getConstant(name_index, + Constants.CONSTANT_Utf8); + name = c.getBytes(); + // Length of data in bytes + length = file.readInt(); + // Compare strings to find known attribute + // System.out.println(name); + for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) + { + if (name.equals(Constants.ATTRIBUTE_NAMES[i])) + { + tag = i; // found! + break; + } + } + // Call proper constructor, depending on `tag' + switch (tag) + { + case Constants.ATTR_UNKNOWN: + AttributeReader r = (AttributeReader) readers.get(name); + if (r != null) + { + return r.createAttribute(name_index, length, file, + constant_pool); + } + return new Unknown(name_index, length, file, constant_pool); + case Constants.ATTR_CONSTANT_VALUE: + return new ConstantValue(name_index, length, file, constant_pool); + case Constants.ATTR_SOURCE_FILE: + return new SourceFile(name_index, length, file, constant_pool); + case Constants.ATTR_CODE: + return new Code(name_index, length, file, constant_pool); + case Constants.ATTR_EXCEPTIONS: + return new ExceptionTable(name_index, length, file, constant_pool); + case Constants.ATTR_LINE_NUMBER_TABLE: + return new LineNumberTable(name_index, length, file, constant_pool); + case Constants.ATTR_LOCAL_VARIABLE_TABLE: + return new LocalVariableTable(name_index, length, file, + constant_pool); + case Constants.ATTR_INNER_CLASSES: + return new InnerClasses(name_index, length, file, constant_pool); + case Constants.ATTR_SYNTHETIC: + return new Synthetic(name_index, length, file, constant_pool); + case Constants.ATTR_DEPRECATED: + return new Deprecated(name_index, length, file, constant_pool); + case Constants.ATTR_PMG: + return new PMGClass(name_index, length, file, constant_pool); + case Constants.ATTR_SIGNATURE: + return new Signature(name_index, length, file, constant_pool); + case Constants.ATTR_STACK_MAP: + return new StackMap(name_index, length, file, constant_pool); + case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: + return new RuntimeVisibleAnnotations(name_index, length, file, + constant_pool); + case Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS: + return new RuntimeInvisibleAnnotations(name_index, length, file, + constant_pool); + case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeVisibleParameterAnnotations(name_index, length, + file, constant_pool); + case Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS: + return new RuntimeInvisibleParameterAnnotations(name_index, length, + file, constant_pool); + case Constants.ATTR_ANNOTATION_DEFAULT: + return new AnnotationDefault(name_index, length, file, + constant_pool); + case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE: + return new LocalVariableTypeTable(name_index, length, file, + constant_pool); + case Constants.ATTR_ENCLOSING_METHOD: + return new EnclosingMethod(name_index, length, file, constant_pool); + case Constants.ATTR_STACK_MAP_TABLE: + return new StackMapTable(name_index, length, file, constant_pool); + default: // Never reached + throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); + } + } + + /** + * @return Name of attribute + */ + public String getName() + { + ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(name_index, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + /** + * @return Length of attribute field in bytes. + */ + public final int getLength() + { + return length; + } + + /** + * @param length + * length in bytes. + */ + public final void setLength(int length) + { + this.length = length; + } + + /** + * @param name_index + * of attribute. + */ + public final void setNameIndex(int name_index) + { + this.name_index = name_index; + } + + /** + * @return Name index in constant pool of attribute name. + */ + public final int getNameIndex() + { + return name_index; + } + + /** + * @return Tag of attribute, i.e., its type. Value may not be altered, thus + * there is no setTag() method. + */ + public final byte getTag() + { + return tag; + } + + /** + * @return Constant pool used by this object. + * @see ConstantPool + */ + public final ConstantPool getConstantPool() + { + return constant_pool; + } + + /** + * @param constant_pool + * Constant pool to be used for this object. + * @see ConstantPool + */ + public final void setConstantPool(ConstantPool constant_pool) + { + this.constant_pool = constant_pool; + } + + /** + * Use copy() if you want to have a deep copy(), i.e., with all references + * copied correctly. + * + * @return shallow copy of this attribute + */ + public Object clone() + { + Object o = null; + try + { + o = super.clone(); + } + catch (CloneNotSupportedException e) + { + e.printStackTrace(); // Never occurs + } + return o; + } + + /** + * @return deep copy of this attribute + */ + public abstract Attribute copy(ConstantPool _constant_pool); + + /** + * @return attribute name. + */ + public String toString() + { + return Constants.ATTRIBUTE_NAMES[tag]; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/AttributeReader.java b/java/org/apache/tomcat/util/bcel/classfile/AttributeReader.java new file mode 100644 index 000000000..166c31497 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/AttributeReader.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * Unknown (non-standard) attributes may be read via user-defined factory + * objects that can be registered with the Attribute.addAttributeReader + * method. These factory objects should implement this interface. + + * @see Attribute + * @version $Id$ + * @author M. Dahm + */ +public interface AttributeReader { + + /** + When this attribute reader is added via the static method + Attribute.addAttributeReader, an attribute name is associated with it. + As the class file parser parses attributes, it will call various + AttributeReaders based on the name of the attributes it is + constructing. + + @param name_index An index into the constant pool, indexing a + ConstantUtf8 that represents the name of the attribute. + + @param length The length of the data contained in the attribute. This + is written into the constant pool and should agree with what the + factory expects the length to be. + + @param file This is the data input stream that the factory needs to read + its data from. + + @param constant_pool This is the constant pool associated with the + Attribute that we are constructing. + + @return The user-defined AttributeReader should take this data and use + it to construct an attribute. In the case of errors, a null can be + returned which will cause the parsing of the class file to fail. + + @see Attribute#addAttributeReader( String, AttributeReader ) + */ + public Attribute createAttribute( int name_index, int length, java.io.DataInputStream file, + ConstantPool constant_pool ); +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ClassElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/ClassElementValue.java new file mode 100644 index 000000000..f3dad0f9e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ClassElementValue.java @@ -0,0 +1,44 @@ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +public class ClassElementValue extends ElementValue +{ + // For primitive types and string type, this points to the value entry in + // the cpool + // For 'class' this points to the class entry in the cpool + private int idx; + + public ClassElementValue(int type, int idx, ConstantPool cpool) + { + super(type, cpool); + this.idx = idx; + } + + public int getIndex() + { + return idx; + } + + public String getClassString() + { + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(idx, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + public String stringifyValue() + { + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(idx, + Constants.CONSTANT_Utf8); + return cu8.getBytes(); + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 kind of value + dos.writeShort(idx); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ClassFormatException.java b/java/org/apache/tomcat/util/bcel/classfile/ClassFormatException.java new file mode 100644 index 000000000..e3c4d97e6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ClassFormatException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * Thrown when the BCEL attempts to read a class file and determines + * that the file is malformed or otherwise cannot be interpreted as a + * class file. + * + * @version $Id$ + * @author M. Dahm + */ +public class ClassFormatException extends RuntimeException { + + public ClassFormatException() { + super(); + } + + + public ClassFormatException(String s) { + super(s); + } + + public ClassFormatException(String s, Throwable initCause) { + super(s, initCause); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ClassParser.java b/java/org/apache/tomcat/util/bcel/classfile/ClassParser.java new file mode 100644 index 000000000..e24eea482 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ClassParser.java @@ -0,0 +1,302 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Wrapper class that parses a given Java .class file. The method parse returns a + * JavaClass 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 + * JVM specification 1.0. See this paper for + * further details about the structure of a bytecode file. + * + * @version $Id$ + * @author M. Dahm + */ +public final class ClassParser { + + private DataInputStream file; + private boolean fileOwned; + private String file_name; + private String zip_file; + private int class_name_index, superclass_name_index; + private int major, minor; // Compiler version + private int access_flags; // Access rights of parsed class + private int[] interfaces; // Names of implemented interfaces + private ConstantPool constant_pool; // collection of constants + private Field[] fields; // class fields, i.e., its variables + private Method[] methods; // methods defined in the class + private Attribute[] attributes; // attributes defined in the class + private boolean is_zip; // Loaded from zip file + private static final int BUFSIZE = 8192; + + + /** + * Parse class from the given stream. + * + * @param file Input stream + * @param file_name File name + */ + public ClassParser(InputStream file, String file_name) { + this.file_name = file_name; + fileOwned = false; + String clazz = file.getClass().getName(); // Not a very clean solution ... + is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar."); + if (file instanceof DataInputStream) { + this.file = (DataInputStream) file; + } else { + this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE)); + } + } + + + /** Parse class from given .class file. + * + * @param file_name file name + */ + public ClassParser(String file_name) { + is_zip = false; + this.file_name = file_name; + fileOwned = true; + } + + + /** Parse class from given .class file in a ZIP-archive + * + * @param zip_file zip file name + * @param file_name file name + */ + public ClassParser(String zip_file, String file_name) { + is_zip = true; + fileOwned = true; + this.zip_file = zip_file; + this.file_name = file_name; + } + + + /** + * Parse the given Java class file and return an object that represents + * the contained data, i.e., constants, methods, fields and commands. + * A ClassFormatException is raised, if the file is not a valid + * .class file. (This does not include verification of the byte code as it + * is performed by the java interpreter). + * + * @return Class object representing the parsed class file + * @throws IOException + * @throws ClassFormatException + */ + public JavaClass parse() throws IOException, ClassFormatException { + ZipFile zip = null; + try { + if (fileOwned) { + if (is_zip) { + zip = new ZipFile(zip_file); + ZipEntry entry = zip.getEntry(file_name); + file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), + BUFSIZE)); + } else { + file = new DataInputStream(new BufferedInputStream(new FileInputStream( + file_name), BUFSIZE)); + } + } + /****************** Read headers ********************************/ + // Check magic tag of class file + readID(); + // Get compiler version + readVersion(); + /****************** Read constant pool and related **************/ + // Read constant pool entries + readConstantPool(); + // Get class information + readClassInfo(); + // Get interface information, i.e., implemented interfaces + readInterfaces(); + /****************** Read class fields and methods ***************/ + // Read class fields, i.e., the variables of the class + readFields(); + // Read class methods, i.e., the functions in the class + readMethods(); + // Read class attributes + readAttributes(); + // Check for unknown variables + //Unknown[] u = Unknown.getUnknownAttributes(); + //for(int i=0; i < u.length; i++) + // System.err.println("WARNING: " + u[i]); + // Everything should have been read now + // if(file.available() > 0) { + // int bytes = file.available(); + // byte[] buf = new byte[bytes]; + // file.read(buf); + // if(!(is_zip && (buf.length == 1))) { + // System.err.println("WARNING: Trailing garbage at end of " + file_name); + // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); + // } + // } + } finally { + // Read everything of interest, so close the file + if (fileOwned) { + try { + if (file != null) { + file.close(); + } + if (zip != null) { + zip.close(); + } + } catch (IOException ioe) { + //ignore close exceptions + } + } + } + // Return the information we have gathered in a new object + return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, + access_flags, constant_pool, interfaces, fields, methods, attributes, is_zip + ? JavaClass.ZIP + : JavaClass.FILE); + } + + + /** + * Read information about the attributes of the class. + * @throws IOException + * @throws ClassFormatException + */ + private final void readAttributes() throws IOException, ClassFormatException { + int attributes_count; + attributes_count = file.readUnsignedShort(); + attributes = new Attribute[attributes_count]; + for (int i = 0; i < attributes_count; i++) { + attributes[i] = Attribute.readAttribute(file, constant_pool); + } + } + + + /** + * Read information about the class and its super class. + * @throws IOException + * @throws ClassFormatException + */ + private final void readClassInfo() throws IOException, ClassFormatException { + access_flags = file.readUnsignedShort(); + /* Interfaces are implicitely abstract, the flag should be set + * according to the JVM specification. + */ + if ((access_flags & Constants.ACC_INTERFACE) != 0) { + access_flags |= Constants.ACC_ABSTRACT; + } + if (((access_flags & Constants.ACC_ABSTRACT) != 0) + && ((access_flags & Constants.ACC_FINAL) != 0)) { + throw new ClassFormatException("Class " + file_name + " can't be both final and abstract"); + } + class_name_index = file.readUnsignedShort(); + superclass_name_index = file.readUnsignedShort(); + } + + + /** + * Read constant pool entries. + * @throws IOException + * @throws ClassFormatException + */ + private final void readConstantPool() throws IOException, ClassFormatException { + constant_pool = new ConstantPool(file); + } + + + /** + * Read information about the fields of the class, i.e., its variables. + * @throws IOException + * @throws ClassFormatException + */ + private final void readFields() throws IOException, ClassFormatException { + int fields_count; + fields_count = file.readUnsignedShort(); + fields = new Field[fields_count]; + for (int i = 0; i < fields_count; i++) { + fields[i] = new Field(file, constant_pool); + } + } + + + /******************** Private utility methods **********************/ + /** + * Check whether the header of the file is ok. + * Of course, this has to be the first action on successive file reads. + * @throws IOException + * @throws ClassFormatException + */ + private final void readID() throws IOException, ClassFormatException { + int magic = 0xCAFEBABE; + if (file.readInt() != magic) { + throw new ClassFormatException(file_name + " is not a Java .class file"); + } + } + + + /** + * Read information about the interfaces implemented by this class. + * @throws IOException + * @throws ClassFormatException + */ + private final void readInterfaces() throws IOException, ClassFormatException { + int interfaces_count; + interfaces_count = file.readUnsignedShort(); + interfaces = new int[interfaces_count]; + for (int i = 0; i < interfaces_count; i++) { + interfaces[i] = file.readUnsignedShort(); + } + } + + + /** + * Read information about the methods of the class. + * @throws IOException + * @throws ClassFormatException + */ + private final void readMethods() throws IOException, ClassFormatException { + int methods_count; + methods_count = file.readUnsignedShort(); + methods = new Method[methods_count]; + for (int i = 0; i < methods_count; i++) { + methods[i] = new Method(file, constant_pool); + } + } + + + /** + * Read major and minor version of compiler which created the file. + * @throws IOException + * @throws ClassFormatException + */ + private final void readVersion() throws IOException, ClassFormatException { + minor = file.readUnsignedShort(); + major = file.readUnsignedShort(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Code.java b/java/org/apache/tomcat/util/bcel/classfile/Code.java new file mode 100644 index 000000000..af6f182b8 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Code.java @@ -0,0 +1,352 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a chunk of Java byte code contained in a + * method. It is instantiated by the + * Attribute.readAttribute() method. A Code + * attribute contains informations about operand stack, local + * variables, byte code and the exceptions handled within this + * method. + * + * This attribute has attributes itself, namely LineNumberTable which + * is used for debugging purposes and LocalVariableTable which + * contains information about the local variables. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + * @see CodeException + * @see LineNumberTable + * @see LocalVariableTable + */ +public final class Code extends Attribute { + + private int max_stack; // Maximum size of stack used by this method + private int max_locals; // Number of local variables + private int code_length; // Length of code in bytes + private byte[] code; // Actual byte code + private int exception_table_length; + private CodeException[] exception_table; // Table of handled exceptions + private int attributes_count; // Attributes of code: LineNumber + private Attribute[] attributes; // or LocalVariable + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public Code(Code c) { + this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c + .getExceptionTable(), c.getAttributes(), c.getConstantPool()); + } + + + /** + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + */ + Code(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + // Initialize with some default values which will be overwritten later + this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, + (CodeException[]) null, (Attribute[]) null, constant_pool); + code_length = file.readInt(); + code = new byte[code_length]; // Read byte code + file.readFully(code); + /* Read exception table that contains all regions where an exception + * handler is active, i.e., a try { ... } catch() block. + */ + exception_table_length = file.readUnsignedShort(); + exception_table = new CodeException[exception_table_length]; + for (int i = 0; i < exception_table_length; i++) { + exception_table[i] = new CodeException(file); + } + /* Read all attributes, currently `LineNumberTable' and + * `LocalVariableTable' + */ + attributes_count = file.readUnsignedShort(); + attributes = new Attribute[attributes_count]; + for (int i = 0; i < attributes_count; i++) { + attributes[i] = Attribute.readAttribute(file, constant_pool); + } + /* Adjust length, because of setAttributes in this(), s.b. length + * is incorrect, because it didn't take the internal attributes + * into account yet! Very subtle bug, fixed in 3.1.1. + */ + this.length = length; + } + + + /** + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param max_stack Maximum size of stack + * @param max_locals Number of local variables + * @param code Actual byte code + * @param exception_table Table of handled exceptions + * @param attributes Attributes of code: LineNumber or LocalVariable + * @param constant_pool Array of constants + */ + public Code(int name_index, int length, int max_stack, int max_locals, byte[] code, + CodeException[] exception_table, Attribute[] attributes, ConstantPool constant_pool) { + super(Constants.ATTR_CODE, name_index, length, constant_pool); + this.max_stack = max_stack; + this.max_locals = max_locals; + setCode(code); + setExceptionTable(exception_table); + setAttributes(attributes); // Overwrites length! + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitCode(this); + } + + + /** + * Dump code attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(max_stack); + file.writeShort(max_locals); + file.writeInt(code_length); + file.write(code, 0, code_length); + file.writeShort(exception_table_length); + for (int i = 0; i < exception_table_length; i++) { + exception_table[i].dump(file); + } + file.writeShort(attributes_count); + for (int i = 0; i < attributes_count; i++) { + attributes[i].dump(file); + } + } + + + /** + * @return Collection of code attributes. + * @see Attribute + */ + public final Attribute[] getAttributes() { + return attributes; + } + + + /** + * @return LineNumberTable of Code, if it has one + */ + public LineNumberTable getLineNumberTable() { + for (int i = 0; i < attributes_count; i++) { + if (attributes[i] instanceof LineNumberTable) { + return (LineNumberTable) attributes[i]; + } + } + return null; + } + + + /** + * @return LocalVariableTable of Code, if it has one + */ + public LocalVariableTable getLocalVariableTable() { + for (int i = 0; i < attributes_count; i++) { + if (attributes[i] instanceof LocalVariableTable) { + return (LocalVariableTable) attributes[i]; + } + } + return null; + } + + + /** + * @return Actual byte code of the method. + */ + public final byte[] getCode() { + return code; + } + + + /** + * @return Table of handled exceptions. + * @see CodeException + */ + public final CodeException[] getExceptionTable() { + return exception_table; + } + + + /** + * @return Number of local variables. + */ + public final int getMaxLocals() { + return max_locals; + } + + + /** + * @return Maximum size of stack used by this method. + */ + public final int getMaxStack() { + return max_stack; + } + + + /** + * @return the internal length of this code attribute (minus the first 6 bytes) + * and excluding all its attributes + */ + private final int getInternalLength() { + return 2 /*max_stack*/+ 2 /*max_locals*/+ 4 /*code length*/ + + code_length /*byte-code*/ + + 2 /*exception-table length*/ + + 8 * exception_table_length /* exception table */ + + 2 /* attributes count */; + } + + + /** + * @return the full size of this code attribute, minus its first 6 bytes, + * including the size of all its contained attributes + */ + private final int calculateLength() { + int len = 0; + for (int i = 0; i < attributes_count; i++) { + len += attributes[i].length + 6 /*attribute header size*/; + } + return len + getInternalLength(); + } + + + /** + * @param attributes the attributes to set for this Code + */ + public final void setAttributes( Attribute[] attributes ) { + this.attributes = attributes; + attributes_count = (attributes == null) ? 0 : attributes.length; + length = calculateLength(); // Adjust length + } + + + /** + * @param code byte code + */ + public final void setCode( byte[] code ) { + this.code = code; + code_length = (code == null) ? 0 : code.length; + } + + + /** + * @param exception_table exception table + */ + public final void setExceptionTable( CodeException[] exception_table ) { + this.exception_table = exception_table; + exception_table_length = (exception_table == null) ? 0 : exception_table.length; + } + + + /** + * @param max_locals maximum number of local variables + */ + public final void setMaxLocals( int max_locals ) { + this.max_locals = max_locals; + } + + + /** + * @param max_stack maximum stack size + */ + public final void setMaxStack( int max_stack ) { + this.max_stack = max_stack; + } + + + /** + * @return String representation of code chunk. + */ + public final String toString( boolean verbose ) { + StringBuffer buf; + buf = new StringBuffer(100); + buf.append("Code(max_stack = ").append(max_stack).append(", max_locals = ").append( + max_locals).append(", code_length = ").append(code_length).append(")\n").append( + Utility.codeToString(code, constant_pool, 0, -1, verbose)); + if (exception_table_length > 0) { + buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n"); + for (int i = 0; i < exception_table_length; i++) { + buf.append(exception_table[i].toString(constant_pool, verbose)).append("\n"); + } + } + if (attributes_count > 0) { + buf.append("\nAttribute(s) = \n"); + for (int i = 0; i < attributes_count; i++) { + buf.append(attributes[i].toString()).append("\n"); + } + } + return buf.toString(); + } + + + /** + * @return String representation of code chunk. + */ + public final String toString() { + return toString(true); + } + + + /** + * @return deep copy of this attribute + * + * @param _constant_pool the constant pool to duplicate + */ + public Attribute copy( ConstantPool _constant_pool ) { + Code c = (Code) clone(); + if (code != null) { + c.code = new byte[code.length]; + System.arraycopy(code, 0, c.code, 0, code.length); + } + c.constant_pool = _constant_pool; + c.exception_table = new CodeException[exception_table_length]; + for (int i = 0; i < exception_table_length; i++) { + c.exception_table[i] = exception_table[i].copy(); + } + c.attributes = new Attribute[attributes_count]; + for (int i = 0; i < attributes_count; i++) { + c.attributes[i] = attributes[i].copy(_constant_pool); + } + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/CodeException.java b/java/org/apache/tomcat/util/bcel/classfile/CodeException.java new file mode 100644 index 000000000..816f9f66b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/CodeException.java @@ -0,0 +1,215 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents an entry in the exception table of the Code + * attribute and is used only there. It contains a range in which a + * particular exception handler is active. + * + * @version $Id$ + * @author M. Dahm + * @see Code + */ +public final class CodeException implements Cloneable, Constants, Node, Serializable { + + private int start_pc; // Range in the code the exception handler is + private int end_pc; // active. start_pc is inclusive, end_pc exclusive + private int handler_pc; /* Starting address of exception handler, i.e., + * an offset from start of code. + */ + private int catch_type; /* If this is zero the handler catches any + * exception, otherwise it points to the + * exception class which is to be caught. + */ + + + /** + * Initialize from another object. + */ + public CodeException(CodeException c) { + this(c.getStartPC(), c.getEndPC(), c.getHandlerPC(), c.getCatchType()); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + CodeException(DataInput file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file + .readUnsignedShort()); + } + + + /** + * @param start_pc Range in the code the exception handler is active, + * start_pc is inclusive while + * @param end_pc is exclusive + * @param handler_pc Starting address of exception handler, i.e., + * an offset from start of code. + * @param catch_type If zero the handler catches any + * exception, otherwise it points to the exception class which is + * to be caught. + */ + public CodeException(int start_pc, int end_pc, int handler_pc, int catch_type) { + this.start_pc = start_pc; + this.end_pc = end_pc; + this.handler_pc = handler_pc; + this.catch_type = catch_type; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitCodeException(this); + } + + + /** + * Dump code exception to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(start_pc); + file.writeShort(end_pc); + file.writeShort(handler_pc); + file.writeShort(catch_type); + } + + + /** + * @return 0, if the handler catches any exception, otherwise it points to + * the exception class which is to be caught. + */ + public final int getCatchType() { + return catch_type; + } + + + /** + * @return Exclusive end index of the region where the handler is active. + */ + public final int getEndPC() { + return end_pc; + } + + + /** + * @return Starting address of exception handler, relative to the code. + */ + public final int getHandlerPC() { + return handler_pc; + } + + + /** + * @return Inclusive start index of the region where the handler is active. + */ + public final int getStartPC() { + return start_pc; + } + + + /** + * @param catch_type the type of exception that is caught + */ + public final void setCatchType( int catch_type ) { + this.catch_type = catch_type; + } + + + /** + * @param end_pc end of handled block + */ + public final void setEndPC( int end_pc ) { + this.end_pc = end_pc; + } + + + /** + * @param handler_pc where the actual code is + */ + public final void setHandlerPC( int handler_pc ) { + this.handler_pc = handler_pc; + } + + + /** + * @param start_pc start of handled block + */ + public final void setStartPC( int start_pc ) { + this.start_pc = start_pc; + } + + + /** + * @return String representation. + */ + public final String toString() { + return "CodeException(start_pc = " + start_pc + ", end_pc = " + end_pc + ", handler_pc = " + + handler_pc + ", catch_type = " + catch_type + ")"; + } + + + /** + * @return String representation. + */ + public final String toString( ConstantPool cp, boolean verbose ) { + String str; + if (catch_type == 0) { + str = "(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/java/org/apache/tomcat/util/bcel/classfile/Constant.java b/java/org/apache/tomcat/util/bcel/classfile/Constant.java new file mode 100644 index 000000000..8cbedaab4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Constant.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * Abstract superclass for classes to represent the different constant types + * in the constant pool of a class file. The classes keep closely to + * the JVM specification. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class Constant implements Cloneable, Node, Serializable { + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + Constant THIS = (Constant) o1; + Constant THAT = (Constant) o2; + return THIS.toString().equals(THAT.toString()); + } + + + public int hashCode( Object o ) { + Constant THIS = (Constant) o; + return THIS.toString().hashCode(); + } + }; + /* In fact this tag is redundant since we can distinguish different + * `Constant' objects by their type, i.e., via `instanceof'. In some + * places we will use the tag for switch()es anyway. + * + * First, we want match the specification as closely as possible. Second we + * need the tag as an index to select the corresponding class name from the + * `CONSTANT_NAMES' array. + */ + protected byte tag; + + + Constant(byte tag) { + this.tag = tag; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public abstract void accept( Visitor v ); + + + public abstract void dump( DataOutputStream file ) throws IOException; + + + /** + * @return Tag of constant, i.e., its type. No setTag() method to avoid + * confusion. + */ + public final byte getTag() { + return tag; + } + + + /** + * @return String representation. + */ + public String toString() { + return Constants.CONSTANT_NAMES[tag] + "[" + tag + "]"; + } + + + /** + * @return deep copy of this constant + */ + public Constant copy() { + try { + return (Constant) super.clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } + + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + + /** + * Read one constant from the given file, the type depends on a tag byte. + * + * @param file Input stream + * @return Constant object + */ + static final Constant readConstant( DataInputStream file ) throws IOException, + ClassFormatException { + byte b = file.readByte(); // Read tag byte + switch (b) { + case Constants.CONSTANT_Class: + return new ConstantClass(file); + case Constants.CONSTANT_Fieldref: + return new ConstantFieldref(file); + case Constants.CONSTANT_Methodref: + return new ConstantMethodref(file); + case Constants.CONSTANT_InterfaceMethodref: + return new ConstantInterfaceMethodref(file); + case Constants.CONSTANT_String: + return new ConstantString(file); + case Constants.CONSTANT_Integer: + return new ConstantInteger(file); + case Constants.CONSTANT_Float: + return new ConstantFloat(file); + case Constants.CONSTANT_Long: + return new ConstantLong(file); + case Constants.CONSTANT_Double: + return new ConstantDouble(file); + case Constants.CONSTANT_NameAndType: + return new ConstantNameAndType(file); + case Constants.CONSTANT_Utf8: + return new ConstantUtf8(file); + default: + throw new ClassFormatException("Invalid byte tag in constant pool: " + b); + } + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two Constant objects are said to be equal when + * the result of toString() is equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the result of toString(). + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantCP.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantCP.java new file mode 100644 index 000000000..907ed71b2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantCP.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Abstract super class for Fieldref and Methodref constants. + * + * @version $Id$ + * @author M. Dahm + * @see ConstantFieldref + * @see ConstantMethodref + * @see ConstantInterfaceMethodref + */ +public abstract class ConstantCP extends Constant { + + /** References to the constants containing the class and the field signature + */ + protected int class_index, name_and_type_index; + + + /** + * Initialize from another object. + */ + public ConstantCP(ConstantCP c) { + this(c.getTag(), c.getClassIndex(), c.getNameAndTypeIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param tag Constant type tag + * @param file Input stream + * @throws IOException + */ + ConstantCP(byte tag, DataInput file) throws IOException { + this(tag, file.readUnsignedShort(), file.readUnsignedShort()); + } + + + /** + * @param class_index Reference to the class containing the field + * @param name_and_type_index and the field signature + */ + protected ConstantCP(byte tag, int class_index, int name_and_type_index) { + super(tag); + this.class_index = class_index; + this.name_and_type_index = name_and_type_index; + } + + + /** + * Dump constant field reference to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeShort(class_index); + file.writeShort(name_and_type_index); + } + + + /** + * @return Reference (index) to class this field or method belongs to. + */ + public final int getClassIndex() { + return class_index; + } + + + /** + * @return Reference (index) to signature of the field. + */ + public final int getNameAndTypeIndex() { + return name_and_type_index; + } + + + /** + * @param class_index points to Constant_class + */ + public final void setClassIndex( int class_index ) { + this.class_index = class_index; + } + + + /** + * @return Class this field belongs to. + */ + public String getClass( ConstantPool cp ) { + return cp.constantToString(class_index, Constants.CONSTANT_Class); + } + + + /** + * @param name_and_type_index points to Constant_NameAndType + */ + public final void setNameAndTypeIndex( int name_and_type_index ) { + this.name_and_type_index = name_and_type_index; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(class_index = " + class_index + ", name_and_type_index = " + + name_and_type_index + ")"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java new file mode 100644 index 000000000..45bd8a6f5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantClass.java @@ -0,0 +1,129 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a (external) class. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantClass extends Constant implements ConstantObject { + + private int name_index; // Identical to ConstantString except for the name + + + /** + * Initialize from another object. + */ + public ConstantClass(ConstantClass c) { + this(c.getNameIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantClass(DataInput file) throws IOException { + this(file.readUnsignedShort()); + } + + + /** + * @param name_index Name index in constant pool. Should refer to a + * ConstantUtf8. + */ + public ConstantClass(int name_index) { + super(Constants.CONSTANT_Class); + this.name_index = name_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantClass(this); + } + + + /** + * Dump constant class to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeShort(name_index); + } + + + /** + * @return Name index in constant pool of class name. + */ + public final int getNameIndex() { + return name_index; + } + + + /** + * @param name_index the name index in the constant pool of this Constant Class + */ + public final void setNameIndex( int name_index ) { + this.name_index = name_index; + } + + + /** @return String object + */ + public Object getConstantValue( ConstantPool cp ) { + Constant c = cp.getConstant(name_index, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getBytes(); + } + + + /** @return dereferenced string + */ + public String getBytes( ConstantPool cp ) { + return (String) getConstantValue(cp); + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(name_index = " + name_index + ")"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java new file mode 100644 index 000000000..d0b0e9c84 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantDouble.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a Double object. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantDouble extends Constant implements ConstantObject { + + private double bytes; + + + /** + * @param bytes Data + */ + public ConstantDouble(double bytes) { + super(Constants.CONSTANT_Double); + this.bytes = bytes; + } + + + /** + * Initialize from another object. + */ + public ConstantDouble(ConstantDouble c) { + this(c.getBytes()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantDouble(DataInput file) throws IOException { + this(file.readDouble()); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantDouble(this); + } + + + /** + * Dump constant double to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeDouble(bytes); + } + + + /** + * @return data, i.e., 8 bytes. + */ + public final double getBytes() { + return bytes; + } + + + /** + * @param bytes the raw bytes that represent the double value + */ + public final void setBytes( double bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(bytes = " + bytes + ")"; + } + + + /** @return Double object + */ + public Object getConstantValue( ConstantPool cp ) { + return new Double(bytes); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantFieldref.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantFieldref.java new file mode 100644 index 000000000..b294ced43 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantFieldref.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a constant pool reference to a field. + * + * @version $Id$ + * @author M. Dahm + */ +public final class ConstantFieldref extends ConstantCP { + + /** + * Initialize from another object. + */ + public ConstantFieldref(ConstantFieldref c) { + super(Constants.CONSTANT_Fieldref, c.getClassIndex(), c.getNameAndTypeIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file input stream + * @throws IOException + */ + ConstantFieldref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Fieldref, file); + } + + + /** + * @param class_index Reference to the class containing the Field + * @param name_and_type_index and the Field signature + */ + public ConstantFieldref(int class_index, int name_and_type_index) { + super(Constants.CONSTANT_Fieldref, class_index, name_and_type_index); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of Fields, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantFieldref(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java new file mode 100644 index 000000000..8551914d4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantFloat.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a float object. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantFloat extends Constant implements ConstantObject { + + private float bytes; + + + /** + * @param bytes Data + */ + public ConstantFloat(float bytes) { + super(Constants.CONSTANT_Float); + this.bytes = bytes; + } + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public ConstantFloat(ConstantFloat c) { + this(c.getBytes()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantFloat(DataInput file) throws IOException { + this(file.readFloat()); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantFloat(this); + } + + + /** + * Dump constant float to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeFloat(bytes); + } + + + /** + * @return data, i.e., 4 bytes. + */ + public final float getBytes() { + return bytes; + } + + + /** + * @param bytes the raw bytes that represent this float + */ + public final void setBytes( float bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(bytes = " + bytes + ")"; + } + + + /** @return Float object + */ + public Object getConstantValue( ConstantPool cp ) { + return new Float(bytes); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java new file mode 100644 index 000000000..d862c0442 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantInteger.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to an int object. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantInteger extends Constant implements ConstantObject { + + private int bytes; + + + /** + * @param bytes Data + */ + public ConstantInteger(int bytes) { + super(Constants.CONSTANT_Integer); + this.bytes = bytes; + } + + + /** + * Initialize from another object. + */ + public ConstantInteger(ConstantInteger c) { + this(c.getBytes()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantInteger(DataInput file) throws IOException { + this(file.readInt()); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantInteger(this); + } + + + /** + * Dump constant integer to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeInt(bytes); + } + + + /** + * @return data, i.e., 4 bytes. + */ + public final int getBytes() { + return bytes; + } + + + /** + * @param bytes the raw bytes that represent this integer + */ + public final void setBytes( int bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(bytes = " + bytes + ")"; + } + + + /** @return Integer object + */ + public Object getConstantValue( ConstantPool cp ) { + return new Integer(bytes); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantInterfaceMethodref.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantInterfaceMethodref.java new file mode 100644 index 000000000..41da17b72 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantInterfaceMethodref.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a constant pool reference to an interface method. + * + * @version $Id$ + * @author M. Dahm + */ +public final class ConstantInterfaceMethodref extends ConstantCP { + + /** + * Initialize from another object. + */ + public ConstantInterfaceMethodref(ConstantInterfaceMethodref c) { + super(Constants.CONSTANT_InterfaceMethodref, c.getClassIndex(), c.getNameAndTypeIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file input stream + * @throws IOException + */ + ConstantInterfaceMethodref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_InterfaceMethodref, file); + } + + + /** + * @param class_index Reference to the class containing the method + * @param name_and_type_index and the method signature + */ + public ConstantInterfaceMethodref(int class_index, int name_and_type_index) { + super(Constants.CONSTANT_InterfaceMethodref, class_index, name_and_type_index); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantInterfaceMethodref(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java new file mode 100644 index 000000000..d8837e8f7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantLong.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a long object. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantLong extends Constant implements ConstantObject { + + private long bytes; + + + /** + * @param bytes Data + */ + public ConstantLong(long bytes) { + super(Constants.CONSTANT_Long); + this.bytes = bytes; + } + + + /** + * Initialize from another object. + */ + public ConstantLong(ConstantLong c) { + this(c.getBytes()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantLong(DataInput file) throws IOException { + this(file.readLong()); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantLong(this); + } + + + /** + * Dump constant long to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeLong(bytes); + } + + + /** + * @return data, i.e., 8 bytes. + */ + public final long getBytes() { + return bytes; + } + + + /** + * @param bytes thr raw bytes that represent this long + */ + public final void setBytes( long bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(bytes = " + bytes + ")"; + } + + + /** @return Long object + */ + public Object getConstantValue( ConstantPool cp ) { + return new Long(bytes); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantMethodref.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantMethodref.java new file mode 100644 index 000000000..c40f0aa09 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantMethodref.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a constant pool reference to a method. + * + * @version $Id$ + * @author M. Dahm + */ +public final class ConstantMethodref extends ConstantCP { + + /** + * Initialize from another object. + */ + public ConstantMethodref(ConstantMethodref c) { + super(Constants.CONSTANT_Methodref, c.getClassIndex(), c.getNameAndTypeIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file input stream + * @throws IOException + */ + ConstantMethodref(DataInputStream file) throws IOException { + super(Constants.CONSTANT_Methodref, file); + } + + + /** + * @param class_index Reference to the class containing the method + * @param name_and_type_index and the method signature + */ + public ConstantMethodref(int class_index, int name_and_type_index) { + super(Constants.CONSTANT_Methodref, class_index, name_and_type_index); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantMethodref(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantNameAndType.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantNameAndType.java new file mode 100644 index 000000000..00e46c26c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantNameAndType.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to the name and signature + * of a field or method. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantNameAndType extends Constant { + + private int name_index; // Name of field/method + private int signature_index; // and its signature. + + + /** + * Initialize from another object. + */ + public ConstantNameAndType(ConstantNameAndType c) { + this(c.getNameIndex(), c.getSignatureIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantNameAndType(DataInput file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort()); + } + + + /** + * @param name_index Name of field/method + * @param signature_index and its signature + */ + public ConstantNameAndType(int name_index, int signature_index) { + super(Constants.CONSTANT_NameAndType); + this.name_index = name_index; + this.signature_index = signature_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantNameAndType(this); + } + + + /** + * Dump name and signature index to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeShort(name_index); + file.writeShort(signature_index); + } + + + /** + * @return Name index in constant pool of field/method name. + */ + public final int getNameIndex() { + return name_index; + } + + + /** @return name + */ + public final String getName( ConstantPool cp ) { + return cp.constantToString(getNameIndex(), Constants.CONSTANT_Utf8); + } + + + /** + * @return Index in constant pool of field/method signature. + */ + public final int getSignatureIndex() { + return signature_index; + } + + + /** @return signature + */ + public final String getSignature( ConstantPool cp ) { + return cp.constantToString(getSignatureIndex(), Constants.CONSTANT_Utf8); + } + + + /** + * @param name_index the name index of this constant + */ + public final void setNameIndex( int name_index ) { + this.name_index = name_index; + } + + + /** + * @param signature_index the signature index in the constant pool of this type + */ + public final void setSignatureIndex( int signature_index ) { + this.signature_index = signature_index; + } + + + /** + * @return String representation + */ + public final String toString() { + return super.toString() + "(name_index = " + name_index + ", signature_index = " + + signature_index + ")"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantObject.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantObject.java new file mode 100644 index 000000000..3d343940f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantObject.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * This interface denotes those constants that have a "natural" value, + * such as ConstantLong, ConstantString, etc.. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public interface ConstantObject { + + /** @return object representing the constant, e.g., Long for ConstantLong + */ + public abstract Object getConstantValue( ConstantPool cp ); +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantPool.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantPool.java new file mode 100644 index 000000000..612d3457e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantPool.java @@ -0,0 +1,353 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents the constant pool, i.e., a table of constants, of + * a parsed classfile. It may contain null references, due to the JVM + * specification that skips an entry after an 8-byte constant (double, + * long) entry. Those interested in generating constant pools + * programatically should see + * ConstantPoolGen. + + * @version $Id$ + * @see Constant + * @see org.apache.tomcat.util.bcel.generic.ConstantPoolGen + * @author M. Dahm + */ +public class ConstantPool implements Cloneable, Node, Serializable { + + private int constant_pool_count; + private Constant[] constant_pool; + + + /** + * @param constant_pool Array of constants + */ + public ConstantPool(Constant[] constant_pool) { + setConstantPool(constant_pool); + } + + + /** + * Read constants from given file stream. + * + * @param file Input stream + * @throws IOException + * @throws ClassFormatException + */ + ConstantPool(DataInputStream file) throws IOException, ClassFormatException { + byte tag; + constant_pool_count = file.readUnsignedShort(); + constant_pool = new Constant[constant_pool_count]; + /* constant_pool[0] is unused by the compiler and may be used freely + * by the implementation. + */ + for (int i = 1; i < constant_pool_count; i++) { + constant_pool[i] = Constant.readConstant(file); + /* Quote from the JVM specification: + * "All eight byte constants take up two spots in the constant pool. + * If this is the n'th byte in the constant pool, then the next item + * will be numbered n+2" + * + * Thus we have to increment the index counter. + */ + tag = constant_pool[i].getTag(); + if ((tag == Constants.CONSTANT_Double) || (tag == Constants.CONSTANT_Long)) { + i++; + } + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantPool(this); + } + + + /** + * Resolve constant to a string representation. + * + * @param c Constant to be printed + * @return String representation + */ + public String constantToString( Constant c ) throws ClassFormatException { + String str; + int i; + byte tag = c.getTag(); + switch (tag) { + case Constants.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false); + break; + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = getConstant(i, Constants.CONSTANT_Utf8); + str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\""; + break; + case Constants.CONSTANT_Utf8: + str = ((ConstantUtf8) c).getBytes(); + break; + case Constants.CONSTANT_Double: + str = String.valueOf(((ConstantDouble) c).getBytes()); + break; + case Constants.CONSTANT_Float: + str = String.valueOf(((ConstantFloat) c).getBytes()); + break; + case Constants.CONSTANT_Long: + str = String.valueOf(((ConstantLong) c).getBytes()); + break; + case Constants.CONSTANT_Integer: + str = String.valueOf(((ConstantInteger) c).getBytes()); + break; + case Constants.CONSTANT_NameAndType: + str = (constantToString(((ConstantNameAndType) c).getNameIndex(), + Constants.CONSTANT_Utf8) + + " " + constantToString(((ConstantNameAndType) c).getSignatureIndex(), + Constants.CONSTANT_Utf8)); + break; + case Constants.CONSTANT_InterfaceMethodref: + case Constants.CONSTANT_Methodref: + case Constants.CONSTANT_Fieldref: + str = (constantToString(((ConstantCP) c).getClassIndex(), Constants.CONSTANT_Class) + + "." + constantToString(((ConstantCP) c).getNameAndTypeIndex(), + Constants.CONSTANT_NameAndType)); + break; + default: // Never reached + throw new RuntimeException("Unknown constant type " + tag); + } + return str; + } + + + private static final String escape( String str ) { + int len = str.length(); + StringBuffer buf = new StringBuffer(len + 5); + char[] ch = str.toCharArray(); + for (int i = 0; i < len; i++) { + switch (ch[i]) { + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\t': + buf.append("\\t"); + break; + case '\b': + buf.append("\\b"); + break; + case '"': + buf.append("\\\""); + break; + default: + buf.append(ch[i]); + } + } + return buf.toString(); + } + + + /** + * Retrieve constant at `index' from constant pool and resolve it to + * a string representation. + * + * @param index of constant in constant pool + * @param tag expected type + * @return String representation + */ + public String constantToString( int index, byte tag ) throws ClassFormatException { + Constant c = getConstant(index, tag); + return constantToString(c); + } + + + /** + * Dump constant pool to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public void dump( DataOutputStream file ) throws IOException { + file.writeShort(constant_pool_count); + for (int i = 1; i < constant_pool_count; i++) { + if (constant_pool[i] != null) { + constant_pool[i].dump(file); + } + } + } + + + /** + * Get constant from constant pool. + * + * @param index Index in constant pool + * @return Constant value + * @see Constant + */ + public Constant getConstant( int index ) { + if (index >= constant_pool.length || index < 0) { + throw new ClassFormatException("Invalid constant pool reference: " + index + + ". Constant pool size is: " + constant_pool.length); + } + return constant_pool[index]; + } + + + /** + * Get constant from constant pool and check whether it has the + * expected type. + * + * @param index Index in constant pool + * @param tag Tag of expected constant, i.e., its type + * @return Constant value + * @see Constant + * @throws ClassFormatException + */ + public Constant getConstant( int index, byte tag ) throws ClassFormatException { + Constant c; + c = getConstant(index); + if (c == null) { + throw new ClassFormatException("Constant pool at index " + index + " is null."); + } + if (c.getTag() != tag) { + throw new ClassFormatException("Expected class `" + Constants.CONSTANT_NAMES[tag] + + "' at index " + index + " and got " + c); + } + return c; + } + + + /** + * @return Array of constants. + * @see Constant + */ + public Constant[] getConstantPool() { + return constant_pool; + } + + + /** + * Get string from constant pool and bypass the indirection of + * `ConstantClass' and `ConstantString' objects. I.e. these classes have + * an index field that points to another entry of the constant pool of + * type `ConstantUtf8' which contains the real data. + * + * @param index Index in constant pool + * @param tag Tag of expected constant, either ConstantClass or ConstantString + * @return Contents of string reference + * @see ConstantClass + * @see ConstantString + * @throws ClassFormatException + */ + public String getConstantString( int index, byte tag ) throws ClassFormatException { + Constant c; + int i; + c = getConstant(index, tag); + /* This switch() is not that elegant, since the two classes have the + * same contents, they just differ in the name of the index + * field variable. + * But we want to stick to the JVM naming conventions closely though + * we could have solved these more elegantly by using the same + * variable name or by subclassing. + */ + switch (tag) { + case Constants.CONSTANT_Class: + i = ((ConstantClass) c).getNameIndex(); + break; + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + break; + default: + throw new RuntimeException("getConstantString called with illegal tag " + tag); + } + // Finally get the string from the constant pool + c = getConstant(i, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getBytes(); + } + + + /** + * @return Length of constant pool. + */ + public int getLength() { + return constant_pool_count; + } + + + /** + * @param constant Constant to set + */ + public void setConstant( int index, Constant constant ) { + constant_pool[index] = constant; + } + + + /** + * @param constant_pool + */ + public void setConstantPool( Constant[] constant_pool ) { + this.constant_pool = constant_pool; + constant_pool_count = (constant_pool == null) ? 0 : constant_pool.length; + } + + + /** + * @return String representation. + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 1; i < constant_pool_count; i++) { + buf.append(i).append(")").append(constant_pool[i]).append("\n"); + } + return buf.toString(); + } + + + /** + * @return deep copy of this constant pool + */ + public ConstantPool copy() { + ConstantPool c = null; + try { + c = (ConstantPool) clone(); + c.constant_pool = new Constant[constant_pool_count]; + for (int i = 1; i < constant_pool_count; i++) { + if (constant_pool[i] != null) { + c.constant_pool[i] = constant_pool[i].copy(); + } + } + } catch (CloneNotSupportedException e) { + } + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantString.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantString.java new file mode 100644 index 000000000..d063a10c9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantString.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a String object. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantString extends Constant implements ConstantObject { + + private int string_index; // Identical to ConstantClass except for this name + + + /** + * Initialize from another object. + */ + public ConstantString(ConstantString c) { + this(c.getStringIndex()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantString(DataInput file) throws IOException { + this(file.readUnsignedShort()); + } + + + /** + * @param string_index Index of Constant_Utf8 in constant pool + */ + public ConstantString(int string_index) { + super(Constants.CONSTANT_String); + this.string_index = string_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantString(this); + } + + + /** + * Dump constant field reference to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeShort(string_index); + } + + + /** + * @return Index in constant pool of the string (ConstantUtf8). + */ + public final int getStringIndex() { + return string_index; + } + + + /** + * @param string_index the index into the constant of the string value + */ + public final void setStringIndex( int string_index ) { + this.string_index = string_index; + } + + + /** + * @return String representation. + */ + public final String toString() { + return super.toString() + "(string_index = " + string_index + ")"; + } + + + /** @return String object + */ + public Object getConstantValue( ConstantPool cp ) { + Constant c = cp.getConstant(string_index, Constants.CONSTANT_Utf8); + return ((ConstantUtf8) c).getBytes(); + } + + + /** @return dereferenced string + */ + public String getBytes( ConstantPool cp ) { + return (String) getConstantValue(cp); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantUtf8.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantUtf8.java new file mode 100644 index 000000000..ea7b1050a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantUtf8.java @@ -0,0 +1,117 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from the abstract + * Constant class + * and represents a reference to a Utf8 encoded string. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public final class ConstantUtf8 extends Constant { + + private String bytes; + + + /** + * Initialize from another object. + */ + public ConstantUtf8(ConstantUtf8 c) { + this(c.getBytes()); + } + + + /** + * Initialize instance from file data. + * + * @param file Input stream + * @throws IOException + */ + ConstantUtf8(DataInput file) throws IOException { + super(Constants.CONSTANT_Utf8); + bytes = file.readUTF(); + } + + + /** + * @param bytes Data + */ + public ConstantUtf8(String bytes) { + super(Constants.CONSTANT_Utf8); + if (bytes == null) { + throw new IllegalArgumentException("bytes must not be null!"); + } + this.bytes = bytes; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantUtf8(this); + } + + + /** + * Dump String in Utf8 format to file stream. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(tag); + file.writeUTF(bytes); + } + + + /** + * @return Data converted to string. + */ + public final String getBytes() { + return bytes; + } + + + /** + * @param bytes the raw bytes of this Utf-8 + */ + public final void setBytes( String bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation + */ + public final String toString() { + return super.toString() + "(\"" + Utility.replace(bytes, "\n", "\\n") + "\")"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ConstantValue.java b/java/org/apache/tomcat/util/bcel/classfile/ConstantValue.java new file mode 100644 index 000000000..7b488b07b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ConstantValue.java @@ -0,0 +1,156 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute and represents a constant + * value, i.e., a default value for initializing a class field. + * This class is instantiated by the Attribute.readAttribute() method. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class ConstantValue extends Attribute { + + private int constantvalue_index; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public ConstantValue(ConstantValue c) { + this(c.getNameIndex(), c.getLength(), c.getConstantValueIndex(), c.getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param name_index Name index in constant pool + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + ConstantValue(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, file.readUnsignedShort(), constant_pool); + } + + + /** + * @param name_index Name index in constant pool + * @param length Content length in bytes + * @param constantvalue_index Index in constant pool + * @param constant_pool Array of constants + */ + public ConstantValue(int name_index, int length, int constantvalue_index, + ConstantPool constant_pool) { + super(Constants.ATTR_CONSTANT_VALUE, name_index, length, constant_pool); + this.constantvalue_index = constantvalue_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitConstantValue(this); + } + + + /** + * Dump constant value attribute to file stream on binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(constantvalue_index); + } + + + /** + * @return Index in constant pool of constant value. + */ + public final int getConstantValueIndex() { + return constantvalue_index; + } + + + /** + * @param constantvalue_index the index info the constant pool of this constant value + */ + public final void setConstantValueIndex( int constantvalue_index ) { + this.constantvalue_index = constantvalue_index; + } + + + /** + * @return String representation of constant value. + */ + public final String toString() { + Constant c = constant_pool.getConstant(constantvalue_index); + String buf; + int i; + // Print constant to string depending on its type + switch (c.getTag()) { + case Constants.CONSTANT_Long: + buf = String.valueOf(((ConstantLong) c).getBytes()); + break; + case Constants.CONSTANT_Float: + buf = String.valueOf(((ConstantFloat) c).getBytes()); + break; + case Constants.CONSTANT_Double: + buf = String.valueOf(((ConstantDouble) c).getBytes()); + break; + case Constants.CONSTANT_Integer: + buf = String.valueOf(((ConstantInteger) c).getBytes()); + break; + case Constants.CONSTANT_String: + i = ((ConstantString) c).getStringIndex(); + c = constant_pool.getConstant(i, Constants.CONSTANT_Utf8); + buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\""; + break; + default: + throw new IllegalStateException("Type of ConstValue invalid: " + c); + } + return buf; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + ConstantValue c = (ConstantValue) clone(); + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Deprecated.java b/java/org/apache/tomcat/util/bcel/classfile/Deprecated.java new file mode 100644 index 000000000..47833aec4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Deprecated.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute and denotes that this is a + * deprecated method. + * It is instantiated from the Attribute.readAttribute() method. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class Deprecated extends Attribute { + + private byte[] bytes; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public Deprecated(Deprecated c) { + this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param bytes Attribute contents + * @param constant_pool Array of constants + */ + public Deprecated(int name_index, int length, byte[] bytes, ConstantPool constant_pool) { + super(Constants.ATTR_DEPRECATED, name_index, length, constant_pool); + this.bytes = bytes; + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + Deprecated(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (byte[]) null, constant_pool); + if (length > 0) { + bytes = new byte[length]; + file.readFully(bytes); + System.err.println("Deprecated attribute with length > 0"); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitDeprecated(this); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + if (length > 0) { + file.write(bytes, 0, length); + } + } + + + /** + * @return data bytes. + */ + public final byte[] getBytes() { + return bytes; + } + + + /** + * @param bytes the raw bytes that represents this byte array + */ + public final void setBytes( byte[] bytes ) { + this.bytes = bytes; + } + + + /** + * @return attribute name + */ + public final String toString() { + return Constants.ATTRIBUTE_NAMES[Constants.ATTR_DEPRECATED]; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + Deprecated c = (Deprecated) clone(); + if (bytes != null) { + c.bytes = new byte[bytes.length]; + System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); + } + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/DescendingVisitor.java b/java/org/apache/tomcat/util/bcel/classfile/DescendingVisitor.java new file mode 100644 index 000000000..7aafd4e6f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/DescendingVisitor.java @@ -0,0 +1,445 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.util.Stack; + +/** + * Traverses a JavaClass with another Visitor object 'piggy-backed' that is + * applied to all components of a JavaClass object. I.e. this class supplies the + * traversal strategy, other classes can make use of it. + * + * @version $Id$ + * @author M. Dahm + */ +public class DescendingVisitor implements Visitor +{ + private JavaClass clazz; + + private Visitor visitor; + + private Stack stack = new Stack(); + + /** + * @return container of current entitity, i.e., predecessor during traversal + */ + public Object predecessor() + { + return predecessor(0); + } + + /** + * @param level + * nesting level, i.e., 0 returns the direct predecessor + * @return container of current entitity, i.e., predecessor during traversal + */ + public Object predecessor(int level) + { + int size = stack.size(); + if ((size < 2) || (level < 0)) + { + return null; + } + else + { + return stack.elementAt(size - (level + 2)); // size - 1 == current + } + } + + /** + * @return current object + */ + public Object current() + { + return stack.peek(); + } + + /** + * @param clazz + * Class to traverse + * @param visitor + * visitor object to apply to all components + */ + public DescendingVisitor(JavaClass clazz, Visitor visitor) + { + this.clazz = clazz; + this.visitor = visitor; + } + + /** + * Start traversal. + */ + public void visit() + { + clazz.accept(this); + } + + public void visitJavaClass(JavaClass _clazz) + { + stack.push(_clazz); + _clazz.accept(visitor); + Field[] fields = _clazz.getFields(); + for (int i = 0; i < fields.length; i++) + { + fields[i].accept(this); + } + Method[] methods = _clazz.getMethods(); + for (int i = 0; i < methods.length; i++) + { + methods[i].accept(this); + } + Attribute[] attributes = _clazz.getAttributes(); + for (int i = 0; i < attributes.length; i++) + { + attributes[i].accept(this); + } + _clazz.getConstantPool().accept(this); + stack.pop(); + } + + public void visitAnnotation(Annotations annotation) + { + stack.push(annotation); + annotation.accept(visitor); + AnnotationEntry[] entries = annotation.getAnnotationEntries(); + for (int i = 0; i < entries.length; i++) + { + entries[i].accept(this); + } + stack.pop(); + } + + public void visitAnnotationEntry(AnnotationEntry annotationEntry) + { + stack.push(annotationEntry); + annotationEntry.accept(visitor); + stack.pop(); + } + + public void visitField(Field field) + { + stack.push(field); + field.accept(visitor); + Attribute[] attributes = field.getAttributes(); + for (int i = 0; i < attributes.length; i++) + { + attributes[i].accept(this); + } + stack.pop(); + } + + public void visitConstantValue(ConstantValue cv) + { + stack.push(cv); + cv.accept(visitor); + stack.pop(); + } + + public void visitMethod(Method method) + { + stack.push(method); + method.accept(visitor); + Attribute[] attributes = method.getAttributes(); + for (int i = 0; i < attributes.length; i++) + { + attributes[i].accept(this); + } + stack.pop(); + } + + public void visitExceptionTable(ExceptionTable table) + { + stack.push(table); + table.accept(visitor); + stack.pop(); + } + + public void visitCode(Code code) + { + stack.push(code); + code.accept(visitor); + CodeException[] table = code.getExceptionTable(); + for (int i = 0; i < table.length; i++) + { + table[i].accept(this); + } + Attribute[] attributes = code.getAttributes(); + for (int i = 0; i < attributes.length; i++) + { + attributes[i].accept(this); + } + stack.pop(); + } + + public void visitCodeException(CodeException ce) + { + stack.push(ce); + ce.accept(visitor); + stack.pop(); + } + + public void visitLineNumberTable(LineNumberTable table) + { + stack.push(table); + table.accept(visitor); + LineNumber[] numbers = table.getLineNumberTable(); + for (int i = 0; i < numbers.length; i++) + { + numbers[i].accept(this); + } + stack.pop(); + } + + public void visitLineNumber(LineNumber number) + { + stack.push(number); + number.accept(visitor); + stack.pop(); + } + + public void visitLocalVariableTable(LocalVariableTable table) + { + stack.push(table); + table.accept(visitor); + LocalVariable[] vars = table.getLocalVariableTable(); + for (int i = 0; i < vars.length; i++) + { + vars[i].accept(this); + } + stack.pop(); + } + + public void visitStackMap(StackMap table) + { + stack.push(table); + table.accept(visitor); + StackMapEntry[] vars = table.getStackMap(); + for (int i = 0; i < vars.length; i++) + { + vars[i].accept(this); + } + stack.pop(); + } + + public void visitStackMapEntry(StackMapEntry var) + { + stack.push(var); + var.accept(visitor); + stack.pop(); + } + + public void visitStackMapTable(StackMapTable table) + { + stack.push(table); + table.accept(visitor); + StackMapTableEntry[] vars = table.getStackMapTable(); + for (int i = 0; i < vars.length; i++) + { + vars[i].accept(this); + } + stack.pop(); + } + + public void visitStackMapTableEntry(StackMapTableEntry var) + { + stack.push(var); + var.accept(visitor); + stack.pop(); + } + + public void visitLocalVariable(LocalVariable var) + { + stack.push(var); + var.accept(visitor); + stack.pop(); + } + + public void visitConstantPool(ConstantPool cp) + { + stack.push(cp); + cp.accept(visitor); + Constant[] constants = cp.getConstantPool(); + for (int i = 1; i < constants.length; i++) + { + if (constants[i] != null) + { + constants[i].accept(this); + } + } + stack.pop(); + } + + public void visitConstantClass(ConstantClass constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantDouble(ConstantDouble constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantFieldref(ConstantFieldref constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantFloat(ConstantFloat constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantInteger(ConstantInteger constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantInterfaceMethodref( + ConstantInterfaceMethodref constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantLong(ConstantLong constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantMethodref(ConstantMethodref constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantNameAndType(ConstantNameAndType constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantString(ConstantString constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitConstantUtf8(ConstantUtf8 constant) + { + stack.push(constant); + constant.accept(visitor); + stack.pop(); + } + + public void visitInnerClasses(InnerClasses ic) + { + stack.push(ic); + ic.accept(visitor); + InnerClass[] ics = ic.getInnerClasses(); + for (int i = 0; i < ics.length; i++) + { + ics[i].accept(this); + } + stack.pop(); + } + + public void visitInnerClass(InnerClass inner) + { + stack.push(inner); + inner.accept(visitor); + stack.pop(); + } + + public void visitDeprecated(Deprecated attribute) + { + stack.push(attribute); + attribute.accept(visitor); + stack.pop(); + } + + public void visitSignature(Signature attribute) + { + stack.push(attribute); + attribute.accept(visitor); + stack.pop(); + } + + public void visitSourceFile(SourceFile attribute) + { + stack.push(attribute); + attribute.accept(visitor); + stack.pop(); + } + + public void visitSynthetic(Synthetic attribute) + { + stack.push(attribute); + attribute.accept(visitor); + stack.pop(); + } + + public void visitUnknown(Unknown attribute) + { + stack.push(attribute); + attribute.accept(visitor); + stack.pop(); + } + + public void visitAnnotationDefault(AnnotationDefault obj) + { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } + + public void visitEnclosingMethod(EnclosingMethod obj) + { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } + + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) + { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } + + public void visitParameterAnnotation(ParameterAnnotations obj) + { + stack.push(obj); + obj.accept(visitor); + stack.pop(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/ElementValue.java new file mode 100644 index 000000000..f16616c9e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ElementValue.java @@ -0,0 +1,142 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * @version $Id: ElementValue + * @author D. Brosius + * @since 5.3 + */ +public abstract class ElementValue +{ + protected int type; + + protected ConstantPool cpool; + + public String toString() + { + return stringifyValue(); + } + + protected ElementValue(int type, ConstantPool cpool) + { + this.type = type; + this.cpool = cpool; + } + + public int getElementValueType() + { + return type; + } + + public abstract String stringifyValue(); + + public abstract void dump(DataOutputStream dos) throws IOException; + + public static final int STRING = 's'; + + public static final int ENUM_CONSTANT = 'e'; + + public static final int CLASS = 'c'; + + public static final int ANNOTATION = '@'; + + public static final int ARRAY = '['; + + public static final int PRIMITIVE_INT = 'I'; + + public static final int PRIMITIVE_BYTE = 'B'; + + public static final int PRIMITIVE_CHAR = 'C'; + + public static final int PRIMITIVE_DOUBLE = 'D'; + + public static final int PRIMITIVE_FLOAT = 'F'; + + public static final int PRIMITIVE_LONG = 'J'; + + public static final int PRIMITIVE_SHORT = 'S'; + + public static final int PRIMITIVE_BOOLEAN = 'Z'; + + public static ElementValue readElementValue(DataInputStream dis, + ConstantPool cpool) throws IOException + { + byte type = dis.readByte(); + switch (type) + { + case 'B': // byte + return new SimpleElementValue(PRIMITIVE_BYTE, dis + .readUnsignedShort(), cpool); + case 'C': // char + return new SimpleElementValue(PRIMITIVE_CHAR, dis + .readUnsignedShort(), cpool); + case 'D': // double + return new SimpleElementValue(PRIMITIVE_DOUBLE, dis + .readUnsignedShort(), cpool); + case 'F': // float + return new SimpleElementValue(PRIMITIVE_FLOAT, dis + .readUnsignedShort(), cpool); + case 'I': // int + return new SimpleElementValue(PRIMITIVE_INT, dis + .readUnsignedShort(), cpool); + case 'J': // long + return new SimpleElementValue(PRIMITIVE_LONG, dis + .readUnsignedShort(), cpool); + case 'S': // short + return new SimpleElementValue(PRIMITIVE_SHORT, dis + .readUnsignedShort(), cpool); + case 'Z': // boolean + return new SimpleElementValue(PRIMITIVE_BOOLEAN, dis + .readUnsignedShort(), cpool); + case 's': // String + return new SimpleElementValue(STRING, dis.readUnsignedShort(), + cpool); + case 'e': // Enum constant + return new EnumElementValue(ENUM_CONSTANT, dis.readUnsignedShort(), + dis.readUnsignedShort(), cpool); + case 'c': // Class + return new ClassElementValue(CLASS, dis.readUnsignedShort(), cpool); + case '@': // Annotation + // TODO isRuntimeVisible + return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read( + dis, cpool, false), cpool); + case '[': // Array + int numArrayVals = dis.readUnsignedShort(); + ElementValue[] evalues = new ElementValue[numArrayVals]; + for (int j = 0; j < numArrayVals; j++) + { + evalues[j] = ElementValue.readElementValue(dis, cpool); + } + return new ArrayElementValue(ARRAY, evalues, cpool); + default: + throw new RuntimeException( + "Unexpected element value kind in annotation: " + type); + } + } + + public String toShortString() + { + StringBuffer result = new StringBuffer(); + result.append(stringifyValue()); + return result.toString(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ElementValuePair.java b/java/org/apache/tomcat/util/bcel/classfile/ElementValuePair.java new file mode 100644 index 000000000..4c36a640e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ElementValuePair.java @@ -0,0 +1,75 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * an annotation's element value pair + * + * @version $Id: ElementValuePair + * @author D. Brosius + * @since 5.3 + */ +public class ElementValuePair +{ + private ElementValue elementValue; + + private ConstantPool constantPool; + + private int elementNameIndex; + + public ElementValuePair(int elementNameIndex, ElementValue elementValue, + ConstantPool constantPool) + { + this.elementValue = elementValue; + this.elementNameIndex = elementNameIndex; + this.constantPool = constantPool; + } + + public String getNameString() + { + ConstantUtf8 c = (ConstantUtf8) constantPool.getConstant( + elementNameIndex, Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + public final ElementValue getValue() + { + return elementValue; + } + + public int getNameIndex() + { + return elementNameIndex; + } + + public String toShortString() + { + StringBuffer result = new StringBuffer(); + result.append(getNameString()).append("=").append( + getValue().toShortString()); + return result.toString(); + } + + protected void dump(DataOutputStream dos) throws IOException { + dos.writeShort(elementNameIndex); // u2 name of the element + elementValue.dump(dos); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/EmptyVisitor.java b/java/org/apache/tomcat/util/bcel/classfile/EmptyVisitor.java new file mode 100644 index 000000000..5a1d86105 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/EmptyVisitor.java @@ -0,0 +1,191 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * Visitor with empty method bodies, can be extended and used in conjunction + * with the DescendingVisitor class, e.g. By courtesy of David Spencer. + * + * @see DescendingVisitor + * @version $Id$ + */ +public class EmptyVisitor implements Visitor +{ + protected EmptyVisitor() + { + } + + public void visitAnnotation(Annotations obj) + { + } + + public void visitParameterAnnotation(ParameterAnnotations obj) + { + } + + public void visitAnnotationEntry(AnnotationEntry obj) + { + } + + public void visitAnnotationDefault(AnnotationDefault obj) + { + } + + public void visitCode(Code obj) + { + } + + public void visitCodeException(CodeException obj) + { + } + + public void visitConstantClass(ConstantClass obj) + { + } + + public void visitConstantDouble(ConstantDouble obj) + { + } + + public void visitConstantFieldref(ConstantFieldref obj) + { + } + + public void visitConstantFloat(ConstantFloat obj) + { + } + + public void visitConstantInteger(ConstantInteger obj) + { + } + + public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj) + { + } + + public void visitConstantLong(ConstantLong obj) + { + } + + public void visitConstantMethodref(ConstantMethodref obj) + { + } + + public void visitConstantNameAndType(ConstantNameAndType obj) + { + } + + public void visitConstantPool(ConstantPool obj) + { + } + + public void visitConstantString(ConstantString obj) + { + } + + public void visitConstantUtf8(ConstantUtf8 obj) + { + } + + public void visitConstantValue(ConstantValue obj) + { + } + + public void visitDeprecated(Deprecated obj) + { + } + + public void visitExceptionTable(ExceptionTable obj) + { + } + + public void visitField(Field obj) + { + } + + public void visitInnerClass(InnerClass obj) + { + } + + public void visitInnerClasses(InnerClasses obj) + { + } + + public void visitJavaClass(JavaClass obj) + { + } + + public void visitLineNumber(LineNumber obj) + { + } + + public void visitLineNumberTable(LineNumberTable obj) + { + } + + public void visitLocalVariable(LocalVariable obj) + { + } + + public void visitLocalVariableTable(LocalVariableTable obj) + { + } + + public void visitMethod(Method obj) + { + } + + public void visitSignature(Signature obj) + { + } + + public void visitSourceFile(SourceFile obj) + { + } + + public void visitSynthetic(Synthetic obj) + { + } + + public void visitUnknown(Unknown obj) + { + } + + public void visitStackMap(StackMap obj) + { + } + + public void visitStackMapEntry(StackMapEntry obj) + { + } + + public void visitStackMapTable(StackMapTable obj) + { + } + + public void visitStackMapTableEntry(StackMapTableEntry obj) + { + } + + public void visitEnclosingMethod(EnclosingMethod obj) + { + } + + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) + { + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/EnclosingMethod.java b/java/org/apache/tomcat/util/bcel/classfile/EnclosingMethod.java new file mode 100755 index 000000000..ab08c4193 --- /dev/null +++ b/java/org/apache/tomcat/util/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 Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * ******************************************************************/ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This attribute exists for local or + * anonymous classes and ... there can be only one. + */ +public class EnclosingMethod extends Attribute { + + // Pointer to the CONSTANT_Class_info structure representing the + // innermost class that encloses the declaration of the current class. + private int classIndex; + + // If the current class is not immediately enclosed by a method or + // constructor, then the value of the method_index item must be zero. + // Otherwise, the value of the method_index item must point to a + // CONSTANT_NameAndType_info structure representing the name and the + // type of a method in the class referenced by the class we point + // to in the class_index. *It is the compiler responsibility* to + // ensure that the method identified by this index is the closest + // lexically enclosing method that includes the local/anonymous class. + private int methodIndex; + + // Ctors - and code to read an attribute in. + public EnclosingMethod(int nameIndex, int len, DataInput dis, ConstantPool cpool) throws IOException { + this(nameIndex, len, dis.readUnsignedShort(), dis.readUnsignedShort(), cpool); + } + + private EnclosingMethod(int nameIndex, int len, int classIdx,int methodIdx, ConstantPool cpool) { + super(Constants.ATTR_ENCLOSING_METHOD, nameIndex, len, cpool); + classIndex = classIdx; + methodIndex = methodIdx; + } + + public void accept(Visitor v) { + v.visitEnclosingMethod(this); + } + + public Attribute copy(ConstantPool constant_pool) { + throw new RuntimeException("Not implemented yet!"); + // is this next line sufficient? + // return (EnclosingMethod)clone(); + } + + // Accessors + public final int getEnclosingClassIndex() { return classIndex; } + public final int getEnclosingMethodIndex(){ return methodIndex;} + + public final void setEnclosingClassIndex(int idx) {classIndex = idx;} + public final void setEnclosingMethodIndex(int idx){methodIndex= idx;} + + public final ConstantClass getEnclosingClass() { + ConstantClass c = + (ConstantClass)constant_pool.getConstant(classIndex,Constants.CONSTANT_Class); + return c; + } + + public final ConstantNameAndType getEnclosingMethod() { + if (methodIndex == 0) return null; + ConstantNameAndType nat = + (ConstantNameAndType)constant_pool.getConstant(methodIndex,Constants.CONSTANT_NameAndType); + return nat; + } + + public final void dump(DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(classIndex); + file.writeShort(methodIndex); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/EnumElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/EnumElementValue.java new file mode 100644 index 000000000..4d2c89929 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/EnumElementValue.java @@ -0,0 +1,62 @@ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +public class EnumElementValue extends ElementValue +{ + // For enum types, these two indices point to the type and value + private int typeIdx; + + private int valueIdx; + + public EnumElementValue(int type, int typeIdx, int valueIdx, + ConstantPool cpool) + { + super(type, cpool); + if (type != ENUM_CONSTANT) + throw new RuntimeException( + "Only element values of type enum can be built with this ctor - type specified: " + type); + this.typeIdx = typeIdx; + this.valueIdx = valueIdx; + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e') + dos.writeShort(typeIdx); // u2 + dos.writeShort(valueIdx); // u2 + } + + public String stringifyValue() + { + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(valueIdx, + Constants.CONSTANT_Utf8); + return cu8.getBytes(); + } + + public String getEnumTypeString() + { + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(typeIdx, + Constants.CONSTANT_Utf8); + return cu8.getBytes();// Utility.signatureToString(cu8.getBytes()); + } + + public String getEnumValueString() + { + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(valueIdx, + Constants.CONSTANT_Utf8); + return cu8.getBytes(); + } + + public int getValueIndex() + { + return valueIdx; + } + + public int getTypeIndex() + { + return typeIdx; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ExceptionTable.java b/java/org/apache/tomcat/util/bcel/classfile/ExceptionTable.java new file mode 100644 index 000000000..222478a8b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ExceptionTable.java @@ -0,0 +1,180 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents the table of exceptions that are thrown by a + * method. This attribute may be used once per method. The name of + * this class is ExceptionTable for historical reasons; The + * Java Virtual Machine Specification, Second Edition defines this + * attribute using the name Exceptions (which is inconsistent + * with the other classes). + * + * @version $Id$ + * @author M. Dahm + * @see Code + */ +public final class ExceptionTable extends Attribute { + + private int number_of_exceptions; // Table of indices into + private int[] exception_index_table; // constant pool + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public ExceptionTable(ExceptionTable c) { + this(c.getNameIndex(), c.getLength(), c.getExceptionIndexTable(), c.getConstantPool()); + } + + + /** + * @param name_index Index in constant pool + * @param length Content length in bytes + * @param exception_index_table Table of indices in constant pool + * @param constant_pool Array of constants + */ + public ExceptionTable(int name_index, int length, int[] exception_index_table, + ConstantPool constant_pool) { + super(Constants.ATTR_EXCEPTIONS, name_index, length, constant_pool); + setExceptionIndexTable(exception_index_table); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + ExceptionTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (int[]) null, constant_pool); + number_of_exceptions = file.readUnsignedShort(); + exception_index_table = new int[number_of_exceptions]; + for (int i = 0; i < number_of_exceptions; i++) { + exception_index_table[i] = file.readUnsignedShort(); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionTable(this); + } + + + /** + * Dump exceptions attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(number_of_exceptions); + for (int i = 0; i < number_of_exceptions; i++) { + file.writeShort(exception_index_table[i]); + } + } + + + /** + * @return Array of indices into constant pool of thrown exceptions. + */ + public final int[] getExceptionIndexTable() { + return exception_index_table; + } + + + /** + * @return Length of exception table. + */ + public final int getNumberOfExceptions() { + return number_of_exceptions; + } + + + /** + * @return class names of thrown exceptions + */ + public final String[] getExceptionNames() { + String[] names = new String[number_of_exceptions]; + for (int i = 0; i < number_of_exceptions; i++) { + names[i] = constant_pool.getConstantString(exception_index_table[i], + Constants.CONSTANT_Class).replace('/', '.'); + } + return names; + } + + + /** + * @param exception_index_table the list of exception indexes + * Also redefines number_of_exceptions according to table length. + */ + public final void setExceptionIndexTable( int[] exception_index_table ) { + this.exception_index_table = exception_index_table; + number_of_exceptions = (exception_index_table == null) ? 0 : exception_index_table.length; + } + + + /** + * @return String representation, i.e., a list of thrown exceptions. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(); + String str; + for (int i = 0; i < number_of_exceptions; i++) { + str = constant_pool.getConstantString(exception_index_table[i], + Constants.CONSTANT_Class); + buf.append(Utility.compactClassName(str, false)); + if (i < number_of_exceptions - 1) { + buf.append(", "); + } + } + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + ExceptionTable c = (ExceptionTable) clone(); + if (exception_index_table != null) { + c.exception_index_table = new int[exception_index_table.length]; + System.arraycopy(exception_index_table, 0, c.exception_index_table, 0, + exception_index_table.length); + } + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Field.java b/java/org/apache/tomcat/util/bcel/classfile/Field.java new file mode 100644 index 000000000..3e907b880 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Field.java @@ -0,0 +1,190 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.generic.Type; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * This class represents the field info structure, i.e., the representation + * for a variable in the class. See JVM specification for details. + * + * @version $Id$ + * @author M. Dahm + */ +public final class Field extends FieldOrMethod { + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + Field THIS = (Field) o1; + Field THAT = (Field) o2; + return THIS.getName().equals(THAT.getName()) + && THIS.getSignature().equals(THAT.getSignature()); + } + + + public int hashCode( Object o ) { + Field THIS = (Field) o; + return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + } + }; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public Field(Field c) { + super(c); + } + + + /** + * Construct object from file stream. + * @param file Input stream + */ + Field(DataInputStream file, ConstantPool constant_pool) throws IOException, + ClassFormatException { + super(file, constant_pool); + } + + + /** + * @param access_flags Access rights of field + * @param name_index Points to field name in constant pool + * @param signature_index Points to encoded signature + * @param attributes Collection of attributes + * @param constant_pool Array of constants + */ + public Field(int access_flags, int name_index, int signature_index, Attribute[] attributes, + ConstantPool constant_pool) { + super(access_flags, name_index, signature_index, attributes, constant_pool); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitField(this); + } + + + /** + * @return constant value associated with this field (may be null) + */ + public final ConstantValue getConstantValue() { + for (int i = 0; i < attributes_count; i++) { + if (attributes[i].getTag() == Constants.ATTR_CONSTANT_VALUE) { + return (ConstantValue) attributes[i]; + } + } + return null; + } + + + /** + * Return string representation close to declaration format, + * `public static final short MAX = 100', e.g.. + * + * @return String representation of field, including the signature. + */ + public final String toString() { + String name, signature, access; // Short cuts to constant pool + // Get names from constant pool + access = Utility.accessToString(access_flags); + access = access.equals("") ? "" : (access + " "); + signature = Utility.signatureToString(getSignature()); + name = getName(); + StringBuffer buf = new StringBuffer(64); + buf.append(access).append(signature).append(" ").append(name); + ConstantValue cv = getConstantValue(); + if (cv != null) { + buf.append(" = ").append(cv); + } + for (int i = 0; i < attributes_count; i++) { + Attribute a = attributes[i]; + if (!(a instanceof ConstantValue)) { + buf.append(" [").append(a.toString()).append("]"); + } + } + return buf.toString(); + } + + + /** + * @return deep copy of this field + */ + public final Field copy( ConstantPool _constant_pool ) { + return (Field) copy_(_constant_pool); + } + + + /** + * @return type of field + */ + public Type getType() { + return Type.getReturnType(getSignature()); + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two Field objects are said to be equal when + * their names and signatures are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the field's name XOR signature. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/FieldOrMethod.java b/java/org/apache/tomcat/util/bcel/classfile/FieldOrMethod.java new file mode 100644 index 000000000..e4f7c8595 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/FieldOrMethod.java @@ -0,0 +1,290 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Signature; + +/** + * Abstract super class for fields and methods. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { + + protected int name_index; // Points to field name in constant pool + protected int signature_index; // Points to encoded signature + protected int attributes_count; // No. of attributes + protected Attribute[] attributes; // Collection of attributes + protected AnnotationEntry[] annotationEntries; // annotations defined on the field or method + protected ConstantPool constant_pool; + + private String signatureAttributeString = null; + private boolean searchedForSignatureAttribute = false; + + + // Annotations are collected from certain attributes, don't do it more than necessary! + private boolean annotationsOutOfDate = true; + + FieldOrMethod() { + } + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + protected FieldOrMethod(FieldOrMethod c) { + this(c.getAccessFlags(), c.getNameIndex(), c.getSignatureIndex(), c.getAttributes(), c + .getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + * @throws ClassFormatException + */ + protected FieldOrMethod(DataInputStream file, ConstantPool constant_pool) throws IOException, + ClassFormatException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, + constant_pool); + attributes_count = file.readUnsignedShort(); + attributes = new Attribute[attributes_count]; + for (int i = 0; i < attributes_count; i++) { + attributes[i] = Attribute.readAttribute(file, constant_pool); + } + } + + + /** + * @param access_flags Access rights of method + * @param name_index Points to field name in constant pool + * @param signature_index Points to encoded signature + * @param attributes Collection of attributes + * @param constant_pool Array of constants + */ + protected FieldOrMethod(int access_flags, int name_index, int signature_index, + Attribute[] attributes, ConstantPool constant_pool) { + this.access_flags = access_flags; + this.name_index = name_index; + this.signature_index = signature_index; + this.constant_pool = constant_pool; + setAttributes(attributes); + } + + + /** + * Dump object to file stream on binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(access_flags); + file.writeShort(name_index); + file.writeShort(signature_index); + file.writeShort(attributes_count); + for (int i = 0; i < attributes_count; i++) { + attributes[i].dump(file); + } + } + + + /** + * @return Collection of object attributes. + */ + public final Attribute[] getAttributes() { + return attributes; + } + + + /** + * @param attributes Collection of object attributes. + */ + public final void setAttributes( Attribute[] attributes ) { + this.attributes = attributes; + attributes_count = (attributes == null) ? 0 : attributes.length; + } + + + /** + * @return Constant pool used by this object. + */ + public final ConstantPool getConstantPool() { + return constant_pool; + } + + + /** + * @param constant_pool Constant pool to be used for this object. + */ + public final void setConstantPool( ConstantPool constant_pool ) { + this.constant_pool = constant_pool; + } + + + /** + * @return Index in constant pool of object's name. + */ + public final int getNameIndex() { + return name_index; + } + + + /** + * @param name_index Index in constant pool of object's name. + */ + public final void setNameIndex( int name_index ) { + this.name_index = name_index; + } + + + /** + * @return Index in constant pool of field signature. + */ + public final int getSignatureIndex() { + return signature_index; + } + + + /** + * @param signature_index Index in constant pool of field signature. + */ + public final void setSignatureIndex( int signature_index ) { + this.signature_index = signature_index; + } + + + /** + * @return Name of object, i.e., method name or field name + */ + public final String getName() { + ConstantUtf8 c; + c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return String representation of object's type signature (java style) + */ + public final String getSignature() { + ConstantUtf8 c; + c = (ConstantUtf8) constant_pool.getConstant(signature_index, Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return deep copy of this field + */ + protected FieldOrMethod copy_( ConstantPool _constant_pool ) { + FieldOrMethod c = null; + + try { + c = (FieldOrMethod)clone(); + } catch(CloneNotSupportedException e) {} + + c.constant_pool = constant_pool; + c.attributes = new Attribute[attributes_count]; + + for(int i=0; i < attributes_count; i++) + c.attributes[i] = attributes[i].copy(constant_pool); + + return c; + } + + /** + * Ensure we have unpacked any attributes that contain annotations. + * We don't remove these annotation attributes from the attributes list, they + * remain there. + */ + private void ensureAnnotationsUpToDate() + { + if (annotationsOutOfDate) + { + // Find attributes that contain annotation data + Attribute[] attrs = getAttributes(); + List accumulatedAnnotations = new ArrayList(); + for (int i = 0; i < attrs.length; i++) + { + Attribute attribute = attrs[i]; + if (attribute instanceof Annotations) + { + Annotations annotations = (Annotations) attribute; + for (int j = 0; j < annotations.getAnnotationEntries().length; j++) + { + accumulatedAnnotations.add(annotations + .getAnnotationEntries()[j]); + } + } + } + annotationEntries = (AnnotationEntry[]) accumulatedAnnotations + .toArray(new AnnotationEntry[accumulatedAnnotations.size()]); + annotationsOutOfDate = false; + } + } + + public AnnotationEntry[] getAnnotationEntries() + { + ensureAnnotationsUpToDate(); + return annotationEntries; + } + + public void addAnnotationEntry(AnnotationEntry a) + { + ensureAnnotationsUpToDate(); + int len = annotationEntries.length; + AnnotationEntry[] newAnnotations = new AnnotationEntry[len + 1]; + System.arraycopy(annotationEntries, 0, newAnnotations, 0, len); + newAnnotations[len] = a; + annotationEntries = newAnnotations; + } + + /** + * Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature + * may be (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector;' + * Coded for performance - searches for the attribute only when requested - only searches for it once. + */ + public final String getGenericSignature() + { + if (!searchedForSignatureAttribute) + { + boolean found = false; + for (int i = 0; !found && i < attributes_count; i++) + { + if (attributes[i] instanceof Signature) + { + signatureAttributeString = ((Signature) attributes[i]) + .getSignature(); + found = true; + } + } + searchedForSignatureAttribute = true; + } + return signatureAttributeString; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/InnerClass.java b/java/org/apache/tomcat/util/bcel/classfile/InnerClass.java new file mode 100644 index 000000000..f64f08f13 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/InnerClass.java @@ -0,0 +1,215 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a inner class attribute, i.e., the class + * indices of the inner and outer classes, the name and the attributes + * of the inner class. + * + * @version $Id$ + * @author M. Dahm + * @see InnerClasses + */ +public final class InnerClass implements Cloneable, Node, Serializable { + + private int inner_class_index; + private int outer_class_index; + private int inner_name_index; + private int inner_access_flags; + + + /** + * Initialize from another object. + */ + public InnerClass(InnerClass c) { + this(c.getInnerClassIndex(), c.getOuterClassIndex(), c.getInnerNameIndex(), c + .getInnerAccessFlags()); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + InnerClass(DataInput file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file + .readUnsignedShort()); + } + + + /** + * @param inner_class_index Class index in constant pool of inner class + * @param outer_class_index Class index in constant pool of outer class + * @param inner_name_index Name index in constant pool of inner class + * @param inner_access_flags Access flags of inner class + */ + public InnerClass(int inner_class_index, int outer_class_index, int inner_name_index, + int inner_access_flags) { + this.inner_class_index = inner_class_index; + this.outer_class_index = outer_class_index; + this.inner_name_index = inner_name_index; + this.inner_access_flags = inner_access_flags; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitInnerClass(this); + } + + + /** + * Dump inner class attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(inner_class_index); + file.writeShort(outer_class_index); + file.writeShort(inner_name_index); + file.writeShort(inner_access_flags); + } + + + /** + * @return access flags of inner class. + */ + public final int getInnerAccessFlags() { + return inner_access_flags; + } + + + /** + * @return class index of inner class. + */ + public final int getInnerClassIndex() { + return inner_class_index; + } + + + /** + * @return name index of inner class. + */ + public final int getInnerNameIndex() { + return inner_name_index; + } + + + /** + * @return class index of outer class. + */ + public final int getOuterClassIndex() { + return outer_class_index; + } + + + /** + * @param inner_access_flags access flags for this inner class + */ + public final void setInnerAccessFlags( int inner_access_flags ) { + this.inner_access_flags = inner_access_flags; + } + + + /** + * @param inner_class_index index into the constant pool for this class + */ + public final void setInnerClassIndex( int inner_class_index ) { + this.inner_class_index = inner_class_index; + } + + + /** + * @param inner_name_index index into the constant pool for this class's name + */ + public final void setInnerNameIndex( int inner_name_index ) { + this.inner_name_index = inner_name_index; + } + + + /** + * @param outer_class_index index into the constant pool for the owning class + */ + public final void setOuterClassIndex( int outer_class_index ) { + this.outer_class_index = outer_class_index; + } + + + /** + * @return String representation. + */ + public final String toString() { + return "InnerClass(" + inner_class_index + ", " + outer_class_index + ", " + + inner_name_index + ", " + inner_access_flags + ")"; + } + + + /** + * @return Resolved string representation + */ + public final String toString( ConstantPool constant_pool ) { + String inner_class_name, outer_class_name, inner_name, access; + inner_class_name = constant_pool.getConstantString(inner_class_index, + Constants.CONSTANT_Class); + inner_class_name = Utility.compactClassName(inner_class_name); + if (outer_class_index != 0) { + outer_class_name = constant_pool.getConstantString(outer_class_index, + Constants.CONSTANT_Class); + outer_class_name = Utility.compactClassName(outer_class_name); + } else { + outer_class_name = ""; + } + if (inner_name_index != 0) { + inner_name = ((ConstantUtf8) constant_pool.getConstant(inner_name_index, + Constants.CONSTANT_Utf8)).getBytes(); + } else { + inner_name = ""; + } + 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/java/org/apache/tomcat/util/bcel/classfile/InnerClasses.java b/java/org/apache/tomcat/util/bcel/classfile/InnerClasses.java new file mode 100644 index 000000000..5f46f54bc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/InnerClasses.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute and denotes that this class + * is an Inner class of another. + * to the source file of this class. + * It is instantiated from the Attribute.readAttribute() method. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class InnerClasses extends Attribute { + + private InnerClass[] inner_classes; + private int number_of_classes; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public InnerClasses(InnerClasses c) { + this(c.getNameIndex(), c.getLength(), c.getInnerClasses(), c.getConstantPool()); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param inner_classes array of inner classes attributes + * @param constant_pool Array of constants + */ + public InnerClasses(int name_index, int length, InnerClass[] inner_classes, + ConstantPool constant_pool) { + super(Constants.ATTR_INNER_CLASSES, name_index, length, constant_pool); + setInnerClasses(inner_classes); + } + + + /** + * Construct object from file stream. + * + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + InnerClasses(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (InnerClass[]) null, constant_pool); + number_of_classes = file.readUnsignedShort(); + inner_classes = new InnerClass[number_of_classes]; + for (int i = 0; i < number_of_classes; i++) { + inner_classes[i] = new InnerClass(file); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitInnerClasses(this); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(number_of_classes); + for (int i = 0; i < number_of_classes; i++) { + inner_classes[i].dump(file); + } + } + + + /** + * @return array of inner class "records" + */ + public final InnerClass[] getInnerClasses() { + return inner_classes; + } + + + /** + * @param inner_classes the array of inner classes + */ + public final void setInnerClasses( InnerClass[] inner_classes ) { + this.inner_classes = inner_classes; + number_of_classes = (inner_classes == null) ? 0 : inner_classes.length; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < number_of_classes; i++) { + buf.append(inner_classes[i].toString(constant_pool)).append("\n"); + } + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + InnerClasses c = (InnerClasses) clone(); + c.inner_classes = new InnerClass[number_of_classes]; + for (int i = 0; i < number_of_classes; i++) { + c.inner_classes[i] = inner_classes[i].copy(); + } + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java b/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java new file mode 100644 index 000000000..84298d0e1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/JavaClass.java @@ -0,0 +1,933 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeSet; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.generic.Type; +import org.apache.tomcat.util.bcel.util.BCELComparator; +import org.apache.tomcat.util.bcel.util.ClassQueue; +import org.apache.tomcat.util.bcel.util.SyntheticRepository; + +/** + * Represents a Java class, i.e., the data structures, constant pool, + * fields, methods and commands contained in a Java .class file. + * See JVM specification 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 ClassGen class. + + * @version $Id$ + * @see org.apache.tomcat.util.bcel.generic.ClassGen + * @author M. Dahm + */ +public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable { + + private String file_name; + private String package_name; + private String source_file_name = ""; + private int class_name_index; + private int superclass_name_index; + private String class_name; + private String superclass_name; + private int major, minor; // Compiler version + private ConstantPool constant_pool; // Constant pool + private int[] interfaces; // implemented interfaces + private String[] interface_names; + private Field[] fields; // Fields, i.e., variables of class + private Method[] methods; // methods defined in the class + private Attribute[] attributes; // attributes defined in the class + private AnnotationEntry[] annotations; // annotations defined on the class + private byte source = HEAP; // Generated in memory + private boolean isAnonymous = false; + private boolean isNested = false; + private boolean computedNestedTypeStatus = false; + public static final byte HEAP = 1; + public static final byte FILE = 2; + public static final byte ZIP = 3; + static boolean debug = false; // Debugging on/off + static char sep = '/'; // directory separator + + // Annotations are collected from certain attributes, don't do it more than necessary! + private boolean annotationsOutOfDate = true; + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + JavaClass THIS = (JavaClass) o1; + JavaClass THAT = (JavaClass) o2; + return THIS.getClassName().equals(THAT.getClassName()); + } + + + public int hashCode( Object o ) { + JavaClass THIS = (JavaClass) o; + return THIS.getClassName().hashCode(); + } + }; + /** + * In cases where we go ahead and create something, + * use the default SyntheticRepository, because we + * don't know any better. + */ + private transient org.apache.tomcat.util.bcel.util.Repository repository = SyntheticRepository + .getInstance(); + + + /** + * Constructor gets all contents as arguments. + * + * @param class_name_index Index into constant pool referencing a + * ConstantClass that represents this class. + * @param superclass_name_index Index into constant pool referencing a + * ConstantClass that represents this class's superclass. + * @param file_name File name + * @param major Major compiler version + * @param minor Minor compiler version + * @param access_flags Access rights defined by bit flags + * @param constant_pool Array of constants + * @param interfaces Implemented interfaces + * @param fields Class fields + * @param methods Class methods + * @param attributes Class attributes + * @param source Read from file or generated in memory? + */ + public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major, + int minor, int access_flags, ConstantPool constant_pool, int[] interfaces, + Field[] fields, Method[] methods, Attribute[] attributes, byte source) { + if (interfaces == null) { + interfaces = new int[0]; + } + if (attributes == null) { + attributes = new Attribute[0]; + } + if (fields == null) { + fields = new Field[0]; + } + if (methods == null) { + methods = new Method[0]; + } + this.class_name_index = class_name_index; + this.superclass_name_index = superclass_name_index; + this.file_name = file_name; + this.major = major; + this.minor = minor; + this.access_flags = access_flags; + this.constant_pool = constant_pool; + this.interfaces = interfaces; + this.fields = fields; + this.methods = methods; + this.attributes = attributes; + annotationsOutOfDate = true; + this.source = source; + // Get source file name if available + for (int i = 0; i < attributes.length; i++) { + if (attributes[i] instanceof SourceFile) { + source_file_name = ((SourceFile) attributes[i]).getSourceFileName(); + break; + } + } + /* According to the specification the following entries must be of type + * `ConstantClass' but we check that anyway via the + * `ConstPool.getConstant' method. + */ + class_name = constant_pool.getConstantString(class_name_index, Constants.CONSTANT_Class); + class_name = Utility.compactClassName(class_name, false); + int index = class_name.lastIndexOf('.'); + if (index < 0) { + package_name = ""; + } else { + package_name = class_name.substring(0, index); + } + if (superclass_name_index > 0) { + // May be zero -> class is java.lang.Object + superclass_name = constant_pool.getConstantString(superclass_name_index, + Constants.CONSTANT_Class); + superclass_name = Utility.compactClassName(superclass_name, false); + } else { + superclass_name = "java.lang.Object"; + } + interface_names = new String[interfaces.length]; + for (int i = 0; i < interfaces.length; i++) { + String str = constant_pool.getConstantString(interfaces[i], Constants.CONSTANT_Class); + interface_names[i] = Utility.compactClassName(str, false); + } + } + + + /** + * Constructor gets all contents as arguments. + * + * @param class_name_index Class name + * @param superclass_name_index Superclass name + * @param file_name File name + * @param major Major compiler version + * @param minor Minor compiler version + * @param access_flags Access rights defined by bit flags + * @param constant_pool Array of constants + * @param interfaces Implemented interfaces + * @param fields Class fields + * @param methods Class methods + * @param attributes Class attributes + */ + public JavaClass(int class_name_index, int superclass_name_index, String file_name, int major, + int minor, int access_flags, ConstantPool constant_pool, int[] interfaces, + Field[] fields, Method[] methods, Attribute[] attributes) { + this(class_name_index, superclass_name_index, file_name, major, minor, access_flags, + constant_pool, interfaces, fields, methods, attributes, HEAP); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitJavaClass(this); + } + + + /* Print debug information depending on `JavaClass.debug' + */ + static final void Debug( String str ) { + if (debug) { + System.out.println(str); + } + } + + + /** + * Dump class to a file. + * + * @param file Output file + * @throws IOException + */ + public void dump( File file ) throws IOException { + String parent = file.getParent(); + if (parent != null) { + File dir = new File(parent); + dir.mkdirs(); + } + DataOutputStream dos = null; + try { + dos = new DataOutputStream(new FileOutputStream(file)); + dump(dos); + } finally { + if (dos != null) { + dos.close(); + } + } + } + + + /** + * Dump class to a file named file_name. + * + * @param _file_name Output file name + * @exception IOException + */ + public void dump( String _file_name ) throws IOException { + dump(new File(_file_name)); + } + + + /** + * @return class in binary format + */ + public byte[] getBytes() { + ByteArrayOutputStream s = new ByteArrayOutputStream(); + DataOutputStream ds = new DataOutputStream(s); + try { + dump(ds); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + ds.close(); + } catch (IOException e2) { + e2.printStackTrace(); + } + } + return s.toByteArray(); + } + + + /** + * Dump Java class to output stream in binary format. + * + * @param file Output stream + * @exception IOException + */ + public void dump( OutputStream file ) throws IOException { + dump(new DataOutputStream(file)); + } + + + /** + * Dump Java class to output stream in binary format. + * + * @param file Output stream + * @exception IOException + */ + public void dump( DataOutputStream file ) throws IOException { + file.writeInt(0xcafebabe); + file.writeShort(minor); + file.writeShort(major); + constant_pool.dump(file); + file.writeShort(access_flags); + file.writeShort(class_name_index); + file.writeShort(superclass_name_index); + file.writeShort(interfaces.length); + for (int i = 0; i < interfaces.length; i++) { + file.writeShort(interfaces[i]); + } + file.writeShort(fields.length); + for (int i = 0; i < fields.length; i++) { + fields[i].dump(file); + } + file.writeShort(methods.length); + for (int i = 0; i < methods.length; i++) { + methods[i].dump(file); + } + if (attributes != null) { + file.writeShort(attributes.length); + for (int i = 0; i < attributes.length; i++) { + attributes[i].dump(file); + } + } else { + file.writeShort(0); + } + file.flush(); + } + + + /** + * @return Attributes of the class. + */ + public Attribute[] getAttributes() { + return attributes; + } + + public AnnotationEntry[] getAnnotationEntries() { + if (annotationsOutOfDate) { + // Find attributes that contain annotation data + Attribute[] attrs = getAttributes(); + List accumulatedAnnotations = new ArrayList(); + for (int i = 0; i < attrs.length; i++) { + Attribute attribute = attrs[i]; + if (attribute instanceof Annotations) { + Annotations runtimeAnnotations = (Annotations)attribute; + for(int j = 0; j < runtimeAnnotations.getAnnotationEntries().length; j++) + accumulatedAnnotations.add(runtimeAnnotations.getAnnotationEntries()[j]); + } + } + annotations = (AnnotationEntry[])accumulatedAnnotations.toArray(new AnnotationEntry[accumulatedAnnotations.size()]); + annotationsOutOfDate = false; + } + return annotations; + } + /** + * @return Class name. + */ + public String getClassName() { + return class_name; + } + + + /** + * @return Package name. + */ + public String getPackageName() { + return package_name; + } + + + /** + * @return Class name index. + */ + public int getClassNameIndex() { + return class_name_index; + } + + + /** + * @return Constant pool. + */ + public ConstantPool getConstantPool() { + return constant_pool; + } + + + /** + * @return Fields, i.e., variables of the class. Like the JVM spec + * mandates for the classfile format, these fields are those specific to + * this class, and not those of the superclass or superinterfaces. + */ + public Field[] getFields() { + return fields; + } + + + /** + * @return File name of class, aka SourceFile attribute value + */ + public String getFileName() { + return file_name; + } + + + /** + * @return Names of implemented interfaces. + */ + public String[] getInterfaceNames() { + return interface_names; + } + + + /** + * @return Indices in constant pool of implemented interfaces. + */ + public int[] getInterfaceIndices() { + return interfaces; + } + + + /** + * @return Major number of class file version. + */ + public int getMajor() { + return major; + } + + + /** + * @return Methods of the class. + */ + public Method[] getMethods() { + return methods; + } + + + /** + * @return A org.apache.tomcat.util.bcel.classfile.Method corresponding to + * java.lang.reflect.Method if any + */ + public Method getMethod( java.lang.reflect.Method m ) { + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers()) + && Type.getSignature(m).equals(method.getSignature())) { + return method; + } + } + return null; + } + + + /** + * @return Minor number of class file version. + */ + public int getMinor() { + return minor; + } + + + /** + * @return sbsolute path to file where this class was read from + */ + public String getSourceFileName() { + return source_file_name; + } + + + /** + * @return Superclass name. + */ + public String getSuperclassName() { + return superclass_name; + } + + + /** + * @return Class name index. + */ + public int getSuperclassNameIndex() { + return superclass_name_index; + } + + static { + // Debugging ... on/off + debug = Boolean.getBoolean("JavaClass.debug"); + // Get path separator either / or \ usually + String _sep = System.getProperty("file.separator"); + if (_sep != null) { + try { + JavaClass.sep = _sep.charAt(0); + } catch (StringIndexOutOfBoundsException e) { + } // Never reached + } + } + + + /** + * @param attributes . + */ + public void setAttributes( Attribute[] attributes ) { + this.attributes = attributes; + } + + + /** + * @param class_name . + */ + public void setClassName( String class_name ) { + this.class_name = class_name; + } + + + /** + * @param class_name_index . + */ + public void setClassNameIndex( int class_name_index ) { + this.class_name_index = class_name_index; + } + + + /** + * @param constant_pool . + */ + public void setConstantPool( ConstantPool constant_pool ) { + this.constant_pool = constant_pool; + } + + + /** + * @param fields . + */ + public void setFields( Field[] fields ) { + this.fields = fields; + } + + + /** + * Set File name of class, aka SourceFile attribute value + */ + public void setFileName( String file_name ) { + this.file_name = file_name; + } + + + /** + * @param interface_names . + */ + public void setInterfaceNames( String[] interface_names ) { + this.interface_names = interface_names; + } + + + /** + * @param interfaces . + */ + public void setInterfaces( int[] interfaces ) { + this.interfaces = interfaces; + } + + + /** + * @param major . + */ + public void setMajor( int major ) { + this.major = major; + } + + + /** + * @param methods . + */ + public void setMethods( Method[] methods ) { + this.methods = methods; + } + + + /** + * @param minor . + */ + public void setMinor( int minor ) { + this.minor = minor; + } + + + /** + * Set absolute path to file this class was read from. + */ + public void setSourceFileName( String source_file_name ) { + this.source_file_name = source_file_name; + } + + + /** + * @param superclass_name . + */ + public void setSuperclassName( String superclass_name ) { + this.superclass_name = superclass_name; + } + + + /** + * @param superclass_name_index . + */ + public void setSuperclassNameIndex( int superclass_name_index ) { + this.superclass_name_index = superclass_name_index; + } + + + /** + * @return String representing class contents. + */ + public String toString() { + String access = Utility.accessToString(access_flags, true); + access = access.equals("") ? "" : (access + " "); + StringBuffer buf = new StringBuffer(128); + buf.append(access).append(Utility.classOrInterface(access_flags)).append(" ").append( + class_name).append(" extends ").append( + Utility.compactClassName(superclass_name, false)).append('\n'); + int size = interfaces.length; + if (size > 0) { + buf.append("implements\t\t"); + for (int i = 0; i < size; i++) { + buf.append(interface_names[i]); + if (i < size - 1) { + buf.append(", "); + } + } + buf.append('\n'); + } + buf.append("filename\t\t").append(file_name).append('\n'); + buf.append("compiled from\t\t").append(source_file_name).append('\n'); + buf.append("compiler version\t").append(major).append(".").append(minor).append('\n'); + buf.append("access flags\t\t").append(access_flags).append('\n'); + buf.append("constant pool\t\t").append(constant_pool.getLength()).append(" entries\n"); + buf.append("ACC_SUPER flag\t\t").append(isSuper()).append("\n"); + if (attributes.length > 0) { + buf.append("\nAttribute(s):\n"); + for (int i = 0; i < attributes.length; i++) { + buf.append(indent(attributes[i])); + } + } + AnnotationEntry[] annotations = getAnnotationEntries(); + if (annotations!=null && annotations.length>0) { + buf.append("\nAnnotation(s):\n"); + for (int i=0; i 0) { + buf.append("\n").append(fields.length).append(" fields:\n"); + for (int i = 0; i < fields.length; i++) { + buf.append("\t").append(fields[i]).append('\n'); + } + } + if (methods.length > 0) { + buf.append("\n").append(methods.length).append(" methods:\n"); + for (int i = 0; i < methods.length; i++) { + buf.append("\t").append(methods[i]).append('\n'); + } + } + return buf.toString(); + } + + + private static final String indent( Object obj ) { + StringTokenizer tok = new StringTokenizer(obj.toString(), "\n"); + StringBuffer buf = new StringBuffer(); + while (tok.hasMoreTokens()) { + buf.append("\t").append(tok.nextToken()).append("\n"); + } + return buf.toString(); + } + + + /** + * @return deep copy of this class + */ + public JavaClass copy() { + JavaClass c = null; + try { + c = (JavaClass) clone(); + c.constant_pool = constant_pool.copy(); + c.interfaces = (int[]) interfaces.clone(); + c.interface_names = (String[]) interface_names.clone(); + c.fields = new Field[fields.length]; + for (int i = 0; i < fields.length; i++) { + c.fields[i] = fields[i].copy(c.constant_pool); + } + c.methods = new Method[methods.length]; + for (int i = 0; i < methods.length; i++) { + c.methods[i] = methods[i].copy(c.constant_pool); + } + c.attributes = new Attribute[attributes.length]; + for (int i = 0; i < attributes.length; i++) { + c.attributes[i] = attributes[i].copy(c.constant_pool); + } + } catch (CloneNotSupportedException e) { + } + return c; + } + + + public final boolean isSuper() { + return (access_flags & Constants.ACC_SUPER) != 0; + } + + + public final boolean isClass() { + return (access_flags & Constants.ACC_INTERFACE) == 0; + } + + public final boolean isAnonymous() { + computeNestedTypeStatus(); + return this.isAnonymous; + } + + public final boolean isNested() { + computeNestedTypeStatus(); + return this.isNested; + } + + private final void computeNestedTypeStatus() { + if (computedNestedTypeStatus) return; + for (int i = 0; i < this.attributes.length; i++) { + if (this.attributes[i] instanceof InnerClasses) { + InnerClass[] innerClasses = ((InnerClasses) this.attributes[i]).getInnerClasses(); + for (int j = 0; j < innerClasses.length; j++) { + boolean innerClassAttributeRefersToMe = false; + String inner_class_name = constant_pool.getConstantString(innerClasses[j].getInnerClassIndex(), + Constants.CONSTANT_Class); + inner_class_name = Utility.compactClassName(inner_class_name); + if (inner_class_name.equals(getClassName())) { + innerClassAttributeRefersToMe = true; + } + if (innerClassAttributeRefersToMe) { + this.isNested = true; + if (innerClasses[j].getInnerNameIndex() == 0) { + this.isAnonymous = true; + } + } + } + } + } + this.computedNestedTypeStatus = true; + } + + + /** @return returns either HEAP (generated), FILE, or ZIP + */ + public final byte getSource() { + return source; + } + + + /********************* New repository functionality *********************/ + /** + * Gets the ClassRepository which holds its definition. By default + * this is the same as SyntheticRepository.getInstance(); + */ + public org.apache.tomcat.util.bcel.util.Repository getRepository() { + return repository; + } + + + /** + * Sets the ClassRepository which loaded the JavaClass. + * Should be called immediately after parsing is done. + */ + public void setRepository( org.apache.tomcat.util.bcel.util.Repository repository ) { + this.repository = repository; + } + + + /** Equivalent to runtime "instanceof" operator. + * + * @return true if this JavaClass is derived from the super class + * @throws ClassNotFoundException if superclasses or superinterfaces + * of this object can't be found + */ + public final boolean instanceOf( JavaClass super_class ) throws ClassNotFoundException { + if (this.equals(super_class)) { + return true; + } + JavaClass[] super_classes = getSuperClasses(); + for (int i = 0; i < super_classes.length; i++) { + if (super_classes[i].equals(super_class)) { + return true; + } + } + if (super_class.isInterface()) { + return implementationOf(super_class); + } + return false; + } + + + /** + * @return true, if this class is an implementation of interface inter + * @throws ClassNotFoundException if superclasses or superinterfaces + * of this class can't be found + */ + public boolean implementationOf( JavaClass inter ) throws ClassNotFoundException { + if (!inter.isInterface()) { + throw new IllegalArgumentException(inter.getClassName() + " is no interface"); + } + if (this.equals(inter)) { + return true; + } + JavaClass[] super_interfaces = getAllInterfaces(); + for (int i = 0; i < super_interfaces.length; i++) { + if (super_interfaces[i].equals(inter)) { + return true; + } + } + return false; + } + + + /** + * @return the superclass for this JavaClass object, or null if this + * is java.lang.Object + * @throws ClassNotFoundException if the superclass can't be found + */ + public JavaClass getSuperClass() throws ClassNotFoundException { + if ("java.lang.Object".equals(getClassName())) { + return null; + } + return repository.loadClass(getSuperclassName()); + } + + + /** + * @return list of super classes of this class in ascending order, i.e., + * java.lang.Object is always the last element + * @throws ClassNotFoundException if any of the superclasses can't be found + */ + public JavaClass[] getSuperClasses() throws ClassNotFoundException { + JavaClass clazz = this; + List allSuperClasses = new ArrayList(); + for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { + allSuperClasses.add(clazz); + } + return (JavaClass[]) allSuperClasses.toArray(new JavaClass[allSuperClasses.size()]); + } + + + /** + * Get interfaces directly implemented by this JavaClass. + */ + public JavaClass[] getInterfaces() throws ClassNotFoundException { + String[] _interfaces = getInterfaceNames(); + JavaClass[] classes = new JavaClass[_interfaces.length]; + for (int i = 0; i < _interfaces.length; i++) { + classes[i] = repository.loadClass(_interfaces[i]); + } + return classes; + } + + + /** + * Get all interfaces implemented by this JavaClass (transitively). + */ + public JavaClass[] getAllInterfaces() throws ClassNotFoundException { + ClassQueue queue = new ClassQueue(); + Set allInterfaces = new TreeSet(); + queue.enqueue(this); + while (!queue.empty()) { + JavaClass clazz = queue.dequeue(); + JavaClass souper = clazz.getSuperClass(); + JavaClass[] _interfaces = clazz.getInterfaces(); + if (clazz.isInterface()) { + allInterfaces.add(clazz); + } else { + if (souper != null) { + queue.enqueue(souper); + } + } + for (int i = 0; i < _interfaces.length; i++) { + queue.enqueue(_interfaces[i]); + } + } + return (JavaClass[]) allInterfaces.toArray(new JavaClass[allInterfaces.size()]); + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two JavaClass objects are said to be equal when + * their class names are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return the natural ordering of two JavaClasses. + * This ordering is based on the class name + */ + public int compareTo( Object obj ) { + return getClassName().compareTo(((JavaClass) obj).getClassName()); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the class name. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/LineNumber.java b/java/org/apache/tomcat/util/bcel/classfile/LineNumber.java new file mode 100644 index 000000000..3dfd64e24 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/LineNumber.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +/** + * This class represents a (PC offset, line number) pair, i.e., a line number in + * the source that corresponds to a relative address in the byte code. This + * is used for debugging purposes. + * + * @version $Id$ + * @author M. Dahm + * @see LineNumberTable + */ +public final class LineNumber implements Cloneable, Node, Serializable { + + private int start_pc; // Program Counter (PC) corresponds to line + private int line_number; // number in source file + + + /** + * Initialize from another object. + */ + public LineNumber(LineNumber c) { + this(c.getStartPC(), c.getLineNumber()); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + LineNumber(DataInput file) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort()); + } + + + /** + * @param start_pc Program Counter (PC) corresponds to + * @param line_number line number in source file + */ + public LineNumber(int start_pc, int line_number) { + this.start_pc = start_pc; + this.line_number = line_number; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLineNumber(this); + } + + + /** + * Dump line number/pc pair to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(start_pc); + file.writeShort(line_number); + } + + + /** + * @return Corresponding source line + */ + public final int getLineNumber() { + return line_number; + } + + + /** + * @return PC in code + */ + public final int getStartPC() { + return start_pc; + } + + + /** + * @param line_number the source line number + */ + public final void setLineNumber( int line_number ) { + this.line_number = line_number; + } + + + /** + * @param start_pc the pc for this line number + */ + public final void setStartPC( int start_pc ) { + this.start_pc = start_pc; + } + + + /** + * @return String representation + */ + public final String toString() { + return "LineNumber(" + start_pc + ", " + line_number + ")"; + } + + + /** + * @return deep copy of this object + */ + public LineNumber copy() { + try { + return (LineNumber) clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/LineNumberTable.java b/java/org/apache/tomcat/util/bcel/classfile/LineNumberTable.java new file mode 100644 index 000000000..d0cdedf64 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/LineNumberTable.java @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a table of line numbers for debugging + * purposes. This attribute is used by the Code attribute. It + * contains pairs of PCs and line numbers. + * + * @version $Id$ + * @author M. Dahm + * @see Code + * @see LineNumber + */ +public final class LineNumberTable extends Attribute { + + private int line_number_table_length; + private LineNumber[] line_number_table; // Table of line/numbers pairs + + + /* + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public LineNumberTable(LineNumberTable c) { + this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool()); + } + + + /* + * @param name_index Index of name + * @param length Content length in bytes + * @param line_number_table Table of line/numbers pairs + * @param constant_pool Array of constants + */ + public LineNumberTable(int name_index, int length, LineNumber[] line_number_table, + ConstantPool constant_pool) { + super(Constants.ATTR_LINE_NUMBER_TABLE, name_index, length, constant_pool); + setLineNumberTable(line_number_table); + } + + + /** + * Construct object from file stream. + * @param name_index Index of name + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + LineNumberTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (LineNumber[]) null, constant_pool); + line_number_table_length = (file.readUnsignedShort()); + line_number_table = new LineNumber[line_number_table_length]; + for (int i = 0; i < line_number_table_length; i++) { + line_number_table[i] = new LineNumber(file); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLineNumberTable(this); + } + + + /** + * Dump line number table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(line_number_table_length); + for (int i = 0; i < line_number_table_length; i++) { + line_number_table[i].dump(file); + } + } + + + /** + * @return Array of (pc offset, line number) pairs. + */ + public final LineNumber[] getLineNumberTable() { + return line_number_table; + } + + + /** + * @param line_number_table the line number entries for this table + */ + public final void setLineNumberTable( LineNumber[] line_number_table ) { + this.line_number_table = line_number_table; + line_number_table_length = (line_number_table == null) ? 0 : line_number_table.length; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(); + StringBuffer line = new StringBuffer(); + String newLine = System.getProperty("line.separator", "\n"); + for (int i = 0; i < line_number_table_length; i++) { + line.append(line_number_table[i].toString()); + if (i < line_number_table_length - 1) { + line.append(", "); + } + if (line.length() > 72) { + line.append(newLine); + buf.append(line.toString()); + line.setLength(0); + } + } + buf.append(line); + return buf.toString(); + } + + + /** + * Map byte code positions to source code lines. + * + * @param pos byte code offset + * @return corresponding line in source code + */ + public int getSourceLine( int pos ) { + int l = 0, r = line_number_table_length - 1; + if (r < 0) { + return -1; + } + int min_index = -1, min = -1; + /* Do a binary search since the array is ordered. + */ + do { + int i = (l + r) / 2; + int j = line_number_table[i].getStartPC(); + if (j == pos) { + return line_number_table[i].getLineNumber(); + } else if (pos < j) { + r = i - 1; + } else { + l = i + 1; + } + /* If exact match can't be found (which is the most common case) + * return the line number that corresponds to the greatest index less + * than pos. + */ + if (j < pos && j > min) { + min = j; + min_index = i; + } + } while (l <= r); + /* It's possible that we did not find any valid entry for the bytecode + * offset we were looking for. + */ + if (min_index < 0) { + return -1; + } + return line_number_table[min_index].getLineNumber(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + LineNumberTable c = (LineNumberTable) clone(); + c.line_number_table = new LineNumber[line_number_table_length]; + for (int i = 0; i < line_number_table_length; i++) { + c.line_number_table[i] = line_number_table[i].copy(); + } + c.constant_pool = _constant_pool; + return c; + } + + + public final int getTableLength() { + return line_number_table_length; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/LocalVariable.java b/java/org/apache/tomcat/util/bcel/classfile/LocalVariable.java new file mode 100644 index 000000000..45f5f005f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/LocalVariable.java @@ -0,0 +1,249 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a local variable within a method. It contains its + * scope, name, signature and index on the method's frame. + * + * @version $Id$ + * @author M. Dahm + * @see LocalVariableTable + */ +public final class LocalVariable implements Constants, Cloneable, Node, Serializable { + + private int start_pc; // Range in which the variable is valid + private int length; + private int name_index; // Index in constant pool of variable name + private int signature_index; // Index of variable signature + private int index; /* Variable is `index'th local variable on + * this method's frame. + */ + private ConstantPool constant_pool; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public LocalVariable(LocalVariable c) { + this(c.getStartPC(), c.getLength(), c.getNameIndex(), c.getSignatureIndex(), c.getIndex(), + c.getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + LocalVariable(DataInput file, ConstantPool constant_pool) throws IOException { + this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file + .readUnsignedShort(), file.readUnsignedShort(), constant_pool); + } + + + /** + * @param start_pc Range in which the variable + * @param length ... is valid + * @param name_index Index in constant pool of variable name + * @param signature_index Index of variable's signature + * @param index Variable is `index'th local variable on the method's frame + * @param constant_pool Array of constants + */ + public LocalVariable(int start_pc, int length, int name_index, int signature_index, int index, + ConstantPool constant_pool) { + this.start_pc = start_pc; + this.length = length; + this.name_index = name_index; + this.signature_index = signature_index; + this.index = index; + this.constant_pool = constant_pool; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLocalVariable(this); + } + + + /** + * Dump local variable to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(start_pc); + file.writeShort(length); + file.writeShort(name_index); + file.writeShort(signature_index); + file.writeShort(index); + } + + + /** + * @return Constant pool used by this object. + */ + public final ConstantPool getConstantPool() { + return constant_pool; + } + + + /** + * @return Variable is valid within getStartPC() .. getStartPC()+getLength() + */ + public final int getLength() { + return length; + } + + + /** + * @return Variable name. + */ + public final String getName() { + ConstantUtf8 c; + c = (ConstantUtf8) constant_pool.getConstant(name_index, CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return Index in constant pool of variable name. + */ + public final int getNameIndex() { + return name_index; + } + + + /** + * @return Signature. + */ + public final String getSignature() { + ConstantUtf8 c; + c = (ConstantUtf8) constant_pool.getConstant(signature_index, CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return Index in constant pool of variable signature. + */ + public final int getSignatureIndex() { + return signature_index; + } + + + /** + * @return index of register where variable is stored + */ + public final int getIndex() { + return index; + } + + + /** + * @return Start of range where he variable is valid + */ + public final int getStartPC() { + return start_pc; + } + + + /** + * @param constant_pool Constant pool to be used for this object. + */ + public final void setConstantPool( ConstantPool constant_pool ) { + this.constant_pool = constant_pool; + } + + + /** + * @param length the length of this local variable + */ + public final void setLength( int length ) { + this.length = length; + } + + + /** + * @param name_index the index into the constant pool for the name of this variable + */ + public final void setNameIndex( int name_index ) { + this.name_index = name_index; + } + + + /** + * @param signature_index the index into the constant pool for the signature of this variable + */ + public final void setSignatureIndex( int signature_index ) { + this.signature_index = signature_index; + } + + + /** + * @param index the index in the local variable table of this variable + */ + public final void setIndex( int index ) { + this.index = index; + } + + + /** + * @param start_pc Specify range where the local variable is valid. + */ + public final void setStartPC( int start_pc ) { + this.start_pc = start_pc; + } + + + /** + * @return string representation. + */ + public final String toString() { + String name = getName(), signature = Utility.signatureToString(getSignature()); + return "LocalVariable(start_pc = " + start_pc + ", length = " + length + ", index = " + + index + ":" + signature + " " + name + ")"; + } + + + /** + * @return deep copy of this object + */ + public LocalVariable copy() { + try { + return (LocalVariable) clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTable.java b/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTable.java new file mode 100644 index 000000000..c6994574a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTable.java @@ -0,0 +1,197 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents colection of local variables in a + * method. This attribute is contained in the Code attribute. + * + * @version $Id$ + * @author M. Dahm + * @see Code + * @see LocalVariable + */ +public class LocalVariableTable extends Attribute { + + private int local_variable_table_length; // Table of local + private LocalVariable[] local_variable_table; // variables + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public LocalVariableTable(LocalVariableTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool()); + } + + + /** + * @param name_index Index in constant pool to `LocalVariableTable' + * @param length Content length in bytes + * @param local_variable_table Table of local variables + * @param constant_pool Array of constants + */ + public LocalVariableTable(int name_index, int length, LocalVariable[] local_variable_table, + ConstantPool constant_pool) { + super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool); + setLocalVariableTable(local_variable_table); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (LocalVariable[]) null, constant_pool); + local_variable_table_length = (file.readUnsignedShort()); + local_variable_table = new LocalVariable[local_variable_table_length]; + for (int i = 0; i < local_variable_table_length; i++) { + local_variable_table[i] = new LocalVariable(file, constant_pool); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLocalVariableTable(this); + } + + + /** + * Dump local variable table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(local_variable_table_length); + for (int i = 0; i < local_variable_table_length; i++) { + local_variable_table[i].dump(file); + } + } + + + /** + * @return Array of local variables of method. + */ + public final LocalVariable[] getLocalVariableTable() { + return local_variable_table; + } + + + /** + * @return first matching variable using index + * + * @param index the variable slot + * + * @return the first LocalVariable that matches the slot or null if not found + * + * @deprecated since 5.2 because multiple variables can share the + * same slot, use getLocalVariable(int index, int pc) instead. + */ + public final LocalVariable getLocalVariable( int index ) { + for (int i = 0; i < local_variable_table_length; i++) { + if (local_variable_table[i].getIndex() == index) { + return local_variable_table[i]; + } + } + return null; + } + + + /** + * @return matching variable using index when variable is used at supplied pc + * + * @param index the variable slot + * @param pc the current pc that this variable is alive + * + * @return the LocalVariable that matches or null if not found + */ + public final LocalVariable getLocalVariable( int index, int pc ) { + for (int i = 0; i < local_variable_table_length; i++) { + if (local_variable_table[i].getIndex() == index) { + int start_pc = local_variable_table[i].getStartPC(); + int end_pc = start_pc + local_variable_table[i].getLength(); + if ((pc >= start_pc) && (pc <= end_pc)) { + return local_variable_table[i]; + } + } + } + return null; + } + + + public final void setLocalVariableTable( LocalVariable[] local_variable_table ) { + this.local_variable_table = local_variable_table; + local_variable_table_length = (local_variable_table == null) + ? 0 + : local_variable_table.length; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < local_variable_table_length; i++) { + buf.append(local_variable_table[i].toString()); + if (i < local_variable_table_length - 1) { + buf.append('\n'); + } + } + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + LocalVariableTable c = (LocalVariableTable) clone(); + c.local_variable_table = new LocalVariable[local_variable_table_length]; + for (int i = 0; i < local_variable_table_length; i++) { + c.local_variable_table[i] = local_variable_table[i].copy(); + } + c.constant_pool = _constant_pool; + return c; + } + + + public final int getTableLength() { + return local_variable_table_length; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTypeTable.java b/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTypeTable.java new file mode 100755 index 000000000..eed0b5426 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/LocalVariableTypeTable.java @@ -0,0 +1,135 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation + * + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Common Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * Andy Clement initial implementation + * Heavily based on LocalVariableTable + * ******************************************************************/ +package org.apache.tomcat.util.bcel.classfile; + + +import org.apache.tomcat.util.bcel.Constants; +import java.io.*; + +// The new table is used when generic types are about... + +//LocalVariableTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_table_length; +// { u2 start_pc; +// u2 length; +// u2 name_index; +// u2 descriptor_index; +// u2 index; +// } local_variable_table[local_variable_table_length]; +// } + +//LocalVariableTypeTable_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 local_variable_type_table_length; +// { +// u2 start_pc; +// u2 length; +// u2 name_index; +// u2 signature_index; +// u2 index; +// } local_variable_type_table[local_variable_type_table_length]; +// } +// J5TODO: Needs some testing ! +public class LocalVariableTypeTable extends Attribute { + private int local_variable_type_table_length; // Table of local + private LocalVariable[] local_variable_type_table; // variables + + public LocalVariableTypeTable(LocalVariableTypeTable c) { + this(c.getNameIndex(), c.getLength(), c.getLocalVariableTypeTable(), + c.getConstantPool()); + } + + public LocalVariableTypeTable(int name_index, int length, + LocalVariable[] local_variable_table, + ConstantPool constant_pool) + { + super(Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE, name_index, length, constant_pool); + setLocalVariableTable(local_variable_table); + } + + LocalVariableTypeTable(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { + this(nameIdx, len, (LocalVariable[])null, cpool); + + local_variable_type_table_length = (dis.readUnsignedShort()); + local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i] = new LocalVariable(dis, cpool); + } + + public void accept(Visitor v) { + v.visitLocalVariableTypeTable(this); + } + + public final void dump(DataOutputStream file) throws IOException + { + super.dump(file); + file.writeShort(local_variable_type_table_length); + for(int i=0; i < local_variable_type_table_length; i++) + local_variable_type_table[i].dump(file); + } + + public final LocalVariable[] getLocalVariableTypeTable() { + return local_variable_type_table; + } + + public final LocalVariable getLocalVariable(int index) { + for(int i=0; i < local_variable_type_table_length; i++) + if(local_variable_type_table[i].getIndex() == index) + return local_variable_type_table[i]; + + return null; + } + + public final void setLocalVariableTable(LocalVariable[] local_variable_table) + { + this.local_variable_type_table = local_variable_table; + local_variable_type_table_length = (local_variable_table == null)? 0 : + local_variable_table.length; + } + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(); + + for(int i=0; i < local_variable_type_table_length; i++) { + buf.append(local_variable_type_table[i].toString()); + + if(i < local_variable_type_table_length - 1) buf.append('\n'); + } + + return buf.toString(); + } + + /** + * @return deep copy of this attribute + */ + public Attribute copy(ConstantPool constant_pool) { + LocalVariableTypeTable c = (LocalVariableTypeTable)clone(); + + c.local_variable_type_table = new LocalVariable[local_variable_type_table_length]; + for(int i=0; i < local_variable_type_table_length; i++) + c.local_variable_type_table[i] = local_variable_type_table[i].copy(); + + c.constant_pool = constant_pool; + return c; + } + + public final int getTableLength() { return local_variable_type_table_length; } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Method.java b/java/org/apache/tomcat/util/bcel/classfile/Method.java new file mode 100644 index 000000000..91e434187 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Method.java @@ -0,0 +1,254 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.generic.Type; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * This class represents the method info structure, i.e., the representation + * for a method in the class. See JVM specification for details. + * A method has access flags, a name, a signature and a number of attributes. + * + * @version $Id$ + * @author M. Dahm + */ +public final class Method extends FieldOrMethod { + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + Method THIS = (Method) o1; + Method THAT = (Method) o2; + return THIS.getName().equals(THAT.getName()) + && THIS.getSignature().equals(THAT.getSignature()); + } + + + public int hashCode( Object o ) { + Method THIS = (Method) o; + return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + } + }; + + + /** + * Empty constructor, all attributes have to be defined via `setXXX' + * methods. Use at your own risk. + */ + public Method() { + } + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public Method(Method c) { + super(c); + } + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + * @throws ClassFormatException + */ + Method(DataInputStream file, ConstantPool constant_pool) throws IOException, + ClassFormatException { + super(file, constant_pool); + } + + + /** + * @param access_flags Access rights of method + * @param name_index Points to field name in constant pool + * @param signature_index Points to encoded signature + * @param attributes Collection of attributes + * @param constant_pool Array of constants + */ + public Method(int access_flags, int name_index, int signature_index, Attribute[] attributes, + ConstantPool constant_pool) { + super(access_flags, name_index, signature_index, attributes, constant_pool); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitMethod(this); + } + + + /** + * @return Code attribute of method, if any + */ + public final Code getCode() { + for (int i = 0; i < attributes_count; i++) { + if (attributes[i] instanceof Code) { + return (Code) attributes[i]; + } + } + return null; + } + + + /** + * @return ExceptionTable attribute of method, if any, i.e., list all + * exceptions the method may throw not exception handlers! + */ + public final ExceptionTable getExceptionTable() { + for (int i = 0; i < attributes_count; i++) { + if (attributes[i] instanceof ExceptionTable) { + return (ExceptionTable) attributes[i]; + } + } + return null; + } + + + /** @return LocalVariableTable of code attribute if any, i.e. the call is forwarded + * to the Code atribute. + */ + public final LocalVariableTable getLocalVariableTable() { + Code code = getCode(); + if (code == null) { + return null; + } + return code.getLocalVariableTable(); + } + + + /** @return LineNumberTable of code attribute if any, i.e. the call is forwarded + * to the Code atribute. + */ + public final LineNumberTable getLineNumberTable() { + Code code = getCode(); + if (code == null) { + return null; + } + return code.getLineNumberTable(); + } + + + /** + * Return string representation close to declaration format, + * `public static void main(String[] args) throws IOException', e.g. + * + * @return String representation of the method. + */ + public final String toString() { + ConstantUtf8 c; + String name, signature, access; // Short cuts to constant pool + StringBuffer buf; + access = Utility.accessToString(access_flags); + // Get name and signature from constant pool + c = (ConstantUtf8) constant_pool.getConstant(signature_index, Constants.CONSTANT_Utf8); + signature = c.getBytes(); + c = (ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8); + name = c.getBytes(); + signature = Utility.methodSignatureToString(signature, name, access, true, + getLocalVariableTable()); + buf = new StringBuffer(signature); + for (int i = 0; i < attributes_count; i++) { + Attribute a = attributes[i]; + if (!((a instanceof Code) || (a instanceof ExceptionTable))) { + buf.append(" [").append(a.toString()).append("]"); + } + } + ExceptionTable e = getExceptionTable(); + if (e != null) { + String str = e.toString(); + if (!str.equals("")) { + buf.append("\n\t\tthrows ").append(str); + } + } + return buf.toString(); + } + + + /** + * @return deep copy of this method + */ + public final Method copy( ConstantPool _constant_pool ) { + return (Method) copy_(_constant_pool); + } + + + /** + * @return return type of method + */ + public Type getReturnType() { + return Type.getReturnType(getSignature()); + } + + + /** + * @return array of method argument types + */ + public Type[] getArgumentTypes() { + return Type.getArgumentTypes(getSignature()); + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two method objects are said to be equal when + * their names and signatures are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the method's name XOR signature. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Node.java b/java/org/apache/tomcat/util/bcel/classfile/Node.java new file mode 100644 index 000000000..83e63d4ef --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Node.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * Denote class to have an accept method(); + * + * @version $Id$ + * @author M. Dahm + */ +public interface Node { + + public void accept( Visitor obj ); +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/PMGClass.java b/java/org/apache/tomcat/util/bcel/classfile/PMGClass.java new file mode 100644 index 000000000..f104eea9b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/PMGClass.java @@ -0,0 +1,168 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute and represents a reference + * to a PMG attribute. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class PMGClass extends Attribute { + + private int pmg_class_index, pmg_index; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public PMGClass(PMGClass c) { + this(c.getNameIndex(), c.getLength(), c.getPMGIndex(), c.getPMGClassIndex(), c + .getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + PMGClass(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), constant_pool); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param pmg_index index in constant pool for source file name + * @param pmg_class_index Index in constant pool to CONSTANT_Utf8 + * @param constant_pool Array of constants + */ + public PMGClass(int name_index, int length, int pmg_index, int pmg_class_index, + ConstantPool constant_pool) { + super(Constants.ATTR_PMG, name_index, length, constant_pool); + this.pmg_index = pmg_index; + this.pmg_class_index = pmg_class_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + System.err.println("Visiting non-standard PMGClass object"); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(pmg_index); + file.writeShort(pmg_class_index); + } + + + /** + * @return Index in constant pool of source file name. + */ + public final int getPMGClassIndex() { + return pmg_class_index; + } + + + /** + * @param pmg_class_index + */ + public final void setPMGClassIndex( int pmg_class_index ) { + this.pmg_class_index = pmg_class_index; + } + + + /** + * @return Index in constant pool of source file name. + */ + public final int getPMGIndex() { + return pmg_index; + } + + + /** + * @param pmg_index + */ + public final void setPMGIndex( int pmg_index ) { + this.pmg_index = pmg_index; + } + + + /** + * @return PMG name. + */ + public final String getPMGName() { + ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(pmg_index, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return PMG class name. + */ + public final String getPMGClassName() { + ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(pmg_class_index, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return String representation + */ + public final String toString() { + return "PMGClass(" + getPMGName() + ", " + getPMGClassName() + ")"; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + return (PMGClass) clone(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotationEntry.java b/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotationEntry.java new file mode 100644 index 000000000..5005587e3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotationEntry.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents one parameter annotation in the parameter annotation table + * + * @version $Id: ParameterAnnotationEntry + * @author D. Brosius + * @since 5.3 + */ +public class ParameterAnnotationEntry implements Node, Constants { + + private int annotation_table_length; + private AnnotationEntry[] annotation_table; + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + ParameterAnnotationEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { + annotation_table_length = (file.readUnsignedShort()); + annotation_table = new AnnotationEntry[annotation_table_length]; + for (int i = 0; i < annotation_table_length; i++) { +// TODO isRuntimeVisible + annotation_table[i] = AnnotationEntry.read(file, constant_pool, false); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + // v.visitParameterAnnotationEntry(this); + } + + + /** + * @return the number of annotation entries in this parameter annotation + */ + public final int getNumAnnotations() { + return annotation_table_length; + } + + + /** + * returns the array of annotation entries in this annotation + */ + public AnnotationEntry[] getAnnotationEntries() { + return annotation_table; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotations.java b/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotations.java new file mode 100644 index 000000000..abfb5930d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/ParameterAnnotations.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * base class for parameter annotations + * + * @version $Id: ParameterAnnotations + * @author D. Brosius + * @since 5.3 + */ +public abstract class ParameterAnnotations extends Attribute { + + private int num_parameters; + private ParameterAnnotationEntry[] parameter_annotation_table; // Table of parameter annotations + + + /** + * @param parameter_annotation_type the subclass type of the parameter annotation + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + */ + ParameterAnnotations(byte parameter_annotation_type, int name_index, int length, + DataInputStream file, ConstantPool constant_pool) throws IOException { + this(parameter_annotation_type, name_index, length, (ParameterAnnotationEntry[]) null, + constant_pool); + num_parameters = (file.readUnsignedByte()); + parameter_annotation_table = new ParameterAnnotationEntry[num_parameters]; + for (int i = 0; i < num_parameters; i++) { + parameter_annotation_table[i] = new ParameterAnnotationEntry(file, constant_pool); + } + } + + + /** + * @param parameter_annotation_type the subclass type of the parameter annotation + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param parameter_annotation_table the actual parameter annotations + * @param constant_pool Array of constants + */ + public ParameterAnnotations(byte parameter_annotation_type, int name_index, int length, + ParameterAnnotationEntry[] parameter_annotation_table, ConstantPool constant_pool) { + super(parameter_annotation_type, name_index, length, constant_pool); + setParameterAnnotationTable(parameter_annotation_table); + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + // v.visitParameterAnnotation(this); + } + + + /** + * @param parameter_annotation_table the entries to set in this parameter annotation + */ + public final void setParameterAnnotationTable( + ParameterAnnotationEntry[] parameter_annotation_table ) { + this.parameter_annotation_table = parameter_annotation_table; + num_parameters = (parameter_annotation_table == null) + ? 0 + : parameter_annotation_table.length; + } + + + /** + * @return the parameter annotation entry table + */ + public final ParameterAnnotationEntry[] getParameterAnnotationTable() { + return parameter_annotation_table; + } + + + /** + * returns the array of parameter annotation entries in this parameter annotation + */ + public ParameterAnnotationEntry[] getParameterAnnotationEntries() { + return parameter_annotation_table; + } + + + /** + * @return the number of parameter annotation entries in this parameter annotation + */ + public final int getNumParameterAnnotation() { + return num_parameters; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleAnnotations.java b/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleAnnotations.java new file mode 100644 index 000000000..9a57021da --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleAnnotations.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents an annotation that is represented in the class file but is not + * provided to the JVM. + * + * @version $Id: RuntimeInvisibleAnnotations + * @author D. Brosius + * @since 5.3 + */ +public class RuntimeInvisibleAnnotations extends Annotations +{ + /** + * @param name_index + * Index pointing to the name Code + * @param length + * Content length in bytes + * @param file + * Input stream + * @param constant_pool + * Array of constants + */ + RuntimeInvisibleAnnotations(int name_index, int length, + DataInputStream file, ConstantPool constant_pool) + throws IOException + { + super(Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, name_index, length, + file, constant_pool, false); + } + + /** + * @return deep copy of this attribute + */ + public Attribute copy(ConstantPool constant_pool) + { + Annotations c = (Annotations) clone(); + return c; + } + + public final void dump(DataOutputStream dos) throws IOException + { + super.dump(dos); + writeAnnotations(dos); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleParameterAnnotations.java b/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleParameterAnnotations.java new file mode 100644 index 000000000..ef841e4fc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/RuntimeInvisibleParameterAnnotations.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents a parameter annotation that is represented in the class file + * but is not provided to the JVM. + * + * @version $Id: RuntimeInvisibleParameterAnnotations + * @author D. Brosius + * @since 5.3 + */ +public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { + + /** + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + */ + RuntimeInvisibleParameterAnnotations(int name_index, int length, DataInputStream file, + ConstantPool constant_pool) throws IOException { + super(Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, + constant_pool); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool constant_pool ) { + Annotations c = (Annotations) clone(); + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleAnnotations.java b/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleAnnotations.java new file mode 100644 index 000000000..b52c69ac2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleAnnotations.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents an annotation that is represented in the class file and is + * provided to the JVM. + * + * @version $Id: RuntimeVisibleAnnotations + * @author D. Brosius + * @since 5.3 + */ +public class RuntimeVisibleAnnotations extends Annotations +{ + /** + * @param name_index + * Index pointing to the name Code + * @param length + * Content length in bytes + * @param file + * Input stream + * @param constant_pool + * Array of constants + */ + public RuntimeVisibleAnnotations(int name_index, int length, + DataInputStream file, ConstantPool constant_pool) + throws IOException + { + super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length, + file, constant_pool, true); + } + + /** + * @return deep copy of this attribute + */ + public Attribute copy(ConstantPool constant_pool) + { + Annotations c = (Annotations) clone(); + return c; + } + + public final void dump(DataOutputStream dos) throws IOException + { + super.dump(dos); + writeAnnotations(dos); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleParameterAnnotations.java b/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleParameterAnnotations.java new file mode 100644 index 000000000..de22c4bbd --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/RuntimeVisibleParameterAnnotations.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * represents a parameter annotation that is represented in the class file + * and is provided to the JVM. + * + * @version $Id: RuntimeVisibleParameterAnnotations + * @author D. Brosius + * @since 5.3 + */ +public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { + + /** + * @param name_index Index pointing to the name Code + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + */ + RuntimeVisibleParameterAnnotations(int name_index, int length, DataInputStream file, + ConstantPool constant_pool) throws IOException { + super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, + constant_pool); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool constant_pool ) { + Annotations c = (Annotations) clone(); + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Signature.java b/java/org/apache/tomcat/util/bcel/classfile/Signature.java new file mode 100644 index 000000000..9748032fc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Signature.java @@ -0,0 +1,274 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute and represents a reference + * to a GJ attribute. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class Signature extends Attribute { + + private int signature_index; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public Signature(Signature c) { + this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + Signature(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, file.readUnsignedShort(), constant_pool); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param signature_index Index in constant pool to CONSTANT_Utf8 + * @param constant_pool Array of constants + */ + public Signature(int name_index, int length, int signature_index, ConstantPool constant_pool) { + super(Constants.ATTR_SIGNATURE, name_index, length, constant_pool); + this.signature_index = signature_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + //System.err.println("Visiting non-standard Signature object"); + v.visitSignature(this); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(signature_index); + } + + + /** + * @return Index in constant pool of source file name. + */ + public final int getSignatureIndex() { + return signature_index; + } + + + /** + * @param signature_index the index info the constant pool of this signature + */ + public final void setSignatureIndex( int signature_index ) { + this.signature_index = signature_index; + } + + + /** + * @return GJ signature. + */ + public final String getSignature() { + ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(signature_index, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + /** + * Extends ByteArrayInputStream to make 'unreading' chars possible. + */ + private static final class MyByteArrayInputStream extends ByteArrayInputStream { + + MyByteArrayInputStream(String data) { + super(data.getBytes()); + } + + + final int mark() { + return pos; + } + + + final String getData() { + return new String(buf); + } + + + final void reset( int p ) { + pos = p; + } + + + final void unread() { + if (pos > 0) { + pos--; + } + } + } + + + private static boolean identStart( int ch ) { + return ch == 'T' || ch == 'L'; + } + + + private static final void matchIdent( MyByteArrayInputStream in, StringBuffer buf ) { + int ch; + if ((ch = in.read()) == -1) { + throw new RuntimeException("Illegal signature: " + in.getData() + + " no ident, reaching EOF"); + } + //System.out.println("return from ident:" + (char)ch); + if (!identStart(ch)) { + StringBuffer buf2 = new StringBuffer(); + int count = 1; + while (Character.isJavaIdentifierPart((char) ch)) { + buf2.append((char) ch); + count++; + ch = in.read(); + } + if (ch == ':') { // Ok, formal parameter + in.skip("Ljava/lang/Object".length()); + buf.append(buf2); + ch = in.read(); + in.unread(); + //System.out.println("so far:" + buf2 + ":next:" +(char)ch); + } else { + for (int i = 0; i < count; i++) { + in.unread(); + } + } + return; + } + StringBuffer buf2 = new StringBuffer(); + ch = in.read(); + do { + buf2.append((char) ch); + ch = in.read(); + //System.out.println("within ident:"+ (char)ch); + } while ((ch != -1) && (Character.isJavaIdentifierPart((char) ch) || (ch == '/'))); + buf.append(buf2.toString().replace('/', '.')); + //System.out.println("regular return ident:"+ (char)ch + ":" + buf2); + if (ch != -1) { + in.unread(); + } + } + + + private static final void matchGJIdent( MyByteArrayInputStream in, StringBuffer buf ) { + int ch; + matchIdent(in, buf); + ch = in.read(); + if ((ch == '<') || ch == '(') { // Parameterized or method + //System.out.println("Enter <"); + buf.append((char) ch); + matchGJIdent(in, buf); + while (((ch = in.read()) != '>') && (ch != ')')) { // List of parameters + if (ch == -1) { + throw new RuntimeException("Illegal signature: " + in.getData() + + " reaching EOF"); + } + //System.out.println("Still no >"); + buf.append(", "); + in.unread(); + matchGJIdent(in, buf); // Recursive call + } + //System.out.println("Exit >"); + buf.append((char) ch); + } else { + in.unread(); + } + ch = in.read(); + if (identStart(ch)) { + in.unread(); + matchGJIdent(in, buf); + } else if (ch == ')') { + in.unread(); + return; + } else if (ch != ';') { + throw new RuntimeException("Illegal signature: " + in.getData() + " read " + (char) ch); + } + } + + + public static String translate( String s ) { + //System.out.println("Sig:" + s); + StringBuffer buf = new StringBuffer(); + matchGJIdent(new MyByteArrayInputStream(s), buf); + return buf.toString(); + } + + + public static final boolean isFormalParameterList( String s ) { + return s.startsWith("<") && (s.indexOf(':') > 0); + } + + + public static final boolean isActualParameterList( String s ) { + return s.startsWith("L") && s.endsWith(">;"); + } + + + /** + * @return String representation + */ + public final String toString() { + String s = getSignature(); + return "Signature(" + s + ")"; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + return (Signature) clone(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/SimpleElementValue.java b/java/org/apache/tomcat/util/bcel/classfile/SimpleElementValue.java new file mode 100644 index 000000000..8373feecd --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/SimpleElementValue.java @@ -0,0 +1,209 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +public class SimpleElementValue extends ElementValue +{ + private int index; + + public SimpleElementValue(int type, int index, ConstantPool cpool) + { + super(type, cpool); + this.index = index; + } + + /** + * @return Value entry index in the cpool + */ + public int getIndex() + { + return index; + } + + public void setIndex(int index) + { + this.index = index; + } + + public String getValueString() + { + if (type != STRING) + throw new RuntimeException( + "Dont call getValueString() on a non STRING ElementValue"); + ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(getIndex(), + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + public int getValueInt() + { + if (type != PRIMITIVE_INT) + throw new RuntimeException( + "Dont call getValueString() on a non STRING ElementValue"); + ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return c.getBytes(); + } + + public byte getValueByte() + { + if (type != PRIMITIVE_BYTE) + throw new RuntimeException( + "Dont call getValueByte() on a non BYTE ElementValue"); + ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return (byte) c.getBytes(); + } + + public char getValueChar() + { + if (type != PRIMITIVE_CHAR) + throw new RuntimeException( + "Dont call getValueChar() on a non CHAR ElementValue"); + ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return (char) c.getBytes(); + } + + public long getValueLong() + { + if (type != PRIMITIVE_LONG) + throw new RuntimeException( + "Dont call getValueLong() on a non LONG ElementValue"); + ConstantLong j = (ConstantLong) cpool.getConstant(getIndex()); + return j.getBytes(); + } + + public float getValueFloat() + { + if (type != PRIMITIVE_FLOAT) + throw new RuntimeException( + "Dont call getValueFloat() on a non FLOAT ElementValue"); + ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex()); + return f.getBytes(); + } + + public double getValueDouble() + { + if (type != PRIMITIVE_DOUBLE) + throw new RuntimeException( + "Dont call getValueDouble() on a non DOUBLE ElementValue"); + ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex()); + return d.getBytes(); + } + + public boolean getValueBoolean() + { + if (type != PRIMITIVE_BOOLEAN) + throw new RuntimeException( + "Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + ConstantInteger bo = (ConstantInteger) cpool.getConstant(getIndex()); + return (bo.getBytes() != 0); + } + + public short getValueShort() + { + if (type != PRIMITIVE_SHORT) + throw new RuntimeException( + "Dont call getValueShort() on a non SHORT ElementValue"); + ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex()); + return (short) s.getBytes(); + } + + public String toString() + { + return stringifyValue(); + } + + // Whatever kind of value it is, return it as a string + public String stringifyValue() + { + switch (type) + { + case PRIMITIVE_INT: + ConstantInteger c = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return Integer.toString(c.getBytes()); + case PRIMITIVE_LONG: + ConstantLong j = (ConstantLong) cpool.getConstant(getIndex(), + Constants.CONSTANT_Long); + return Long.toString(j.getBytes()); + case PRIMITIVE_DOUBLE: + ConstantDouble d = (ConstantDouble) cpool.getConstant(getIndex(), + Constants.CONSTANT_Double); + return Double.toString(d.getBytes()); + case PRIMITIVE_FLOAT: + ConstantFloat f = (ConstantFloat) cpool.getConstant(getIndex(), + Constants.CONSTANT_Float); + return Float.toString(f.getBytes()); + case PRIMITIVE_SHORT: + ConstantInteger s = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return Integer.toString(s.getBytes()); + case PRIMITIVE_BYTE: + ConstantInteger b = (ConstantInteger) cpool.getConstant(getIndex(), + Constants.CONSTANT_Integer); + return Integer.toString(b.getBytes()); + case PRIMITIVE_CHAR: + ConstantInteger ch = (ConstantInteger) cpool.getConstant( + getIndex(), Constants.CONSTANT_Integer); + return String.valueOf((char)ch.getBytes()); + case PRIMITIVE_BOOLEAN: + ConstantInteger bo = (ConstantInteger) cpool.getConstant( + getIndex(), Constants.CONSTANT_Integer); + if (bo.getBytes() == 0) + return "false"; + if (bo.getBytes() != 0) + return "true"; + case STRING: + ConstantUtf8 cu8 = (ConstantUtf8) cpool.getConstant(getIndex(), + Constants.CONSTANT_Utf8); + return cu8.getBytes(); + default: + throw new RuntimeException( + "SimpleElementValue class does not know how to stringify type " + + type); + } + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 kind of value + switch (type) + { + case PRIMITIVE_INT: + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_FLOAT: + case PRIMITIVE_LONG: + case PRIMITIVE_BOOLEAN: + case PRIMITIVE_SHORT: + case PRIMITIVE_DOUBLE: + case STRING: + dos.writeShort(getIndex()); + break; + default: + throw new RuntimeException( + "SimpleElementValue doesnt know how to write out type " + + type); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/SourceFile.java b/java/org/apache/tomcat/util/bcel/classfile/SourceFile.java new file mode 100644 index 000000000..61abf40e3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/SourceFile.java @@ -0,0 +1,146 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute 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 Attribute.readAttribute() method. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class SourceFile extends Attribute { + + private int sourcefile_index; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public SourceFile(SourceFile c) { + this(c.getNameIndex(), c.getLength(), c.getSourceFileIndex(), c.getConstantPool()); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + SourceFile(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, file.readUnsignedShort(), constant_pool); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8, which + * should represent the string "SourceFile". + * @param length Content length in bytes, the value should be 2. + * @param constant_pool The constant pool that this attribute is + * associated with. + * @param sourcefile_index Index in constant pool to CONSTANT_Utf8. This + * string will be interpreted as the name of the file from which this + * class was compiled. It will not be interpreted as indicating the name + * of the directory contqining the file or an absolute path; this + * information has to be supplied the consumer of this attribute - in + * many cases, the JVM. + */ + public SourceFile(int name_index, int length, int sourcefile_index, ConstantPool constant_pool) { + super(Constants.ATTR_SOURCE_FILE, name_index, length, constant_pool); + this.sourcefile_index = sourcefile_index; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitSourceFile(this); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(sourcefile_index); + } + + + /** + * @return Index in constant pool of source file name. + */ + public final int getSourceFileIndex() { + return sourcefile_index; + } + + + /** + * @param sourcefile_index + */ + public final void setSourceFileIndex( int sourcefile_index ) { + this.sourcefile_index = sourcefile_index; + } + + + /** + * @return Source file name. + */ + public final String getSourceFileName() { + ConstantUtf8 c = (ConstantUtf8) constant_pool.getConstant(sourcefile_index, + Constants.CONSTANT_Utf8); + return c.getBytes(); + } + + + /** + * @return String representation + */ + public final String toString() { + return "SourceFile(" + getSourceFileName() + ")"; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + return (SourceFile) clone(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/StackMap.java b/java/org/apache/tomcat/util/bcel/classfile/StackMap.java new file mode 100644 index 000000000..75b2e61ac --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/StackMap.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a stack map attribute used for + * preverification of Java classes for the Java 2 Micro Edition + * (J2ME). This attribute is used by the KVM and contained + * within the Code attribute of a method. See CLDC specification + * �5.3.1.2 + * + * @version $Id$ + * @author M. Dahm + * @see Code + * @see StackMapEntry + * @see StackMapType + */ +public final class StackMap extends Attribute implements Node { + + private int map_length; + private StackMapEntry[] map; // Table of stack map entries + + + /* + * @param name_index Index of name + * @param length Content length in bytes + * @param map Table of stack map entries + * @param constant_pool Array of constants + */ + public StackMap(int name_index, int length, StackMapEntry[] map, ConstantPool constant_pool) { + super(Constants.ATTR_STACK_MAP, name_index, length, constant_pool); + setStackMap(map); + } + + + /** + * Construct object from file stream. + * @param name_index Index of name + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + StackMap(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (StackMapEntry[]) null, constant_pool); + map_length = file.readUnsignedShort(); + map = new StackMapEntry[map_length]; + for (int i = 0; i < map_length; i++) { + map[i] = new StackMapEntry(file, constant_pool); + } + } + + + /** + * Dump line number table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(map_length); + for (int i = 0; i < map_length; i++) { + map[i].dump(file); + } + } + + + /** + * @return Array of stack map entries + */ + public final StackMapEntry[] getStackMap() { + return map; + } + + + /** + * @param map Array of stack map entries + */ + public final void setStackMap( StackMapEntry[] map ) { + this.map = map; + map_length = (map == null) ? 0 : map.length; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer("StackMap("); + for (int i = 0; i < map_length; i++) { + buf.append(map[i].toString()); + if (i < map_length - 1) { + buf.append(", "); + } + } + buf.append(')'); + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + StackMap c = (StackMap) clone(); + c.map = new StackMapEntry[map_length]; + for (int i = 0; i < map_length; i++) { + c.map[i] = map[i].copy(); + } + c.constant_pool = _constant_pool; + return c; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackMap(this); + } + + + public final int getMapLength() { + return map_length; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/StackMapEntry.java b/java/org/apache/tomcat/util/bcel/classfile/StackMapEntry.java new file mode 100644 index 000000000..f2df59a39 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/StackMapEntry.java @@ -0,0 +1,212 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * This class represents a stack map entry recording the types of + * local variables and the the of stack items at a given byte code offset. + * See CLDC specification �5.3.1.2 + * + * @version $Id$ + * @author M. Dahm + * @see StackMap + * @see StackMapType + */ +public final class StackMapEntry implements Cloneable { + + private int byte_code_offset; + private int number_of_locals; + private StackMapType[] types_of_locals; + private int number_of_stack_items; + private StackMapType[] types_of_stack_items; + private ConstantPool constant_pool; + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { + this(file.readShort(), file.readShort(), null, -1, null, constant_pool); + types_of_locals = new StackMapType[number_of_locals]; + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i] = new StackMapType(file, constant_pool); + } + number_of_stack_items = file.readShort(); + types_of_stack_items = new StackMapType[number_of_stack_items]; + for (int i = 0; i < number_of_stack_items; i++) { + types_of_stack_items[i] = new StackMapType(file, constant_pool); + } + } + + + public StackMapEntry(int byte_code_offset, int number_of_locals, + StackMapType[] types_of_locals, int number_of_stack_items, + StackMapType[] types_of_stack_items, ConstantPool constant_pool) { + this.byte_code_offset = byte_code_offset; + this.number_of_locals = number_of_locals; + this.types_of_locals = types_of_locals; + this.number_of_stack_items = number_of_stack_items; + this.types_of_stack_items = types_of_stack_items; + this.constant_pool = constant_pool; + } + + + /** + * Dump stack map entry + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeShort(byte_code_offset); + file.writeShort(number_of_locals); + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i].dump(file); + } + file.writeShort(number_of_stack_items); + for (int i = 0; i < number_of_stack_items; i++) { + types_of_stack_items[i].dump(file); + } + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(64); + buf.append("(offset=").append(byte_code_offset); + if (number_of_locals > 0) { + buf.append(", locals={"); + for (int i = 0; i < number_of_locals; i++) { + buf.append(types_of_locals[i]); + if (i < number_of_locals - 1) { + buf.append(", "); + } + } + buf.append("}"); + } + if (number_of_stack_items > 0) { + buf.append(", stack items={"); + for (int i = 0; i < number_of_stack_items; i++) { + buf.append(types_of_stack_items[i]); + if (i < number_of_stack_items - 1) { + buf.append(", "); + } + } + buf.append("}"); + } + buf.append(")"); + return buf.toString(); + } + + + public void setByteCodeOffset( int b ) { + byte_code_offset = b; + } + + + public int getByteCodeOffset() { + return byte_code_offset; + } + + + public void setNumberOfLocals( int n ) { + number_of_locals = n; + } + + + public int getNumberOfLocals() { + return number_of_locals; + } + + + public void setTypesOfLocals( StackMapType[] t ) { + types_of_locals = t; + } + + + public StackMapType[] getTypesOfLocals() { + return types_of_locals; + } + + + public void setNumberOfStackItems( int n ) { + number_of_stack_items = n; + } + + + public int getNumberOfStackItems() { + return number_of_stack_items; + } + + + public void setTypesOfStackItems( StackMapType[] t ) { + types_of_stack_items = t; + } + + + public StackMapType[] getTypesOfStackItems() { + return types_of_stack_items; + } + + + /** + * @return deep copy of this object + */ + public StackMapEntry copy() { + try { + return (StackMapEntry) clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackMapEntry(this); + } + + + /** + * @return Constant pool used by this object. + */ + public final ConstantPool getConstantPool() { + return constant_pool; + } + + + /** + * @param constant_pool Constant pool to be used for this object. + */ + public final void setConstantPool( ConstantPool constant_pool ) { + this.constant_pool = constant_pool; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/StackMapTable.java b/java/org/apache/tomcat/util/bcel/classfile/StackMapTable.java new file mode 100644 index 000000000..63d2477bf --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/StackMapTable.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a stack map attribute used for + * preverification of Java classes for the Java 2 Micro Edition + * (J2ME). This attribute is used by the KVM and contained + * within the Code attribute of a method. See CLDC specification + * ��?5.3.1.2 + * + * @version $Id$ + * @author M. Dahm + * @see Code + * @see StackMapEntry + * @see StackMapType + */ +public final class StackMapTable extends Attribute implements Node { + + private int map_length; + private StackMapTableEntry[] map; // Table of stack map entries + + + /* + * @param name_index Index of name + * @param length Content length in bytes + * @param map Table of stack map entries + * @param constant_pool Array of constants + */ + public StackMapTable(int name_index, int length, StackMapTableEntry[] map, ConstantPool constant_pool) { + super(Constants.ATTR_STACK_MAP_TABLE, name_index, length, constant_pool); + setStackMapTable(map); + } + + + /** + * Construct object from file stream. + * @param name_index Index of name + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + StackMapTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (StackMapTableEntry[]) null, constant_pool); + map_length = file.readUnsignedShort(); + map = new StackMapTableEntry[map_length]; + for (int i = 0; i < map_length; i++) { + map[i] = new StackMapTableEntry(file, constant_pool); + } + } + + + /** + * Dump line number table attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + file.writeShort(map_length); + for (int i = 0; i < map_length; i++) { + map[i].dump(file); + } + } + + + /** + * @return Array of stack map entries + */ + public final StackMapTableEntry[] getStackMapTable() { + return map; + } + + + /** + * @param map Array of stack map entries + */ + public final void setStackMapTable( StackMapTableEntry[] map ) { + this.map = map; + map_length = (map == null) ? 0 : map.length; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer("StackMapTable("); + for (int i = 0; i < map_length; i++) { + buf.append(map[i].toString()); + if (i < map_length - 1) { + buf.append(", "); + } + } + buf.append(')'); + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + StackMapTable c = (StackMapTable) clone(); + c.map = new StackMapTableEntry[map_length]; + for (int i = 0; i < map_length; i++) { + c.map[i] = map[i].copy(); + } + c.constant_pool = _constant_pool; + return c; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackMapTable(this); + } + + + public final int getMapLength() { + return map_length; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/StackMapTableEntry.java b/java/org/apache/tomcat/util/bcel/classfile/StackMapTableEntry.java new file mode 100644 index 000000000..4fd2708b4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/StackMapTableEntry.java @@ -0,0 +1,285 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a stack map entry recording the types of + * local variables and the the of stack items at a given byte code offset. + * See CLDC specification ��?5.3.1.2 + * + * @version $Id$ + * @author M. Dahm + * @see StackMap + * @see StackMapType + */ +public final class StackMapTableEntry implements Cloneable { + + private int frame_type; + private int byte_code_offset_delta; + private int number_of_locals; + private StackMapType[] types_of_locals; + private int number_of_stack_items; + private StackMapType[] types_of_stack_items; + private ConstantPool constant_pool; + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + StackMapTableEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { + this(file.read(), -1, -1, null, -1, null, constant_pool); + + if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) { + byte_code_offset_delta = frame_type - Constants.SAME_FRAME; + } else if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + byte_code_offset_delta = frame_type - Constants.SAME_LOCALS_1_STACK_ITEM_FRAME; + number_of_stack_items = 1; + types_of_stack_items = new StackMapType[1]; + types_of_stack_items[0] = new StackMapType(file, constant_pool); + } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + byte_code_offset_delta = file.readShort(); + number_of_stack_items = 1; + types_of_stack_items = new StackMapType[1]; + types_of_stack_items[0] = new StackMapType(file, constant_pool); + } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) { + byte_code_offset_delta = file.readShort(); + } else if (frame_type == Constants.SAME_FRAME_EXTENDED) { + byte_code_offset_delta = file.readShort(); + } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) { + byte_code_offset_delta = file.readShort(); + number_of_locals = frame_type - 251; + types_of_locals = new StackMapType[number_of_locals]; + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i] = new StackMapType(file, constant_pool); + } + } else if (frame_type == Constants.FULL_FRAME) { + byte_code_offset_delta = file.readShort(); + number_of_locals = file.readShort(); + types_of_locals = new StackMapType[number_of_locals]; + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i] = new StackMapType(file, constant_pool); + } + number_of_stack_items = file.readShort(); + types_of_stack_items = new StackMapType[number_of_stack_items]; + for (int i = 0; i < number_of_stack_items; i++) { + types_of_stack_items[i] = new StackMapType(file, constant_pool); + } + } else { + /* Can't happen */ + throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frame_type); + } + } + + + public StackMapTableEntry(int tag, int byte_code_offset_delta, int number_of_locals, + StackMapType[] types_of_locals, int number_of_stack_items, + StackMapType[] types_of_stack_items, ConstantPool constant_pool) { + this.frame_type = tag; + this.byte_code_offset_delta = byte_code_offset_delta; + this.number_of_locals = number_of_locals; + this.types_of_locals = types_of_locals; + this.number_of_stack_items = number_of_stack_items; + this.types_of_stack_items = types_of_stack_items; + this.constant_pool = constant_pool; + } + + + /** + * Dump stack map entry + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.write(frame_type); + if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + types_of_stack_items[0].dump(file); + } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + file.write(byte_code_offset_delta); + types_of_stack_items[0].dump(file); + } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) { + file.write(byte_code_offset_delta); + } else if (frame_type == Constants.SAME_FRAME_EXTENDED) { + file.write(byte_code_offset_delta); + } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) { + file.write(byte_code_offset_delta); + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i].dump(file); + } + } else if (frame_type == Constants.FULL_FRAME) { + file.writeShort(byte_code_offset_delta); + file.writeShort(number_of_locals); + for (int i = 0; i < number_of_locals; i++) { + types_of_locals[i].dump(file); + } + file.writeShort(number_of_stack_items); + for (int i = 0; i < number_of_stack_items; i++) { + types_of_stack_items[i].dump(file); + } + } else { + /* Can't happen */ + throw new ClassFormatException ("Invalid Stack map table tag: " + frame_type); + } + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer(64); + buf.append("("); + if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) { + buf.append("SAME"); + } else if (frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) { + buf.append("SAME_LOCALS_1_STACK"); + } else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + buf.append("SAME_LOCALS_1_STACK_EXTENDED"); + } else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX) { + buf.append("CHOP "+(251-frame_type)); + } else if (frame_type == Constants.SAME_FRAME_EXTENDED) { + buf.append("SAME_EXTENDED"); + } else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) { + buf.append("APPEND "+(frame_type-251)); + } else if (frame_type == Constants.FULL_FRAME) { + buf.append("FULL"); + } else { + buf.append("UNKNOWN"); + } + buf.append(", offset delta=").append(byte_code_offset_delta); + if (number_of_locals > 0) { + buf.append(", locals={"); + for (int i = 0; i < number_of_locals; i++) { + buf.append(types_of_locals[i]); + if (i < number_of_locals - 1) { + buf.append(", "); + } + } + buf.append("}"); + } + if (number_of_stack_items > 0) { + buf.append(", stack items={"); + for (int i = 0; i < number_of_stack_items; i++) { + buf.append(types_of_stack_items[i]); + if (i < number_of_stack_items - 1) { + buf.append(", "); + } + } + buf.append("}"); + } + buf.append(")"); + return buf.toString(); + } + + + public void setByteCodeOffsetDelta( int b ) { + byte_code_offset_delta = b; + } + + + public int getByteCodeOffsetDelta() { + return byte_code_offset_delta; + } + + + public void setNumberOfLocals( int n ) { + number_of_locals = n; + } + + + public int getNumberOfLocals() { + return number_of_locals; + } + + + public void setTypesOfLocals( StackMapType[] t ) { + types_of_locals = t; + } + + + public StackMapType[] getTypesOfLocals() { + return types_of_locals; + } + + + public void setNumberOfStackItems( int n ) { + number_of_stack_items = n; + } + + + public int getNumberOfStackItems() { + return number_of_stack_items; + } + + + public void setTypesOfStackItems( StackMapType[] t ) { + types_of_stack_items = t; + } + + + public StackMapType[] getTypesOfStackItems() { + return types_of_stack_items; + } + + + /** + * @return deep copy of this object + */ + public StackMapTableEntry copy() { + try { + return (StackMapTableEntry) clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackMapTableEntry(this); + } + + + /** + * @return Constant pool used by this object. + */ + public final ConstantPool getConstantPool() { + return constant_pool; + } + + + /** + * @param constant_pool Constant pool to be used for this object. + */ + public final void setConstantPool( ConstantPool constant_pool ) { + this.constant_pool = constant_pool; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/StackMapType.java b/java/org/apache/tomcat/util/bcel/classfile/StackMapType.java new file mode 100644 index 000000000..b923671d2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/StackMapType.java @@ -0,0 +1,162 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents the type of a local variable or item on stack + * used in the StackMap entries. + * + * @version $Id$ + * @author M. Dahm + * @see StackMapEntry + * @see StackMap + * @see Constants + */ +public final class StackMapType implements Cloneable { + + private byte type; + private int index = -1; // Index to CONSTANT_Class or offset + private ConstantPool constant_pool; + + + /** + * Construct object from file stream. + * @param file Input stream + * @throws IOException + */ + StackMapType(DataInput file, ConstantPool constant_pool) throws IOException { + this(file.readByte(), -1, constant_pool); + if (hasIndex()) { + setIndex(file.readShort()); + } + setConstantPool(constant_pool); + } + + + /** + * @param type type tag as defined in the Constants interface + * @param index index to constant pool, or byte code offset + */ + public StackMapType(byte type, int index, ConstantPool constant_pool) { + setType(type); + setIndex(index); + setConstantPool(constant_pool); + } + + + public void setType( byte t ) { + if ((t < Constants.ITEM_Bogus) || (t > Constants.ITEM_NewObject)) { + throw new RuntimeException("Illegal type for StackMapType: " + t); + } + type = t; + } + + + public byte getType() { + return type; + } + + + public void setIndex( int t ) { + index = t; + } + + + /** @return index to constant pool if type == ITEM_Object, or offset + * in byte code, if type == ITEM_NewObject, and -1 otherwise + */ + public int getIndex() { + return index; + } + + + /** + * Dump type entries to file. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + file.writeByte(type); + if (hasIndex()) { + file.writeShort(getIndex()); + } + } + + + /** @return true, if type is either ITEM_Object or ITEM_NewObject + */ + public final boolean hasIndex() { + return ((type == Constants.ITEM_Object) || (type == Constants.ITEM_NewObject)); + } + + + private String printIndex() { + if (type == Constants.ITEM_Object) { + if (index < 0) { + return ", class="; + } + 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/java/org/apache/tomcat/util/bcel/classfile/Synthetic.java b/java/org/apache/tomcat/util/bcel/classfile/Synthetic.java new file mode 100644 index 000000000..d0cade5fc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Synthetic.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class is derived from Attribute 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 + * Attribute.readAttribute() method. + * + * @version $Id$ + * @author M. Dahm + * @see Attribute + */ +public final class Synthetic extends Attribute { + + private byte[] bytes; + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use copy() for a physical copy. + */ + public Synthetic(Synthetic c) { + this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); + } + + + /** + * @param name_index Index in constant pool to CONSTANT_Utf8, which + * should represent the string "Synthetic". + * @param length Content length in bytes - should be zero. + * @param bytes Attribute contents + * @param constant_pool The constant pool this attribute is associated + * with. + */ + public Synthetic(int name_index, int length, byte[] bytes, ConstantPool constant_pool) { + super(Constants.ATTR_SYNTHETIC, name_index, length, constant_pool); + this.bytes = bytes; + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool to CONSTANT_Utf8 + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + Synthetic(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (byte[]) null, constant_pool); + if (length > 0) { + bytes = new byte[length]; + file.readFully(bytes); + System.err.println("Synthetic attribute with length > 0"); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitSynthetic(this); + } + + + /** + * Dump source file attribute to file stream in binary format. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + if (length > 0) { + file.write(bytes, 0, length); + } + } + + + /** + * @return data bytes. + */ + public final byte[] getBytes() { + return bytes; + } + + + /** + * @param bytes + */ + public final void setBytes( byte[] bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + StringBuffer buf = new StringBuffer("Synthetic"); + if (length > 0) { + buf.append(" ").append(Utility.toHexString(bytes)); + } + return buf.toString(); + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + Synthetic c = (Synthetic) clone(); + if (bytes != null) { + c.bytes = new byte[bytes.length]; + System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); + } + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Unknown.java b/java/org/apache/tomcat/util/bcel/classfile/Unknown.java new file mode 100644 index 000000000..b699963f9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Unknown.java @@ -0,0 +1,188 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.tomcat.util.bcel.Constants; + +/** + * This class represents a reference to an unknown (i.e., + * application-specific) attribute of a class. It is instantiated from the + * Attribute.readAttribute() method. Applications that need to + * read in application-specific attributes should create an AttributeReader implementation and + * attach it via Attribute.addAttributeReader. + + * + * @version $Id$ + * @see org.apache.tomcat.util.bcel.classfile.Attribute + * @see org.apache.tomcat.util.bcel.classfile.AttributeReader + * @author M. Dahm + */ +public final class Unknown extends Attribute { + + private byte[] bytes; + private String name; + private static Map unknown_attributes = new HashMap(); + + + /** @return array of unknown attributes, but just one for each kind. + */ + static Unknown[] getUnknownAttributes() { + Unknown[] unknowns = new Unknown[unknown_attributes.size()]; + Iterator entries = unknown_attributes.values().iterator(); + for (int i = 0; entries.hasNext(); i++) { + unknowns[i] = (Unknown) entries.next(); + } + unknown_attributes.clear(); + return unknowns; + } + + + /** + * Initialize from another object. Note that both objects use the same + * references (shallow copy). Use clone() for a physical copy. + */ + public Unknown(Unknown c) { + this(c.getNameIndex(), c.getLength(), c.getBytes(), c.getConstantPool()); + } + + + /** + * Create a non-standard attribute. + * + * @param name_index Index in constant pool + * @param length Content length in bytes + * @param bytes Attribute contents + * @param constant_pool Array of constants + */ + public Unknown(int name_index, int length, byte[] bytes, ConstantPool constant_pool) { + super(Constants.ATTR_UNKNOWN, name_index, length, constant_pool); + this.bytes = bytes; + name = ((ConstantUtf8) constant_pool.getConstant(name_index, Constants.CONSTANT_Utf8)) + .getBytes(); + unknown_attributes.put(name, this); + } + + + /** + * Construct object from file stream. + * @param name_index Index in constant pool + * @param length Content length in bytes + * @param file Input stream + * @param constant_pool Array of constants + * @throws IOException + */ + Unknown(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + throws IOException { + this(name_index, length, (byte[]) null, constant_pool); + if (length > 0) { + bytes = new byte[length]; + file.readFully(bytes); + } + } + + + /** + * Called by objects that are traversing the nodes of the tree implicitely + * defined by the contents of a Java class. I.e., the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitUnknown(this); + } + + + /** + * Dump unknown bytes to file stream. + * + * @param file Output file stream + * @throws IOException + */ + public final void dump( DataOutputStream file ) throws IOException { + super.dump(file); + if (length > 0) { + file.write(bytes, 0, length); + } + } + + + /** + * @return data bytes. + */ + public final byte[] getBytes() { + return bytes; + } + + + /** + * @return name of attribute. + */ + public final String getName() { + return name; + } + + + /** + * @param bytes the bytes to set + */ + public final void setBytes( byte[] bytes ) { + this.bytes = bytes; + } + + + /** + * @return String representation. + */ + public final String toString() { + if (length == 0 || bytes == null) { + return "(Unknown attribute " + name + ")"; + } + String hex; + if (length > 10) { + byte[] tmp = new byte[10]; + System.arraycopy(bytes, 0, tmp, 0, 10); + hex = Utility.toHexString(tmp) + "... (truncated)"; + } else { + hex = Utility.toHexString(bytes); + } + return "(Unknown attribute " + name + ": " + hex + ")"; + } + + + /** + * @return deep copy of this attribute + */ + public Attribute copy( ConstantPool _constant_pool ) { + Unknown c = (Unknown) clone(); + if (bytes != null) { + c.bytes = new byte[bytes.length]; + System.arraycopy(bytes, 0, c.bytes, 0, bytes.length); + } + c.constant_pool = _constant_pool; + return c; + } +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Utility.java b/java/org/apache/tomcat/util/bcel/classfile/Utility.java new file mode 100644 index 000000000..73ca68bbf --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Utility.java @@ -0,0 +1,1525 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FilterReader; +import java.io.FilterWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.generic.AnnotationEntryGen; +import org.apache.tomcat.util.bcel.generic.ConstantPoolGen; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Utility functions that do not really belong to any class in particular. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class Utility { + + private static int unwrap( ThreadLocal tl ) { + return ((Integer) tl.get()).intValue(); + } + + + private static void wrap( ThreadLocal tl, int value ) { + tl.set(new Integer(value)); + } + + private static ThreadLocal consumed_chars = new ThreadLocal() { + + protected Object initialValue() { + return new Integer(0); + } + };/* How many chars have been consumed + * during parsing in signatureToString(). + * Read by methodSignatureToString(). + * Set by side effect,but only internally. + */ + private static boolean wide = false; /* The `WIDE' instruction is used in the + * byte code to allow 16-bit wide indices + * for local variables. This opcode + * precedes an `ILOAD', e.g.. The opcode + * immediately following takes an extra + * byte which is combined with the + * following byte to form a + * 16-bit value. + */ + + + /** + * Convert bit field of flags into string such as `static final'. + * + * @param access_flags Access flags + * @return String representation of flags + */ + public static final String accessToString( int access_flags ) { + return accessToString(access_flags, false); + } + + + /** + * Convert bit field of flags into string such as `static final'. + * + * Special case: Classes compiled with new compilers and with the + * `ACC_SUPER' flag would be said to be "synchronized". This is + * because SUN used the same value for the flags `ACC_SUPER' and + * `ACC_SYNCHRONIZED'. + * + * @param access_flags Access flags + * @param for_class access flags are for class qualifiers ? + * @return String representation of flags + */ + public static final String accessToString( int access_flags, boolean for_class ) { + StringBuffer buf = new StringBuffer(); + int p = 0; + for (int i = 0; p < Constants.MAX_ACC_FLAG; i++) { // Loop through known flags + p = pow2(i); + if ((access_flags & p) != 0) { + /* Special case: Classes compiled with new compilers and with the + * `ACC_SUPER' flag would be said to be "synchronized". This is + * because SUN used the same value for the flags `ACC_SUPER' and + * `ACC_SYNCHRONIZED'. + */ + if (for_class && ((p == Constants.ACC_SUPER) || (p == Constants.ACC_INTERFACE))) { + continue; + } + buf.append(Constants.ACCESS_NAMES[i]).append(" "); + } + } + return buf.toString().trim(); + } + + + /** + * @return "class" or "interface", depending on the ACC_INTERFACE flag + */ + public static final String classOrInterface( int access_flags ) { + return ((access_flags & Constants.ACC_INTERFACE) != 0) ? "interface" : "class"; + } + + + /** + * Disassemble a byte array of JVM byte codes starting from code line + * `index' and return the disassembled string representation. Decode only + * `num' opcodes (including their operands), use -1 if you want to + * decompile everything. + * + * @param code byte code array + * @param constant_pool Array of constants + * @param index offset in `code' array + * (number of opcodes, not bytes!) + * @param length number of opcodes to decompile, -1 for all + * @param verbose be verbose, e.g. print constant pool index + * @return String representation of byte codes + */ + public static final String codeToString( byte[] code, ConstantPool constant_pool, int index, + int length, boolean verbose ) { + StringBuffer buf = new StringBuffer(code.length * 20); // Should be sufficient + ByteSequence stream = new ByteSequence(code); + try { + for (int i = 0; i < index; i++) { + codeToString(stream, constant_pool, verbose); + } + for (int i = 0; stream.available() > 0; i++) { + if ((length < 0) || (i < length)) { + String indices = fillup(stream.getIndex() + ":", 6, true, ' '); + buf.append(indices).append(codeToString(stream, constant_pool, verbose)) + .append('\n'); + } + } + } catch (IOException e) { + System.out.println(buf.toString()); + e.printStackTrace(); + throw new ClassFormatException("Byte code error: " + e, e); + } + return buf.toString(); + } + + + public static final String codeToString( byte[] code, ConstantPool constant_pool, int index, + int length ) { + return codeToString(code, constant_pool, index, length, true); + } + + + /** + * Disassemble a stream of byte codes and return the + * string representation. + * + * @param bytes stream of bytes + * @param constant_pool Array of constants + * @param verbose be verbose, e.g. print constant pool index + * @return String representation of byte code + */ + public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool, + boolean verbose ) throws IOException { + short opcode = (short) bytes.readUnsignedByte(); + int default_offset = 0, low, high, npairs; + int index, vindex, constant; + int[] match, jump_table; + int no_pad_bytes = 0, offset; + StringBuffer buf = new StringBuffer(Constants.OPCODE_NAMES[opcode]); + /* Special case: Skip (0-3) padding bytes, i.e., the + * following bytes are 4-byte-aligned + */ + if ((opcode == Constants.TABLESWITCH) || (opcode == Constants.LOOKUPSWITCH)) { + int remainder = bytes.getIndex() % 4; + no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; + for (int i = 0; i < no_pad_bytes; i++) { + byte b; + if ((b = bytes.readByte()) != 0) { + System.err.println("Warning: Padding byte != 0 in " + + Constants.OPCODE_NAMES[opcode] + ":" + b); + } + } + // Both cases have a field default_offset in common + default_offset = bytes.readInt(); + } + switch (opcode) { + /* Table switch has variable length arguments. + */ + case Constants.TABLESWITCH: + low = bytes.readInt(); + high = bytes.readInt(); + offset = bytes.getIndex() - 12 - no_pad_bytes - 1; + default_offset += offset; + buf.append("\tdefault = ").append(default_offset).append(", low = ").append(low) + .append(", high = ").append(high).append("("); + jump_table = new int[high - low + 1]; + for (int i = 0; i < jump_table.length; i++) { + jump_table[i] = offset + bytes.readInt(); + buf.append(jump_table[i]); + if (i < jump_table.length - 1) { + buf.append(", "); + } + } + buf.append(")"); + break; + /* Lookup switch has variable length arguments. + */ + case Constants.LOOKUPSWITCH: { + npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - no_pad_bytes - 1; + match = new int[npairs]; + jump_table = new int[npairs]; + default_offset += offset; + buf.append("\tdefault = ").append(default_offset).append(", npairs = ").append( + npairs).append(" ("); + for (int i = 0; i < npairs; i++) { + match[i] = bytes.readInt(); + jump_table[i] = offset + bytes.readInt(); + buf.append("(").append(match[i]).append(", ").append(jump_table[i]).append(")"); + if (i < npairs - 1) { + buf.append(", "); + } + } + buf.append(")"); + } + break; + /* Two address bytes + offset from start of byte stream form the + * jump target + */ + case Constants.GOTO: + case Constants.IFEQ: + case Constants.IFGE: + case Constants.IFGT: + case Constants.IFLE: + case Constants.IFLT: + case Constants.JSR: + case Constants.IFNE: + case Constants.IFNONNULL: + case Constants.IFNULL: + case Constants.IF_ACMPEQ: + case Constants.IF_ACMPNE: + case Constants.IF_ICMPEQ: + case Constants.IF_ICMPGE: + case Constants.IF_ICMPGT: + case Constants.IF_ICMPLE: + case Constants.IF_ICMPLT: + case Constants.IF_ICMPNE: + buf.append("\t\t#").append((bytes.getIndex() - 1) + bytes.readShort()); + break; + /* 32-bit wide jumps + */ + case Constants.GOTO_W: + case Constants.JSR_W: + buf.append("\t\t#").append(((bytes.getIndex() - 1) + bytes.readInt())); + break; + /* Index byte references local variable (register) + */ + case Constants.ALOAD: + case Constants.ASTORE: + case Constants.DLOAD: + case Constants.DSTORE: + case Constants.FLOAD: + case Constants.FSTORE: + case Constants.ILOAD: + case Constants.ISTORE: + case Constants.LLOAD: + case Constants.LSTORE: + case Constants.RET: + if (wide) { + vindex = bytes.readUnsignedShort(); + wide = false; // Clear flag + } else { + vindex = bytes.readUnsignedByte(); + } + buf.append("\t\t%").append(vindex); + break; + /* + * Remember wide byte which is used to form a 16-bit address in the + * following instruction. Relies on that the method is called again with + * the following opcode. + */ + case Constants.WIDE: + wide = true; + buf.append("\t(wide)"); + break; + /* Array of basic type. + */ + case Constants.NEWARRAY: + buf.append("\t\t<").append(Constants.TYPE_NAMES[bytes.readByte()]).append(">"); + break; + /* Access object/class fields. + */ + case Constants.GETFIELD: + case Constants.GETSTATIC: + case Constants.PUTFIELD: + case Constants.PUTSTATIC: + index = bytes.readUnsignedShort(); + buf.append("\t\t").append( + constant_pool.constantToString(index, Constants.CONSTANT_Fieldref)).append( + (verbose ? " (" + index + ")" : "")); + break; + /* Operands are references to classes in constant pool + */ + case Constants.NEW: + case Constants.CHECKCAST: + buf.append("\t"); + /* FALL THRU */ + case Constants.INSTANCEOF: + index = bytes.readUnsignedShort(); + buf.append("\t<").append( + constant_pool.constantToString(index, Constants.CONSTANT_Class)) + .append(">").append((verbose ? " (" + index + ")" : "")); + break; + /* Operands are references to methods in constant pool + */ + case Constants.INVOKESPECIAL: + case Constants.INVOKESTATIC: + case Constants.INVOKEVIRTUAL: + index = bytes.readUnsignedShort(); + buf.append("\t").append( + constant_pool.constantToString(index, Constants.CONSTANT_Methodref)) + .append((verbose ? " (" + index + ")" : "")); + break; + case Constants.INVOKEINTERFACE: + index = bytes.readUnsignedShort(); + int nargs = bytes.readUnsignedByte(); // historical, redundant + buf.append("\t").append( + constant_pool + .constantToString(index, Constants.CONSTANT_InterfaceMethodref)) + .append(verbose ? " (" + index + ")\t" : "").append(nargs).append("\t") + .append(bytes.readUnsignedByte()); // Last byte is a reserved space + break; + /* Operands are references to items in constant pool + */ + case Constants.LDC_W: + case Constants.LDC2_W: + index = bytes.readUnsignedShort(); + buf.append("\t\t").append( + constant_pool.constantToString(index, constant_pool.getConstant(index) + .getTag())).append((verbose ? " (" + index + ")" : "")); + break; + case Constants.LDC: + index = bytes.readUnsignedByte(); + buf.append("\t\t").append( + constant_pool.constantToString(index, constant_pool.getConstant(index) + .getTag())).append((verbose ? " (" + index + ")" : "")); + break; + /* Array of references. + */ + case Constants.ANEWARRAY: + index = bytes.readUnsignedShort(); + buf.append("\t\t<").append( + compactClassName(constant_pool.getConstantString(index, + Constants.CONSTANT_Class), false)).append(">").append( + (verbose ? " (" + index + ")" : "")); + break; + /* Multidimensional array of references. + */ + case Constants.MULTIANEWARRAY: { + index = bytes.readUnsignedShort(); + int dimensions = bytes.readUnsignedByte(); + buf.append("\t<").append( + compactClassName(constant_pool.getConstantString(index, + Constants.CONSTANT_Class), false)).append(">\t").append(dimensions) + .append((verbose ? " (" + index + ")" : "")); + } + break; + /* Increment local variable. + */ + case Constants.IINC: + if (wide) { + vindex = bytes.readUnsignedShort(); + constant = bytes.readShort(); + wide = false; + } else { + vindex = bytes.readUnsignedByte(); + constant = bytes.readByte(); + } + buf.append("\t\t%").append(vindex).append("\t").append(constant); + break; + default: + if (Constants.NO_OF_OPERANDS[opcode] > 0) { + for (int i = 0; i < Constants.TYPE_OF_OPERANDS[opcode].length; i++) { + buf.append("\t\t"); + switch (Constants.TYPE_OF_OPERANDS[opcode][i]) { + case Constants.T_BYTE: + buf.append(bytes.readByte()); + break; + case Constants.T_SHORT: + buf.append(bytes.readShort()); + break; + case Constants.T_INT: + buf.append(bytes.readInt()); + break; + default: // Never reached + System.err.println("Unreachable default case reached!"); + System.exit(-1); + } + } + } + } + return buf.toString(); + } + + + public static final String codeToString( ByteSequence bytes, ConstantPool constant_pool ) + throws IOException { + return codeToString(bytes, constant_pool, true); + } + + + /** + * Shorten long class names, java/lang/String becomes + * String. + * + * @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 str, i.e., chop off the prefix, + * if the + * class name starts with this string and the flag chopit is true. + * Slashes / are converted to dots .. + * + * @param str The long class name + * @param prefix The prefix the get rid off + * @param chopit Flag that determines whether chopping is executed or not + * @return Compacted class name + */ + public static final String compactClassName( String str, String prefix, boolean chopit ) { + int len = prefix.length(); + str = str.replace('/', '.'); // Is `/' on all systems, even DOS + if (chopit) { + // If string starts with `prefix' and contains no further dots + if (str.startsWith(prefix) && (str.substring(len).indexOf('.') == -1)) { + str = str.substring(len); + } + } + return str; + } + + + /** + * Shorten long class names, java/lang/String becomes + * java.lang.String, + * e.g.. If chopit is true the prefix java.lang + * is also removed. + * + * @param str The long class name + * @param chopit Flag that determines whether chopping is executed or not + * @return Compacted class name + */ + public static final String compactClassName( String str, boolean chopit ) { + return compactClassName(str, "java.lang.", chopit); + } + + + /** + * @return `flag' with bit `i' set to 1 + */ + public static final int setBit( int flag, int i ) { + return flag | pow2(i); + } + + + /** + * @return `flag' with bit `i' set to 0 + */ + public static final int clearBit( int flag, int i ) { + int bit = pow2(i); + return (flag & bit) == 0 ? flag : flag ^ bit; + } + + + /** + * @return true, if bit `i' in `flag' is set + */ + public static final boolean isSet( int flag, int i ) { + return (flag & pow2(i)) != 0; + } + + + /** + * Converts string containing the method return and argument types + * to a byte code method signature. + * + * @param ret Return type of method + * @param argv Types of method arguments + * @return Byte code representation of method signature + */ + public final static String methodTypeToSignature( String ret, String[] argv ) + throws ClassFormatException { + StringBuffer buf = new StringBuffer("("); + String str; + if (argv != null) { + for (int i = 0; i < argv.length; i++) { + str = getSignature(argv[i]); + if (str.endsWith("V")) { + throw new ClassFormatException("Invalid type: " + argv[i]); + } + buf.append(str); + } + } + str = getSignature(ret); + buf.append(")").append(str); + return buf.toString(); + } + + + /** + * @param signature Method signature + * @return Array of argument types + * @throws ClassFormatException + */ + public static final String[] methodSignatureArgumentTypes( String signature ) + throws ClassFormatException { + return methodSignatureArgumentTypes(signature, true); + } + + + /** + * @param signature Method signature + * @param chopit Shorten class names ? + * @return Array of argument types + * @throws ClassFormatException + */ + public static final String[] methodSignatureArgumentTypes( String signature, boolean chopit ) + throws ClassFormatException { + List vec = new ArrayList(); + int index; + try { // Read all declarations between for `(' and `)' + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + index = 1; // current string position + while (signature.charAt(index) != ')') { + vec.add(signatureToString(signature.substring(index), chopit)); + //corrected concurrent private static field acess + index += unwrap(consumed_chars); // update position + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + return (String[]) vec.toArray(new String[vec.size()]); + } + + + /** + * @param signature Method signature + * @return return type of method + * @throws ClassFormatException + */ + public static final String methodSignatureReturnType( String signature ) + throws ClassFormatException { + return methodSignatureReturnType(signature, true); + } + + + /** + * @param signature Method signature + * @param chopit Shorten class names ? + * @return return type of method + * @throws ClassFormatException + */ + public static final String methodSignatureReturnType( String signature, boolean chopit ) + throws ClassFormatException { + int index; + String type; + try { + // Read return type after `)' + index = signature.lastIndexOf(')') + 1; + type = signatureToString(signature.substring(index), chopit); + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + return type; + } + + + /** + * Converts method signature to string with all class names compacted. + * + * @param signature to convert + * @param name of method + * @param access flags of method + * @return Human readable signature + */ + public static final String methodSignatureToString( String signature, String name, String access ) { + return methodSignatureToString(signature, name, access, true); + } + + + public static final String methodSignatureToString( String signature, String name, + String access, boolean chopit ) { + return methodSignatureToString(signature, name, access, chopit, null); + } + + + /** + * A returntype signature represents the return value from a method. + * It is a series of bytes in the following grammar: + * + * ::= | V + * + * The character V indicates that the method returns no value. Otherwise, the + * signature indicates the type of the return value. + * An argument signature represents an argument passed to a method: + * + * ::= + * + * A method signature represents the arguments that the method expects, and + * the value that it returns. + * ::= () + * ::= * + * + * This method converts such a string into a Java type declaration like + * `void main(String[])' and throws a `ClassFormatException' when the parsed + * type is invalid. + * + * @param signature Method signature + * @param name Method name + * @param access Method access rights + * @return Java type declaration + * @throws ClassFormatException + */ + public static final String methodSignatureToString( String signature, String name, + String access, boolean chopit, LocalVariableTable vars ) throws ClassFormatException { + StringBuffer buf = new StringBuffer("("); + String type; + int index; + int var_index = (access.indexOf("static") >= 0) ? 0 : 1; + try { // Read all declarations between for `(' and `)' + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + index = 1; // current string position + while (signature.charAt(index) != ')') { + String param_type = signatureToString(signature.substring(index), chopit); + buf.append(param_type); + if (vars != null) { + LocalVariable l = vars.getLocalVariable(var_index); + if (l != null) { + buf.append(" ").append(l.getName()); + } + } else { + buf.append(" arg").append(var_index); + } + if ("double".equals(param_type) || "long".equals(param_type)) { + var_index += 2; + } else { + var_index++; + } + buf.append(", "); + //corrected concurrent private static field acess + index += unwrap(consumed_chars); // update position + } + index++; // update position + // Read return type after `)' + type = signatureToString(signature.substring(index), chopit); + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + if (buf.length() > 1) { + buf.setLength(buf.length() - 2); + } + buf.append(")"); + return access + ((access.length() > 0) ? " " : "") + // May be an empty string + type + " " + name + buf.toString(); + } + + + // Guess what this does + private static final int pow2( int n ) { + return 1 << n; + } + + + /** + * Replace all occurrences of old in str with new. + * + * @param str String to permute + * @param old String to be replaced + * @param new_ Replacement string + * @return new String object + */ + public static final String replace( String str, String old, String new_ ) { + int index, old_index; + try { + if ((index = str.indexOf(old)) != -1) { // `old' found in str + StringBuffer buf = new StringBuffer(); + old_index = 0; // String start offset + // While we have something to replace + while ((index = str.indexOf(old, old_index)) != -1) { + buf.append(str.substring(old_index, index)); // append prefix + buf.append(new_); // append replacement + old_index = index + old.length(); // Skip `old'.length chars + } + buf.append(str.substring(old_index)); // append rest of string + str = buf.toString(); + } + } catch (StringIndexOutOfBoundsException e) { // Should not occur + System.err.println(e); + } + return str; + } + + + /** + * Converts signature to string with all class names compacted. + * + * @param signature to convert + * @return Human readable signature + */ + public static final String signatureToString( String signature ) { + return signatureToString(signature, true); + } + + + /** + * The field signature represents the value of an argument to a function or + * the value of a variable. It is a series of bytes generated by the + * following grammar: + * + *
+     *  ::= 
+     *       ::= ||
+     *        ::= B|C|D|F|I|J|S|Z
+     *      ::= L;
+     *       ::= [
+     *
+     * The meaning of the base types is as follows:
+     * B byte signed byte
+     * C char character
+     * D double double precision IEEE float
+     * F float single precision IEEE float
+     * I int integer
+     * J long long integer
+     * L; ... an object of the given class
+     * S short signed short
+     * Z boolean true or false
+     * [ ... array
+     * 
+ * + * This method converts this string into a Java type declaration such as + * `String[]' and throws a `ClassFormatException' when the parsed type is + * invalid. + * + * @param signature Class signature + * @param chopit Flag that determines whether chopping is executed or not + * @return Java type declaration + * @throws ClassFormatException + */ + public static final String signatureToString( String signature, boolean chopit ) { + //corrected concurrent private static field acess + wrap(consumed_chars, 1); // This is the default, read just one char like `B' + try { + switch (signature.charAt(0)) { + case 'B': + return "byte"; + case 'C': + return "char"; + case 'D': + return "double"; + case 'F': + return "float"; + case 'I': + return "int"; + case 'J': + return "long"; + case 'L': { // Full class name + int index = signature.indexOf(';'); // Look for closing `;' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + //corrected concurrent private static field acess + wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed + return compactClassName(signature.substring(1, index), chopit); + } + case 'S': + return "short"; + case 'Z': + return "boolean"; + case '[': { // Array declaration + int n; + StringBuffer brackets; + String type; + int consumed_chars; // Shadows global var + brackets = new StringBuffer(); // Accumulate []'s + // Count opening brackets and look for optional size argument + for (n = 0; signature.charAt(n) == '['; n++) { + brackets.append("[]"); + } + consumed_chars = n; // Remember value + // The rest of the string denotes a `' + type = signatureToString(signature.substring(n), chopit); + //corrected concurrent private static field acess + //Utility.consumed_chars += consumed_chars; is replaced by: + int _temp = unwrap(Utility.consumed_chars) + consumed_chars; + wrap(Utility.consumed_chars, _temp); + return type + brackets.toString(); + } + case 'V': + return "void"; + default: + throw new ClassFormatException("Invalid signature: `" + signature + "'"); + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid signature: " + signature, e); + } + } + + + /** Parse Java type such as "char", or "java.lang.String[]" and return the + * signature in byte code format, e.g. "C" or "[Ljava/lang/String;" respectively. + * + * @param type Java type + * @return byte code signature + */ + public static String getSignature( String type ) { + StringBuffer buf = new StringBuffer(); + char[] chars = type.toCharArray(); + boolean char_found = false, delim = false; + int index = -1; + loop: for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + if (char_found) { + delim = true; + } + break; + case '[': + if (!char_found) { + throw new RuntimeException("Illegal type: " + type); + } + index = i; + break loop; + default: + char_found = true; + if (!delim) { + buf.append(chars[i]); + } + } + } + int brackets = 0; + if (index > 0) { + brackets = countBrackets(type.substring(index)); + } + type = buf.toString(); + buf.setLength(0); + for (int i = 0; i < brackets; i++) { + buf.append('['); + } + boolean found = false; + for (int i = Constants.T_BOOLEAN; (i <= Constants.T_VOID) && !found; i++) { + if (Constants.TYPE_NAMES[i].equals(type)) { + found = true; + buf.append(Constants.SHORT_TYPE_NAMES[i]); + } + } + if (!found) { + buf.append('L').append(type.replace('.', '/')).append(';'); + } + return buf.toString(); + } + + + private static int countBrackets( String brackets ) { + char[] chars = brackets.toCharArray(); + int count = 0; + boolean open = false; + for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case '[': + if (open) { + throw new RuntimeException("Illegally nested brackets:" + brackets); + } + open = true; + break; + case ']': + if (!open) { + throw new RuntimeException("Illegally nested brackets:" + brackets); + } + open = false; + count++; + break; + default: + // Don't care + } + } + if (open) { + throw new RuntimeException("Illegally nested brackets:" + brackets); + } + return count; + } + + + /** + * Return type of method signature as a byte value as defined in Constants + * + * @param signature in format described above + * @return type of method signature + * @see Constants + */ + public static final byte typeOfMethodSignature( String signature ) throws ClassFormatException { + int index; + try { + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + index = signature.lastIndexOf(')') + 1; + return typeOfSignature(signature.substring(index)); + } catch (StringIndexOutOfBoundsException e) { + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + } + + + /** + * Return type of signature as a byte value as defined in Constants + * + * @param signature in format described above + * @return type of signature + * @see Constants + */ + public static final byte typeOfSignature( String signature ) throws ClassFormatException { + try { + switch (signature.charAt(0)) { + case 'B': + return Constants.T_BYTE; + case 'C': + return Constants.T_CHAR; + case 'D': + return Constants.T_DOUBLE; + case 'F': + return Constants.T_FLOAT; + case 'I': + return Constants.T_INT; + case 'J': + return Constants.T_LONG; + case 'L': + return Constants.T_REFERENCE; + case '[': + return Constants.T_ARRAY; + case 'V': + return Constants.T_VOID; + case 'Z': + return Constants.T_BOOLEAN; + case 'S': + return Constants.T_SHORT; + default: + throw new ClassFormatException("Invalid method signature: " + signature); + } + } catch (StringIndexOutOfBoundsException e) { + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + } + + + /** Map opcode names to opcode numbers. E.g., return Constants.ALOAD for "aload" + */ + public static short searchOpcode( String name ) { + name = name.toLowerCase(Locale.ENGLISH); + for (short i = 0; i < Constants.OPCODE_NAMES.length; i++) { + if (Constants.OPCODE_NAMES[i].equals(name)) { + return i; + } + } + return -1; + } + + + /** + * Convert (signed) byte to (unsigned) short value, i.e., all negative + * values become positive. + */ + private static final short byteToShort( byte b ) { + return (b < 0) ? (short) (256 + b) : (short) b; + } + + + /** Convert bytes into hexidecimal string + * + * @return bytes as hexidecimal string, e.g. 00 FA 12 ... + */ + public static final String toHexString( byte[] bytes ) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + short b = byteToShort(bytes[i]); + String hex = Integer.toString(b, 0x10); + if (b < 0x10) { + buf.append('0'); + } + buf.append(hex); + if (i < bytes.length - 1) { + buf.append(' '); + } + } + return buf.toString(); + } + + + /** + * Return a string for an integer justified left or right and filled up with + * `fill' characters if necessary. + * + * @param i integer to format + * @param length length of desired string + * @param left_justify format left or right + * @param fill fill character + * @return formatted int + */ + public static final String format( int i, int length, boolean left_justify, char fill ) { + return fillup(Integer.toString(i), length, left_justify, fill); + } + + + /** + * Fillup char with up to length characters with char `fill' and justify it left or right. + * + * @param str string to format + * @param length length of desired string + * @param left_justify format left or right + * @param fill fill character + * @return formatted string + */ + public static final String fillup( String str, int length, boolean left_justify, char fill ) { + int len = length - str.length(); + char[] buf = new char[(len < 0) ? 0 : len]; + for (int j = 0; j < buf.length; j++) { + buf[j] = fill; + } + if (left_justify) { + return str + new String(buf); + } + return new String(buf) + str; + } + + + static final boolean equals( byte[] a, byte[] b ) { + int size; + if ((size = a.length) != b.length) { + return false; + } + for (int i = 0; i < size; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + + + public static final void printArray( PrintStream out, Object[] obj ) { + out.println(printArray(obj, true)); + } + + + public static final void printArray( PrintWriter out, Object[] obj ) { + out.println(printArray(obj, true)); + } + + + public static final String printArray( Object[] obj ) { + return printArray(obj, true); + } + + + public static final String printArray( Object[] obj, boolean braces ) { + return printArray(obj, braces, false); + } + + + public static final String printArray( Object[] obj, boolean braces, boolean quote ) { + if (obj == null) { + return null; + } + StringBuffer buf = new StringBuffer(); + if (braces) { + buf.append('{'); + } + for (int i = 0; i < obj.length; i++) { + if (obj[i] != null) { + buf.append((quote ? "\"" : "")).append(obj[i].toString()).append( + (quote ? "\"" : "")); + } else { + buf.append("null"); + } + if (i < obj.length - 1) { + buf.append(", "); + } + } + if (braces) { + buf.append('}'); + } + return buf.toString(); + } + + + /** @return true, if character is one of (a, ... z, A, ... Z, 0, ... 9, _) + */ + public static boolean isJavaIdentifierPart( char ch ) { + return ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) + || ((ch >= '0') && (ch <= '9')) || (ch == '_'); + } + + + /** Encode byte array it into Java identifier string, i.e., a string + * that only contains the following characters: (a, ... z, A, ... Z, + * 0, ... 9, _, $). The encoding algorithm itself is not too + * clever: if the current byte's ASCII value already is a valid Java + * identifier part, leave it as it is. Otherwise it writes the + * escape character($) followed by

  • the ASCII value as a + * hexadecimal string, if the value is not in the range + * 200..247
  • a Java identifier char not used in a lowercase + * hexadecimal string, if the value is in the range + * 200..247
    • + * + *

      This operation inflates the original byte array by roughly 40-50%

      + * + * @param bytes the byte array to convert + * @param compress use gzip to minimize string + */ + public static String encode( byte[] bytes, boolean compress ) throws IOException { + if (compress) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gos = new GZIPOutputStream(baos); + gos.write(bytes, 0, bytes.length); + gos.close(); + baos.close(); + bytes = baos.toByteArray(); + } + CharArrayWriter caw = new CharArrayWriter(); + JavaWriter jw = new JavaWriter(caw); + for (int i = 0; i < bytes.length; i++) { + int in = bytes[i] & 0x000000ff; // Normalize to unsigned + jw.write(in); + } + return caw.toString(); + } + + + /** Decode a string back to a byte array. + * + * @param s the string to convert + * @param uncompress use gzip to uncompress the stream of bytes + */ + public static byte[] decode( String s, boolean uncompress ) throws IOException { + char[] chars = s.toCharArray(); + CharArrayReader car = new CharArrayReader(chars); + JavaReader jr = new JavaReader(car); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int ch; + while ((ch = jr.read()) >= 0) { + bos.write(ch); + } + bos.close(); + car.close(); + jr.close(); + byte[] bytes = bos.toByteArray(); + if (uncompress) { + GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(bytes)); + byte[] tmp = new byte[bytes.length * 3]; // Rough estimate + int count = 0; + int b; + while ((b = gis.read()) >= 0) { + tmp[count++] = (byte) b; + } + bytes = new byte[count]; + System.arraycopy(tmp, 0, bytes, 0, count); + } + return bytes; + } + + // A-Z, g-z, _, $ + private static final int FREE_CHARS = 48; + static int[] CHAR_MAP = new int[FREE_CHARS]; + static int[] MAP_CHAR = new int[256]; // Reverse map + private static final char ESCAPE_CHAR = '$'; + static { + int j = 0; + for (int i = 'A'; i <= 'Z'; i++) { + CHAR_MAP[j] = i; + MAP_CHAR[i] = j; + j++; + } + for (int i = 'g'; i <= 'z'; i++) { + CHAR_MAP[j] = i; + MAP_CHAR[i] = j; + j++; + } + CHAR_MAP[j] = '$'; + MAP_CHAR['$'] = j; + j++; + CHAR_MAP[j] = '_'; + MAP_CHAR['_'] = j; + } + + /** Decode characters into bytes. + * Used by decode() + */ + private static class JavaReader extends FilterReader { + + public JavaReader(Reader in) { + super(in); + } + + + public int read() throws IOException { + int b = in.read(); + if (b != ESCAPE_CHAR) { + return b; + } + int i = in.read(); + if (i < 0) { + return -1; + } + if (((i >= '0') && (i <= '9')) || ((i >= 'a') && (i <= 'f'))) { // Normal escape + int j = in.read(); + if (j < 0) { + return -1; + } + char[] tmp = { + (char) i, (char) j + }; + int s = Integer.parseInt(new String(tmp), 16); + return s; + } + return MAP_CHAR[i]; + } + + + public int read( char[] cbuf, int off, int len ) throws IOException { + for (int i = 0; i < len; i++) { + cbuf[off + i] = (char) read(); + } + return len; + } + } + + /** Encode bytes into valid java identifier characters. + * Used by encode() + */ + private static class JavaWriter extends FilterWriter { + + public JavaWriter(Writer out) { + super(out); + } + + + public void write( int b ) throws IOException { + if (isJavaIdentifierPart((char) b) && (b != ESCAPE_CHAR)) { + out.write(b); + } else { + out.write(ESCAPE_CHAR); // Escape character + // Special escape + if (b >= 0 && b < FREE_CHARS) { + out.write(CHAR_MAP[b]); + } else { // Normal escape + char[] tmp = Integer.toHexString(b).toCharArray(); + if (tmp.length == 1) { + out.write('0'); + out.write(tmp[0]); + } else { + out.write(tmp[0]); + out.write(tmp[1]); + } + } + } + } + + + public void write( char[] cbuf, int off, int len ) throws IOException { + for (int i = 0; i < len; i++) { + write(cbuf[off + i]); + } + } + + + public void write( String str, int off, int len ) throws IOException { + write(str.toCharArray(), off, len); + } + } + + + /** + * Escape all occurences of newline chars '\n', quotes \", etc. + */ + public static final String convertString( String label ) { + char[] ch = label.toCharArray(); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < ch.length; i++) { + switch (ch[i]) { + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + case '\"': + buf.append("\\\""); + break; + case '\'': + buf.append("\\'"); + break; + case '\\': + buf.append("\\\\"); + break; + default: + buf.append(ch[i]); + break; + } + } + return buf.toString(); + } + + + /** + * Converts a list of AnnotationGen objects into a set of attributes + * that can be attached to the class file. + * + * @param cp The constant pool gen where we can create the necessary name refs + * @param vec A list of AnnotationGen objects + */ + public static Attribute[] getAnnotationAttributes(ConstantPoolGen cp,List vec) { + + if (vec.isEmpty()) return new Attribute[0]; + + try { + int countVisible = 0; + int countInvisible = 0; + + // put the annotations in the right output stream + for (int i=0; i2) rvaIndex = cp.addUtf8("RuntimeVisibleAnnotations"); + if (riaData.length>2) riaIndex = cp.addUtf8("RuntimeInvisibleAnnotations"); + + List newAttributes = new ArrayList(); + if (rvaData.length>2) { + + newAttributes.add( + new RuntimeVisibleAnnotations(rvaIndex,rvaData.length,new DataInputStream(new ByteArrayInputStream(rvaData)),cp.getConstantPool())); + } + if (riaData.length>2) { + newAttributes.add( + new RuntimeInvisibleAnnotations(riaIndex,riaData.length,new DataInputStream(new ByteArrayInputStream(riaData)),cp.getConstantPool())); + } + + return (Attribute[])newAttributes.toArray(new Attribute[newAttributes.size()]); + } catch (IOException e) { + System.err.println("IOException whilst processing annotations"); + e.printStackTrace(); + } + return null; + } + + + /** + * Annotations against a class are stored in one of four attribute kinds: + * - RuntimeVisibleParameterAnnotations + * - RuntimeInvisibleParameterAnnotations + */ + public static Attribute[] getParameterAnnotationAttributes( + ConstantPoolGen cp, + List[] /*Array of lists, array size depends on #params */vec) + { + int visCount[] = new int[vec.length]; + int totalVisCount = 0; + int invisCount[] = new int[vec.length]; + int totalInvisCount = 0; + try + { + for (int i = 0; i < vec.length; i++) + { + List l = vec[i]; + if (l != null) + { + for (Iterator iter = l.iterator(); iter.hasNext();) + { + AnnotationEntryGen element = (AnnotationEntryGen) iter.next(); + if (element.isRuntimeVisible()) + { + visCount[i]++; + totalVisCount++; + } + else + { + invisCount[i]++; + totalInvisCount++; + } + } + } + } + // Lets do the visible ones + ByteArrayOutputStream rvaBytes = new ByteArrayOutputStream(); + DataOutputStream rvaDos = new DataOutputStream(rvaBytes); + rvaDos.writeByte(vec.length); // First goes number of parameters + for (int i = 0; i < vec.length; i++) + { + rvaDos.writeShort(visCount[i]); + if (visCount[i] > 0) + { + List l = vec[i]; + for (Iterator iter = l.iterator(); iter.hasNext();) + { + AnnotationEntryGen element = (AnnotationEntryGen) iter.next(); + if (element.isRuntimeVisible()) + element.dump(rvaDos); + } + } + } + rvaDos.close(); + // Lets do the invisible ones + ByteArrayOutputStream riaBytes = new ByteArrayOutputStream(); + DataOutputStream riaDos = new DataOutputStream(riaBytes); + riaDos.writeByte(vec.length); // First goes number of parameters + for (int i = 0; i < vec.length; i++) + { + riaDos.writeShort(invisCount[i]); + if (invisCount[i] > 0) + { + List l = vec[i]; + for (Iterator iter = l.iterator(); iter.hasNext();) + { + AnnotationEntryGen element = (AnnotationEntryGen) iter.next(); + if (!element.isRuntimeVisible()) + element.dump(riaDos); + } + } + } + riaDos.close(); + byte[] rvaData = rvaBytes.toByteArray(); + byte[] riaData = riaBytes.toByteArray(); + int rvaIndex = -1; + int riaIndex = -1; + if (totalVisCount > 0) + rvaIndex = cp.addUtf8("RuntimeVisibleParameterAnnotations"); + if (totalInvisCount > 0) + riaIndex = cp.addUtf8("RuntimeInvisibleParameterAnnotations"); + List newAttributes = new ArrayList(); + if (totalVisCount > 0) + { + newAttributes + .add(new RuntimeVisibleParameterAnnotations(rvaIndex, + rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool())); + } + if (totalInvisCount > 0) + { + newAttributes + .add(new RuntimeInvisibleParameterAnnotations(riaIndex, + riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool())); + } + return (Attribute[]) newAttributes.toArray(new Attribute[newAttributes.size()]); + } + catch (IOException e) + { + System.err + .println("IOException whilst processing parameter annotations"); + e.printStackTrace(); + } + return null; + } + +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/Visitor.java b/java/org/apache/tomcat/util/bcel/classfile/Visitor.java new file mode 100644 index 000000000..1d8305f11 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/Visitor.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.classfile; + +/** + * Interface to make use of the Visitor pattern programming style. I.e. a class + * that implements this interface can traverse the contents of a Java class just + * by calling the `accept' method which all classes have. + * + * @version $Id$ + * @author M. Dahm + */ +public interface Visitor +{ + public void visitCode(Code obj); + + public void visitCodeException(CodeException obj); + + public void visitConstantClass(ConstantClass obj); + + public void visitConstantDouble(ConstantDouble obj); + + public void visitConstantFieldref(ConstantFieldref obj); + + public void visitConstantFloat(ConstantFloat obj); + + public void visitConstantInteger(ConstantInteger obj); + + public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj); + + public void visitConstantLong(ConstantLong obj); + + public void visitConstantMethodref(ConstantMethodref obj); + + public void visitConstantNameAndType(ConstantNameAndType obj); + + public void visitConstantPool(ConstantPool obj); + + public void visitConstantString(ConstantString obj); + + public void visitConstantUtf8(ConstantUtf8 obj); + + public void visitConstantValue(ConstantValue obj); + + public void visitDeprecated(Deprecated obj); + + public void visitExceptionTable(ExceptionTable obj); + + public void visitField(Field obj); + + public void visitInnerClass(InnerClass obj); + + public void visitInnerClasses(InnerClasses obj); + + public void visitJavaClass(JavaClass obj); + + public void visitLineNumber(LineNumber obj); + + public void visitLineNumberTable(LineNumberTable obj); + + public void visitLocalVariable(LocalVariable obj); + + public void visitLocalVariableTable(LocalVariableTable obj); + + public void visitMethod(Method obj); + + public void visitSignature(Signature obj); + + public void visitSourceFile(SourceFile obj); + + public void visitSynthetic(Synthetic obj); + + public void visitUnknown(Unknown obj); + + public void visitStackMap(StackMap obj); + + public void visitStackMapEntry(StackMapEntry obj); + + public void visitStackMapTable(StackMapTable obj); + + public void visitStackMapTableEntry(StackMapTableEntry obj); + + public void visitAnnotation(Annotations obj); + + public void visitParameterAnnotation(ParameterAnnotations obj); + + public void visitAnnotationEntry(AnnotationEntry obj); + + public void visitAnnotationDefault(AnnotationDefault obj); + + public void visitLocalVariableTypeTable(LocalVariableTypeTable obj); + + public void visitEnclosingMethod(EnclosingMethod obj); +} diff --git a/java/org/apache/tomcat/util/bcel/classfile/package.html b/java/org/apache/tomcat/util/bcel/classfile/package.html new file mode 100644 index 000000000..2bf7c28cc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/classfile/package.html @@ -0,0 +1,14 @@ + + + + + + +

      +This package contains the classes that describe the structure of a +Java class file and a class file parser. +

      + + diff --git a/java/org/apache/tomcat/util/bcel/generic/AALOAD.java b/java/org/apache/tomcat/util/bcel/generic/AALOAD.java new file mode 100644 index 000000000..a5a6e845a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/AALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * AALOAD - Load reference from array + *
      Stack: ..., arrayref, index -> value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class AALOAD extends ArrayInstruction implements StackProducer { + + /** Load reference from array + */ + public AALOAD() { + super(org.apache.tomcat.util.bcel.Constants.AALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitAALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/AASTORE.java b/java/org/apache/tomcat/util/bcel/generic/AASTORE.java new file mode 100644 index 000000000..71534ff4d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/AASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * AASTORE - Store into reference array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class AASTORE extends ArrayInstruction implements StackConsumer { + + /** Store into reference array + */ + public AASTORE() { + super(org.apache.tomcat.util.bcel.Constants.AASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitAASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ACONST_NULL.java b/java/org/apache/tomcat/util/bcel/generic/ACONST_NULL.java new file mode 100644 index 000000000..6b68d0ea2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ACONST_NULL.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ACONST_NULL - Push null reference + *
      Stack: ... -> ..., null
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ACONST_NULL extends Instruction implements PushInstruction, TypedInstruction { + + /** + * Push null reference + */ + public ACONST_NULL() { + super(org.apache.tomcat.util.bcel.Constants.ACONST_NULL, (short) 1); + } + + + /** @return Type.NULL + */ + public Type getType( ConstantPoolGen cp ) { + return Type.NULL; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitTypedInstruction(this); + v.visitACONST_NULL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ALOAD.java b/java/org/apache/tomcat/util/bcel/generic/ALOAD.java new file mode 100644 index 000000000..810336897 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ALOAD.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ALOAD - Load reference from local variable + *
      Stack: ... -> ..., objectref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ALOAD extends LoadInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ALOAD() { + super(org.apache.tomcat.util.bcel.Constants.ALOAD, org.apache.tomcat.util.bcel.Constants.ALOAD_0); + } + + + /** Load reference from local variable + * @param n index of local variable + */ + public ALOAD(int n) { + super(org.apache.tomcat.util.bcel.Constants.ALOAD, org.apache.tomcat.util.bcel.Constants.ALOAD_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ANEWARRAY.java b/java/org/apache/tomcat/util/bcel/generic/ANEWARRAY.java new file mode 100644 index 000000000..a35927703 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ANEWARRAY.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * ANEWARRAY - Create new array of references + *
      Stack: ..., count -> ..., arrayref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, + ExceptionThrower, StackConsumer, StackProducer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ANEWARRAY() { + } + + + public ANEWARRAY(int index) { + super(org.apache.tomcat.util.bcel.Constants.ANEWARRAY, index); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[1 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLoadClass(this); + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitANEWARRAY(this); + } + + + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return (t instanceof ObjectType) ? (ObjectType) t : null; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ARETURN.java b/java/org/apache/tomcat/util/bcel/generic/ARETURN.java new file mode 100644 index 000000000..b31ca25f6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ARETURN.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ARETURN - Return reference from method + *
      Stack: ..., objectref -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ARETURN extends ReturnInstruction { + + /** + * Return reference from method + */ + public ARETURN() { + super(org.apache.tomcat.util.bcel.Constants.ARETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitARETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ARRAYLENGTH.java b/java/org/apache/tomcat/util/bcel/generic/ARRAYLENGTH.java new file mode 100644 index 000000000..11592ff4e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ARRAYLENGTH.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ARRAYLENGTH - Get length of array + *
      Stack: ..., arrayref -> ..., length
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer { + + /** Get length of array + */ + public ARRAYLENGTH() { + super(org.apache.tomcat.util.bcel.Constants.ARRAYLENGTH, (short) 1); + } + + + /** @return exceptions this instruction may cause + */ + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitARRAYLENGTH(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ASTORE.java b/java/org/apache/tomcat/util/bcel/generic/ASTORE.java new file mode 100644 index 000000000..43582b754 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ASTORE.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ASTORE - Store reference into local variable + *
      Stack ..., objectref -> ... 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ASTORE extends StoreInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ASTORE() { + super(org.apache.tomcat.util.bcel.Constants.ASTORE, org.apache.tomcat.util.bcel.Constants.ASTORE_0); + } + + + /** Store reference into local variable + * @param n index of local variable + */ + public ASTORE(int n) { + super(org.apache.tomcat.util.bcel.Constants.ASTORE, org.apache.tomcat.util.bcel.Constants.ASTORE_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ATHROW.java b/java/org/apache/tomcat/util/bcel/generic/ATHROW.java new file mode 100644 index 000000000..e187d5b03 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ATHROW.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ATHROW - Throw exception + *
      Stack: ..., objectref -> objectref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower { + + /** + * Throw exception + */ + public ATHROW() { + super(org.apache.tomcat.util.bcel.Constants.ATHROW, (short) 1); + } + + + /** @return exceptions this instruction may cause + */ + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.THROWABLE + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitUnconditionalBranch(this); + v.visitExceptionThrower(this); + v.visitATHROW(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/AllocationInstruction.java b/java/org/apache/tomcat/util/bcel/generic/AllocationInstruction.java new file mode 100644 index 000000000..fd8c32216 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/AllocationInstruction.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote family of instructions that allocates space in the heap. + * + * @version $Id$ + * @author M. Dahm + */ +public interface AllocationInstruction { +} diff --git a/java/org/apache/tomcat/util/bcel/generic/AnnotationElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/AnnotationElementValueGen.java new file mode 100644 index 000000000..dc1a468eb --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/AnnotationElementValueGen.java @@ -0,0 +1,60 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue; +import org.apache.tomcat.util.bcel.classfile.ElementValue; + +public class AnnotationElementValueGen extends ElementValueGen +{ + // For annotation element values, this is the annotation + private AnnotationEntryGen a; + + public AnnotationElementValueGen(AnnotationEntryGen a, ConstantPoolGen cpool) + { + super(ANNOTATION, cpool); + this.a = a; + } + + public AnnotationElementValueGen(int type, AnnotationEntryGen annotation, + ConstantPoolGen cpool) + { + super(type, cpool); + if (type != ANNOTATION) + throw new RuntimeException( + "Only element values of type annotation can be built with this ctor - type specified: " + type); + this.a = annotation; + } + + public AnnotationElementValueGen(AnnotationElementValue value, + ConstantPoolGen cpool, boolean copyPoolEntries) + { + super(ANNOTATION, cpool); + a = new AnnotationEntryGen(value.getAnnotationEntry(), cpool, copyPoolEntries); + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ANNOTATION == '@') + a.dump(dos); + } + + public String stringifyValue() + { + throw new RuntimeException("Not implemented yet"); + } + + /** + * Return immutable variant of this AnnotationElementValueGen + */ + public ElementValue getElementValue() + { + return new AnnotationElementValue(this.type, a.getAnnotation(), cpGen + .getConstantPool()); + } + + public AnnotationEntryGen getAnnotation() + { + return a; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/AnnotationEntryGen.java b/java/org/apache/tomcat/util/bcel/generic/AnnotationEntryGen.java new file mode 100755 index 000000000..ee0d0be40 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/AnnotationEntryGen.java @@ -0,0 +1,190 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ElementValuePair; + + +public class AnnotationEntryGen +{ + private int typeIndex; + + private List /* ElementNameValuePairGen */evs; + + private ConstantPoolGen cpool; + + private boolean isRuntimeVisible = false; + + /** + * Here we are taking a fixed annotation of type Annotation and building a + * modifiable AnnotationGen object. If the pool passed in is for a different + * class file, then copyPoolEntries should have been passed as true as that + * will force us to do a deep copy of the annotation and move the cpool + * entries across. We need to copy the type and the element name value pairs + * and the visibility. + */ + public AnnotationEntryGen(AnnotationEntry a, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + this.cpool = cpool; + if (copyPoolEntries) + { + typeIndex = cpool.addUtf8(a.getAnnotationType()); + } + else + { + typeIndex = a.getAnnotationTypeIndex(); + } + isRuntimeVisible = a.isRuntimeVisible(); + evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries); + } + + private List copyValues(ElementValuePair[] in, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + List out = new ArrayList(); + int l = in.length; + for (int i = 0; i < l; i++) + { + ElementValuePair nvp = (ElementValuePair) in[i]; + out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries)); + } + return out; + } + + private AnnotationEntryGen(ConstantPoolGen cpool) + { + this.cpool = cpool; + } + + /** + * Retrieve an immutable version of this AnnotationGen + */ + public AnnotationEntry getAnnotation() + { + AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(), + isRuntimeVisible); + for (Iterator iter = evs.iterator(); iter.hasNext();) + { + ElementValuePairGen element = (ElementValuePairGen) iter + .next(); + a.addElementNameValuePair(element.getElementNameValuePair()); + } + return a; + } + + public AnnotationEntryGen(ObjectType type, + List /* ElementNameValuePairGen */elements, boolean vis, + ConstantPoolGen cpool) + { + this.cpool = cpool; + this.typeIndex = cpool.addUtf8(type.getSignature()); + evs = elements; + isRuntimeVisible = vis; + } + + public static AnnotationEntryGen read(DataInputStream dis, + ConstantPoolGen cpool, boolean b) throws IOException + { + AnnotationEntryGen a = new AnnotationEntryGen(cpool); + a.typeIndex = dis.readUnsignedShort(); + int elemValuePairCount = dis.readUnsignedShort(); + for (int i = 0; i < elemValuePairCount; i++) + { + int nidx = dis.readUnsignedShort(); + a.addElementNameValuePair(new ElementValuePairGen(nidx, + ElementValueGen.readElementValue(dis, cpool), cpool)); + } + a.isRuntimeVisible(b); + return a; + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeShort(typeIndex); // u2 index of type name in cpool + dos.writeShort(evs.size()); // u2 element_value pair count + for (int i = 0; i < evs.size(); i++) + { + ElementValuePairGen envp = (ElementValuePairGen) evs.get(i); + envp.dump(dos); + } + } + + public void addElementNameValuePair(ElementValuePairGen evp) + { + if (evs == null) + evs = new ArrayList(); + evs.add(evp); + } + + public int getTypeIndex() + { + return typeIndex; + } + + public final String getTypeSignature() + { + // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); + ConstantUtf8 utf8 = (ConstantUtf8) cpool + .getConstant(typeIndex/* c.getNameIndex() */); + return utf8.getBytes(); + } + + public final String getTypeName() + { + return getTypeSignature();// BCELBUG: Should I use this instead? + // Utility.signatureToString(getTypeSignature()); + } + + /** + * Returns list of ElementNameValuePair objects + */ + public List getValues() + { + return evs; + } + + public String toString() + { + StringBuffer s = new StringBuffer(); + s.append("AnnotationGen:[" + getTypeName() + " #" + evs.size() + " {"); + for (int i = 0; i < evs.size(); i++) + { + s.append(evs.get(i)); + if (i + 1 < evs.size()) + s.append(","); + } + s.append("}]"); + return s.toString(); + } + + public String toShortString() + { + StringBuffer s = new StringBuffer(); + s.append("@" + getTypeName() + "("); + for (int i = 0; i < evs.size(); i++) + { + s.append(evs.get(i)); + if (i + 1 < evs.size()) + s.append(","); + } + s.append(")"); + return s.toString(); + } + + private void isRuntimeVisible(boolean b) + { + isRuntimeVisible = b; + } + + public boolean isRuntimeVisible() + { + return isRuntimeVisible; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ArithmeticInstruction.java b/java/org/apache/tomcat/util/bcel/generic/ArithmeticInstruction.java new file mode 100644 index 000000000..1337f63c5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ArithmeticInstruction.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Super class for the family of arithmetic instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class ArithmeticInstruction extends Instruction implements TypedInstruction, + StackProducer, StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ArithmeticInstruction() { + } + + + /** + * @param opcode of instruction + */ + protected ArithmeticInstruction(short opcode) { + super(opcode, (short) 1); + } + + + /** @return type associated with the instruction + */ + public Type getType( ConstantPoolGen cp ) { + switch (opcode) { + case Constants.DADD: + case Constants.DDIV: + case Constants.DMUL: + case Constants.DNEG: + case Constants.DREM: + case Constants.DSUB: + return Type.DOUBLE; + case Constants.FADD: + case Constants.FDIV: + case Constants.FMUL: + case Constants.FNEG: + case Constants.FREM: + case Constants.FSUB: + return Type.FLOAT; + case Constants.IADD: + case Constants.IAND: + case Constants.IDIV: + case Constants.IMUL: + case Constants.INEG: + case Constants.IOR: + case Constants.IREM: + case Constants.ISHL: + case Constants.ISHR: + case Constants.ISUB: + case Constants.IUSHR: + case Constants.IXOR: + return Type.INT; + case Constants.LADD: + case Constants.LAND: + case Constants.LDIV: + case Constants.LMUL: + case Constants.LNEG: + case Constants.LOR: + case Constants.LREM: + case Constants.LSHL: + case Constants.LSHR: + case Constants.LSUB: + case Constants.LUSHR: + case Constants.LXOR: + return Type.LONG; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ArrayElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/ArrayElementValueGen.java new file mode 100644 index 000000000..f05b14907 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ArrayElementValueGen.java @@ -0,0 +1,109 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.tomcat.util.bcel.classfile.ArrayElementValue; +import org.apache.tomcat.util.bcel.classfile.ElementValue; + +public class ArrayElementValueGen extends ElementValueGen +{ + // J5TODO: Should we make this an array or a list? A list would be easier to + // modify ... + private List /* ElementValueGen */evalues; + + public ArrayElementValueGen(ConstantPoolGen cp) + { + super(ARRAY, cp); + evalues = new ArrayList(); + } + + public ArrayElementValueGen(int type, ElementValue[] datums, + ConstantPoolGen cpool) + { + super(type, cpool); + if (type != ARRAY) + throw new RuntimeException( + "Only element values of type array can be built with this ctor - type specified: " + type); + this.evalues = new ArrayList(); + for (int i = 0; i < datums.length; i++) + { + evalues.add(datums[i]); + } + } + + /** + * Return immutable variant of this ArrayElementValueGen + */ + public ElementValue getElementValue() + { + ElementValue[] immutableData = new ElementValue[evalues.size()]; + int i = 0; + for (Iterator iter = evalues.iterator(); iter.hasNext();) + { + ElementValueGen element = (ElementValueGen) iter.next(); + immutableData[i++] = element.getElementValue(); + } + return new ArrayElementValue(type, immutableData, cpGen + .getConstantPool()); + } + + /** + * @param value + * @param cpool + */ + public ArrayElementValueGen(ArrayElementValue value, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + super(ARRAY, cpool); + evalues = new ArrayList(); + ElementValue[] in = value.getElementValuesArray(); + for (int i = 0; i < in.length; i++) + { + evalues.add(ElementValueGen.copy(in[i], cpool, copyPoolEntries)); + } + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ARRAY == '[') + dos.writeShort(evalues.size()); + for (Iterator iter = evalues.iterator(); iter.hasNext();) + { + ElementValueGen element = (ElementValueGen) iter.next(); + element.dump(dos); + } + } + + public String stringifyValue() + { + StringBuffer sb = new StringBuffer(); + sb.append("["); + for (Iterator iter = evalues.iterator(); iter.hasNext();) + { + ElementValueGen element = (ElementValueGen) iter.next(); + sb.append(element.stringifyValue()); + if (iter.hasNext()) + sb.append(","); + } + sb.append("]"); + return sb.toString(); + } + + public List getElementValues() + { + return evalues; + } + + public int getElementValuesSize() + { + return evalues.size(); + } + + public void addElement(ElementValueGen gen) + { + evalues.add(gen); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ArrayInstruction.java b/java/org/apache/tomcat/util/bcel/generic/ArrayInstruction.java new file mode 100644 index 000000000..ac358d988 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ArrayInstruction.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Super class for instructions dealing with array access such as IALOAD. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class ArrayInstruction extends Instruction implements ExceptionThrower, + TypedInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ArrayInstruction() { + } + + + /** + * @param opcode of instruction + */ + protected ArrayInstruction(short opcode) { + super(opcode, (short) 1); + } + + + public Class[] getExceptions() { + return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_ARRAY_EXCEPTION; + } + + + /** @return type associated with the instruction + */ + public Type getType( ConstantPoolGen cp ) { + switch (opcode) { + case org.apache.tomcat.util.bcel.Constants.IALOAD: + case org.apache.tomcat.util.bcel.Constants.IASTORE: + return Type.INT; + case org.apache.tomcat.util.bcel.Constants.CALOAD: + case org.apache.tomcat.util.bcel.Constants.CASTORE: + return Type.CHAR; + case org.apache.tomcat.util.bcel.Constants.BALOAD: + case org.apache.tomcat.util.bcel.Constants.BASTORE: + return Type.BYTE; + case org.apache.tomcat.util.bcel.Constants.SALOAD: + case org.apache.tomcat.util.bcel.Constants.SASTORE: + return Type.SHORT; + case org.apache.tomcat.util.bcel.Constants.LALOAD: + case org.apache.tomcat.util.bcel.Constants.LASTORE: + return Type.LONG; + case org.apache.tomcat.util.bcel.Constants.DALOAD: + case org.apache.tomcat.util.bcel.Constants.DASTORE: + return Type.DOUBLE; + case org.apache.tomcat.util.bcel.Constants.FALOAD: + case org.apache.tomcat.util.bcel.Constants.FASTORE: + return Type.FLOAT; + case org.apache.tomcat.util.bcel.Constants.AALOAD: + case org.apache.tomcat.util.bcel.Constants.AASTORE: + return Type.OBJECT; + default: + throw new ClassGenException("Oops: unknown case in switch" + opcode); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ArrayType.java b/java/org/apache/tomcat/util/bcel/generic/ArrayType.java new file mode 100644 index 000000000..58088a40d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ArrayType.java @@ -0,0 +1,127 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Denotes array type, such as int[][] + * + * @version $Id$ + * @author M. Dahm + */ +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, ""); + if ((dimensions < 1) || (dimensions > Constants.MAX_BYTE)) { + throw new ClassGenException("Invalid number of dimensions: " + dimensions); + } + switch (type.getType()) { + case Constants.T_ARRAY: + ArrayType array = (ArrayType) type; + this.dimensions = dimensions + array.dimensions; + basic_type = array.basic_type; + break; + case Constants.T_VOID: + throw new ClassGenException("Invalid type: void[]"); + default: // Basic type or reference + this.dimensions = dimensions; + basic_type = type; + break; + } + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < this.dimensions; i++) { + buf.append('['); + } + buf.append(basic_type.getSignature()); + signature = buf.toString(); + } + + + /** + * @return basic type of array, i.e., for int[][][] the basic type is int + */ + public Type getBasicType() { + return basic_type; + } + + + /** + * @return element type of array, i.e., for int[][][] the element type is int[][] + */ + public Type getElementType() { + if (dimensions == 1) { + return basic_type; + } + return new ArrayType(basic_type, dimensions - 1); + } + + + /** @return number of dimensions of array + */ + public int getDimensions() { + return dimensions; + } + + + /** @return a hash code value for the object. + */ + public int hashCode() { + return basic_type.hashCode() ^ dimensions; + } + + + /** @return true if both type objects refer to the same array type. + */ + public boolean equals( Object _type ) { + if (_type instanceof ArrayType) { + ArrayType array = (ArrayType) _type; + return (array.dimensions == dimensions) && array.basic_type.equals(basic_type); + } + return false; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BALOAD.java b/java/org/apache/tomcat/util/bcel/generic/BALOAD.java new file mode 100644 index 000000000..38d9c7b1b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * BALOAD - Load byte or boolean from array + *
      Stack: ..., arrayref, index -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class BALOAD extends ArrayInstruction implements StackProducer { + + /** Load byte or boolean from array + */ + public BALOAD() { + super(org.apache.tomcat.util.bcel.Constants.BALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitBALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BASTORE.java b/java/org/apache/tomcat/util/bcel/generic/BASTORE.java new file mode 100644 index 000000000..09726a447 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * BASTORE - Store into byte or boolean array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class BASTORE extends ArrayInstruction implements StackConsumer { + + /** Store byte or boolean into array + */ + public BASTORE() { + super(org.apache.tomcat.util.bcel.Constants.BASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitBASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BIPUSH.java b/java/org/apache/tomcat/util/bcel/generic/BIPUSH.java new file mode 100644 index 000000000..a9474a9b3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BIPUSH.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * BIPUSH - Push byte on stack + * + *
      Stack: ... -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class BIPUSH extends Instruction implements ConstantPushInstruction { + + private byte b; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + BIPUSH() { + } + + + /** Push byte on stack + */ + public BIPUSH(byte b) { + super(org.apache.tomcat.util.bcel.Constants.BIPUSH, (short) 2); + this.b = b; + } + + + /** + * Dump instruction as byte code to stream out. + */ + public void dump( DataOutputStream out ) throws IOException { + super.dump(out); + out.writeByte(b); + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + b; + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + length = 2; + b = bytes.readByte(); + } + + + public Number getValue() { + return new Integer(b); + } + + + /** @return Type.BYTE + */ + public Type getType( ConstantPoolGen cp ) { + return Type.BYTE; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitBIPUSH(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BREAKPOINT.java b/java/org/apache/tomcat/util/bcel/generic/BREAKPOINT.java new file mode 100644 index 000000000..f3454bf29 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BREAKPOINT.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * BREAKPOINT, JVM dependent, ignored by default + * + * @version $Id$ + * @author M. Dahm + */ +public class BREAKPOINT extends Instruction { + + public BREAKPOINT() { + super(org.apache.tomcat.util.bcel.Constants.BREAKPOINT, (short) 1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitBREAKPOINT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BasicType.java b/java/org/apache/tomcat/util/bcel/generic/BasicType.java new file mode 100644 index 000000000..8445f6a5f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BasicType.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Denotes basic type such as int. + * + * @version $Id$ + * @author M. Dahm + */ +public final class BasicType extends Type { + + /** + * Constructor for basic types such as int, long, `void' + * + * @param type one of T_INT, T_BOOLEAN, ..., T_VOID + * @see org.apache.tomcat.util.bcel.Constants + */ + BasicType(byte type) { + super(type, Constants.SHORT_TYPE_NAMES[type]); + if ((type < Constants.T_BOOLEAN) || (type > Constants.T_VOID)) { + throw new ClassGenException("Invalid type: " + type); + } + } + + + public static final BasicType getType( byte type ) { + switch (type) { + case Constants.T_VOID: + return VOID; + case Constants.T_BOOLEAN: + return BOOLEAN; + case Constants.T_BYTE: + return BYTE; + case Constants.T_SHORT: + return SHORT; + case Constants.T_CHAR: + return CHAR; + case Constants.T_INT: + return INT; + case Constants.T_LONG: + return LONG; + case Constants.T_DOUBLE: + return DOUBLE; + case Constants.T_FLOAT: + return FLOAT; + default: + throw new ClassGenException("Invalid type: " + type); + } + } + + + /** @return a hash code value for the object. + */ + public int hashCode() { + return type; + } + + + /** @return true if both type objects refer to the same type + */ + public boolean equals( Object _type ) { + return (_type instanceof BasicType) ? ((BasicType) _type).type == this.type : false; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BranchHandle.java b/java/org/apache/tomcat/util/bcel/generic/BranchHandle.java new file mode 100644 index 000000000..bd436d952 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BranchHandle.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * BranchHandle is returned by specialized InstructionList.append() whenever a + * BranchInstruction is appended. This is useful when the target of this + * instruction is not known at time of creation and must be set later + * via setTarget(). + * + * @see InstructionHandle + * @see Instruction + * @see InstructionList + * @version $Id$ + * @author M. Dahm + */ +public final class BranchHandle extends InstructionHandle { + + private BranchInstruction bi; // An alias in fact, but saves lots of casts + + + private BranchHandle(BranchInstruction i) { + super(i); + bi = i; + } + + /** Factory methods. + */ + private static BranchHandle bh_list = null; // List of reusable handles + + + static final BranchHandle getBranchHandle( BranchInstruction i ) { + if (bh_list == null) { + return new BranchHandle(i); + } + BranchHandle bh = bh_list; + bh_list = (BranchHandle) bh.next; + bh.setInstruction(i); + return bh; + } + + + /** Handle adds itself to the list of resuable handles. + */ + protected void addHandle() { + next = bh_list; + bh_list = this; + } + + + /* Override InstructionHandle methods: delegate to branch instruction. + * Through this overriding all access to the private i_position field should + * be prevented. + */ + public int getPosition() { + return bi.position; + } + + + void setPosition( int pos ) { + i_position = bi.position = pos; + } + + + protected int updatePosition( int offset, int max_offset ) { + int x = bi.updatePosition(offset, max_offset); + i_position = bi.position; + return x; + } + + + /** + * Pass new target to instruction. + */ + public void setTarget( InstructionHandle ih ) { + bi.setTarget(ih); + } + + + /** + * Update target of instruction. + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + bi.updateTarget(old_ih, new_ih); + } + + + /** + * @return target of instruction. + */ + public InstructionHandle getTarget() { + return bi.getTarget(); + } + + + /** + * Set new contents. Old instruction is disposed and may not be used anymore. + */ + public void setInstruction( Instruction i ) { + super.setInstruction(i); + if (!(i instanceof BranchInstruction)) { + throw new ClassGenException("Assigning " + i + + " to branch handle which is not a branch instruction"); + } + bi = (BranchInstruction) i; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/BranchInstruction.java b/java/org/apache/tomcat/util/bcel/generic/BranchInstruction.java new file mode 100644 index 000000000..3f2c2e76f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/BranchInstruction.java @@ -0,0 +1,230 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Abstract super class for branching instructions like GOTO, IFEQ, etc.. + * Branch instructions may have a variable length, namely GOTO, JSR, + * LOOKUPSWITCH and TABLESWITCH. + * + * @see InstructionList + * @version $Id$ + * @author M. Dahm + */ +public abstract class BranchInstruction extends Instruction implements InstructionTargeter { + + protected int index; // Branch target relative to this instruction + protected InstructionHandle target; // Target object in instruction list + protected int position; // Byte code offset + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + BranchInstruction() { + } + + + /** Common super constructor + * @param opcode Instruction opcode + * @param target instruction to branch to + */ + protected BranchInstruction(short opcode, InstructionHandle target) { + super(opcode, (short) 3); + setTarget(target); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + index = getTargetOffset(); + if (Math.abs(index) >= 32767) { + throw new ClassGenException("Branch target offset too large for short: " + index); + } + out.writeShort(index); // May be negative, i.e., point backwards + } + + + /** + * @param _target branch target + * @return the offset to `target' relative to this instruction + */ + protected int getTargetOffset( InstructionHandle _target ) { + if (_target == null) { + throw new ClassGenException("Target of " + super.toString(true) + + " is invalid null handle"); + } + int t = _target.getPosition(); + if (t < 0) { + throw new ClassGenException("Invalid branch target position offset for " + + super.toString(true) + ":" + t + ":" + _target); + } + return t - position; + } + + + /** + * @return the offset to this instruction's target + */ + protected int getTargetOffset() { + return getTargetOffset(target); + } + + + /** + * Called by InstructionList.setPositions when setting the position for every + * instruction. In the presence of variable length instructions `setPositions' + * performs multiple passes over the instruction list to calculate the + * correct (byte) positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param max_offset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + protected int updatePosition( int offset, int max_offset ) { + position += offset; + return 0; + } + + + /** + * Long output format: + * + * <position in byte code> + * <name of opcode> "["<opcode number>"]" + * "("<length of instruction>")" + * "<"<target instruction>">" "@"<branch target offset> + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + String s = super.toString(verbose); + String t = "null"; + if (verbose) { + if (target != null) { + if (target.getInstruction() == this) { + t = ""; + } else if (target.getInstruction() == null) { + t = ""; + } else { + t = target.getInstruction().toString(false); // Avoid circles + } + } + } else { + if (target != null) { + index = getTargetOffset(); + t = "" + (index + position); + } + } + return s + " -> " + t; + } + + + /** + * Read needed data (e.g. index) from file. Conversion to a InstructionHandle + * is done in InstructionList(byte[]). + * + * @param bytes input stream + * @param wide wide prefix? + * @see InstructionList + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + length = 3; + index = bytes.readShort(); + } + + + /** + * @return target offset in byte code + */ + public final int getIndex() { + return index; + } + + + /** + * @return target of branch instruction + */ + public InstructionHandle getTarget() { + return target; + } + + + /** + * Set branch target + * @param target branch target + */ + public void setTarget( InstructionHandle target ) { + notifyTarget(this.target, target, this); + this.target = target; + } + + + /** + * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen + */ + static final void notifyTarget( InstructionHandle old_ih, InstructionHandle new_ih, + InstructionTargeter t ) { + if (old_ih != null) { + old_ih.removeTargeter(t); + } + if (new_ih != null) { + new_ih.addTargeter(t); + } + } + + + /** + * @param old_ih old target + * @param new_ih new target + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + if (target == old_ih) { + setTarget(new_ih); + } else { + throw new ClassGenException("Not targeting " + old_ih + ", but " + target); + } + } + + + /** + * @return true, if ih is target of this instruction + */ + public boolean containsTarget( InstructionHandle ih ) { + return (target == ih); + } + + + /** + * Inform target that it's not targeted anymore. + */ + void dispose() { + setTarget(null); + index = -1; + position = -1; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CALOAD.java b/java/org/apache/tomcat/util/bcel/generic/CALOAD.java new file mode 100644 index 000000000..e777965b9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * CALOAD - Load char from array + *
      Stack: ..., arrayref, index -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class CALOAD extends ArrayInstruction implements StackProducer { + + /** Load char from array + */ + public CALOAD() { + super(org.apache.tomcat.util.bcel.Constants.CALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitCALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CASTORE.java b/java/org/apache/tomcat/util/bcel/generic/CASTORE.java new file mode 100644 index 000000000..060f35bbc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * CASTORE - Store into char array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class CASTORE extends ArrayInstruction implements StackConsumer { + + /** Store char into array + */ + public CASTORE() { + super(org.apache.tomcat.util.bcel.Constants.CASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitCASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CHECKCAST.java b/java/org/apache/tomcat/util/bcel/generic/CHECKCAST.java new file mode 100644 index 000000000..181a3c020 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CHECKCAST.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * CHECKCAST - Check whether object is of given type + *
      Stack: ..., objectref -> ..., objectref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class CHECKCAST extends CPInstruction implements LoadClass, ExceptionThrower, StackProducer, + StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + CHECKCAST() { + } + + + /** Check whether object is of given type + * @param index index to class in constant pool + */ + public CHECKCAST(int index) { + super(org.apache.tomcat.util.bcel.Constants.CHECKCAST, index); + } + + + /** @return exceptions this instruction may cause + */ + public Class[] getExceptions() { + Class[] cs = new Class[1 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.CLASS_CAST_EXCEPTION; + return cs; + } + + + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return (t instanceof ObjectType) ? (ObjectType) t : null; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLoadClass(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitCHECKCAST(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CPInstruction.java b/java/org/apache/tomcat/util/bcel/generic/CPInstruction.java new file mode 100644 index 000000000..eaf3e16fe --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CPInstruction.java @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.classfile.ConstantClass; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Abstract super class for instructions that use an index into the + * constant pool such as LDC, INVOKEVIRTUAL, etc. + * + * @see ConstantPoolGen + * @see LDC + * @see INVOKEVIRTUAL + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class CPInstruction extends Instruction implements TypedInstruction, + IndexedInstruction { + + protected int index; // index to constant pool + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + CPInstruction() { + } + + + /** + * @param index to constant pool + */ + protected CPInstruction(short opcode, int index) { + super(opcode, (short) 3); + setIndex(index); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + } + + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" + * "("<length of instruction>")" "<"< constant pool index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + index; + } + + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString( ConstantPool cp ) { + Constant c = cp.getConstant(index); + String str = cp.constantToString(c); + if (c instanceof ConstantClass) { + str = str.replace('.', '/'); + } + return org.apache.tomcat.util.bcel.Constants.OPCODE_NAMES[opcode] + " " + str; + } + + + /** + * Read needed data (i.e., index) from file. + * @param bytes input stream + * @param wide wide prefix? + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + setIndex(bytes.readUnsignedShort()); + length = 3; + } + + + /** + * @return index in constant pool referred by this instruction. + */ + public final int getIndex() { + return index; + } + + + /** + * Set the index to constant pool. + * @param index in constant pool. + */ + public void setIndex( int index ) { + if (index < 0) { + throw new ClassGenException("Negative index value: " + index); + } + this.index = index; + } + + + /** @return type related with this instruction. + */ + public Type getType( ConstantPoolGen cpg ) { + ConstantPool cp = cpg.getConstantPool(); + String name = cp.getConstantString(index, org.apache.tomcat.util.bcel.Constants.CONSTANT_Class); + if (!name.startsWith("[")) { + name = "L" + name + ";"; + } + return Type.getType(name); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ClassElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/ClassElementValueGen.java new file mode 100644 index 000000000..0910815a1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ClassElementValueGen.java @@ -0,0 +1,80 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ClassElementValue; +import org.apache.tomcat.util.bcel.generic.ConstantPoolGen; +import org.apache.tomcat.util.bcel.generic.ObjectType; +import org.apache.tomcat.util.bcel.generic.ElementValueGen; + +public class ClassElementValueGen extends ElementValueGen +{ + // For primitive types and string type, this points to the value entry in + // the cpool + // For 'class' this points to the class entry in the cpool + private int idx; + + protected ClassElementValueGen(int typeIdx, ConstantPoolGen cpool) + { + super(ElementValueGen.CLASS, cpool); + this.idx = typeIdx; + } + + public ClassElementValueGen(ObjectType t, ConstantPoolGen cpool) + { + super(ElementValueGen.CLASS, cpool); + // this.idx = cpool.addClass(t); + idx = cpool.addUtf8(t.getSignature()); + } + + /** + * Return immutable variant of this ClassElementValueGen + */ + public ElementValue getElementValue() + { + return new ClassElementValue(type, idx, cpGen.getConstantPool()); + } + + public ClassElementValueGen(ClassElementValue value, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + super(CLASS, cpool); + if (copyPoolEntries) + { + // idx = cpool.addClass(value.getClassString()); + idx = cpool.addUtf8(value.getClassString()); + } + else + { + idx = value.getIndex(); + } + } + + public int getIndex() + { + return idx; + } + + public String getClassString() + { + ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); + return cu8.getBytes(); + // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx); + // ConstantUtf8 utf8 = + // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex()); + // return utf8.getBytes(); + } + + public String stringifyValue() + { + return getClassString(); + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 kind of value + dos.writeShort(idx); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ClassGen.java b/java/org/apache/tomcat/util/bcel/generic/ClassGen.java new file mode 100644 index 000000000..e730ff947 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ClassGen.java @@ -0,0 +1,611 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.AccessFlags; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.Annotations; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.Field; +import org.apache.tomcat.util.bcel.classfile.JavaClass; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.RuntimeInvisibleAnnotations; +import org.apache.tomcat.util.bcel.classfile.RuntimeVisibleAnnotations; +import org.apache.tomcat.util.bcel.classfile.SourceFile; +import org.apache.tomcat.util.bcel.classfile.Utility; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * Template class for building up a java class. May be initialized with an + * existing java class (file). + * + * @see JavaClass + * @version $Id$ + * @author M. Dahm + */ +public class ClassGen extends AccessFlags implements Cloneable { + + /* Corresponds to the fields found in a JavaClass object. + */ + private String class_name, super_class_name, file_name; + private int class_name_index = -1, superclass_name_index = -1; + private int major = Constants.MAJOR_1_1, minor = Constants.MINOR_1_1; + private ConstantPoolGen cp; // Template for building up constant pool + // ArrayLists instead of arrays to gather fields, methods, etc. + private List field_vec = new ArrayList(); + private List method_vec = new ArrayList(); + private List attribute_vec = new ArrayList(); + private List interface_vec = new ArrayList(); + private List annotation_vec = new ArrayList(); + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + ClassGen THIS = (ClassGen) o1; + ClassGen THAT = (ClassGen) o2; + return THIS.getClassName().equals(THAT.getClassName()); + } + + + public int hashCode( Object o ) { + ClassGen THIS = (ClassGen) o; + return THIS.getClassName().hashCode(); + } + }; + + + /** Convenience constructor to set up some important values initially. + * + * @param class_name fully qualified class name + * @param super_class_name fully qualified superclass name + * @param file_name source file name + * @param access_flags access qualifiers + * @param interfaces implemented interfaces + * @param cp constant pool to use + */ + public ClassGen(String class_name, String super_class_name, String file_name, int access_flags, + String[] interfaces, ConstantPoolGen cp) { + this.class_name = class_name; + this.super_class_name = super_class_name; + this.file_name = file_name; + this.access_flags = access_flags; + this.cp = cp; + // Put everything needed by default into the constant pool and the vectors + if (file_name != null) { + addAttribute(new SourceFile(cp.addUtf8("SourceFile"), 2, cp.addUtf8(file_name), cp + .getConstantPool())); + } + class_name_index = cp.addClass(class_name); + superclass_name_index = cp.addClass(super_class_name); + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + addInterface(interfaces[i]); + } + } + } + + + /** Convenience constructor to set up some important values initially. + * + * @param class_name fully qualified class name + * @param super_class_name fully qualified superclass name + * @param file_name source file name + * @param access_flags access qualifiers + * @param interfaces implemented interfaces + */ + public ClassGen(String class_name, String super_class_name, String file_name, int access_flags, + String[] interfaces) { + this(class_name, super_class_name, file_name, access_flags, interfaces, + new ConstantPoolGen()); + } + + + /** + * Initialize with existing class. + * @param clazz JavaClass object (e.g. read from file) + */ + public ClassGen(JavaClass clazz) { + class_name_index = clazz.getClassNameIndex(); + superclass_name_index = clazz.getSuperclassNameIndex(); + class_name = clazz.getClassName(); + super_class_name = clazz.getSuperclassName(); + file_name = clazz.getSourceFileName(); + access_flags = clazz.getAccessFlags(); + cp = new ConstantPoolGen(clazz.getConstantPool()); + major = clazz.getMajor(); + minor = clazz.getMinor(); + Attribute[] attributes = clazz.getAttributes(); + // J5TODO: Could make unpacking lazy, done on first reference + AnnotationEntryGen[] annotations = unpackAnnotations(attributes); + Method[] methods = clazz.getMethods(); + Field[] fields = clazz.getFields(); + String[] interfaces = clazz.getInterfaceNames(); + for (int i = 0; i < interfaces.length; i++) { + addInterface(interfaces[i]); + } + for (int i = 0; i < attributes.length; i++) { + if (!(attributes[i] instanceof Annotations)) { + addAttribute(attributes[i]); + } + } + for(int i=0; i < annotations.length; i++) { + addAnnotationEntry(annotations[i]); + } + for (int i = 0; i < methods.length; i++) { + addMethod(methods[i]); + } + for (int i = 0; i < fields.length; i++) { + addField(fields[i]); + } + } + + /** + * Look for attributes representing annotations and unpack them. + */ + private AnnotationEntryGen[] unpackAnnotations(Attribute[] attrs) + { + List /* AnnotationGen */annotationGenObjs = new ArrayList(); + for (int i = 0; i < attrs.length; i++) + { + Attribute attr = attrs[i]; + if (attr instanceof RuntimeVisibleAnnotations) + { + RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; + AnnotationEntry[] annos = rva.getAnnotationEntries(); + for (int j = 0; j < annos.length; j++) + { + AnnotationEntry a = annos[j]; + annotationGenObjs.add(new AnnotationEntryGen(a, + getConstantPool(), false)); + } + } + else + if (attr instanceof RuntimeInvisibleAnnotations) + { + RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; + AnnotationEntry[] annos = ria.getAnnotationEntries(); + for (int j = 0; j < annos.length; j++) + { + AnnotationEntry a = annos[j]; + annotationGenObjs.add(new AnnotationEntryGen(a, + getConstantPool(), false)); + } + } + } + return (AnnotationEntryGen[]) annotationGenObjs + .toArray(new AnnotationEntryGen[annotationGenObjs.size()]); + } + + + /** + * @return the (finally) built up Java class object. + */ + public JavaClass getJavaClass() { + int[] interfaces = getInterfaces(); + Field[] fields = getFields(); + Method[] methods = getMethods(); + Attribute[] attributes = null; + if (annotation_vec.isEmpty()) { + attributes = getAttributes(); + } else { + // TODO: Sometime later, trash any attributes called 'RuntimeVisibleAnnotations' or 'RuntimeInvisibleAnnotations' + Attribute[] annAttributes = Utility.getAnnotationAttributes(cp,annotation_vec); + attributes = new Attribute[attribute_vec.size()+annAttributes.length]; + attribute_vec.toArray(attributes); + System.arraycopy(annAttributes,0,attributes,attribute_vec.size(),annAttributes.length); + } + // Must be last since the above calls may still add something to it + ConstantPool _cp = this.cp.getFinalConstantPool(); + return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, + access_flags, _cp, interfaces, fields, methods, attributes); + } + + + /** + * Add an interface to this class, i.e., this class has to implement it. + * @param name interface to implement (fully qualified class name) + */ + public void addInterface( String name ) { + interface_vec.add(name); + } + + + /** + * Remove an interface from this class. + * @param name interface to remove (fully qualified name) + */ + public void removeInterface( String name ) { + interface_vec.remove(name); + } + + + /** + * @return major version number of class file + */ + public int getMajor() { + return major; + } + + + /** Set major version number of class file, default value is 45 (JDK 1.1) + * @param major major version number + */ + public void setMajor( int major ) { + this.major = major; + } + + + /** Set minor version number of class file, default value is 3 (JDK 1.1) + * @param minor minor version number + */ + public void setMinor( int minor ) { + this.minor = minor; + } + + + /** + * @return minor version number of class file + */ + public int getMinor() { + return minor; + } + + + /** + * Add an attribute to this class. + * @param a attribute to add + */ + public void addAttribute( Attribute a ) { + attribute_vec.add(a); + } + + public void addAnnotationEntry(AnnotationEntryGen a) { + annotation_vec.add(a); + } + + + /** + * Add a method to this class. + * @param m method to add + */ + public void addMethod( Method m ) { + method_vec.add(m); + } + + + /** + * Convenience method. + * + * Add an empty constructor to this class that does nothing but calling super(). + * @param access_flags rights for constructor + */ + public void addEmptyConstructor( int access_flags ) { + InstructionList il = new InstructionList(); + il.append(InstructionConstants.THIS); // Push `this' + il.append(new INVOKESPECIAL(cp.addMethodref(super_class_name, "", "()V"))); + il.append(InstructionConstants.RETURN); + MethodGen mg = new MethodGen(access_flags, Type.VOID, Type.NO_ARGS, null, "", + class_name, il, cp); + mg.setMaxStack(1); + addMethod(mg.getMethod()); + } + + + /** + * Add a field to this class. + * @param f field to add + */ + public void addField( Field f ) { + field_vec.add(f); + } + + + public boolean containsField( Field f ) { + return field_vec.contains(f); + } + + + /** @return field object with given name, or null + */ + public Field containsField( String name ) { + for (Iterator e = field_vec.iterator(); e.hasNext();) { + Field f = (Field) e.next(); + if (f.getName().equals(name)) { + return f; + } + } + return null; + } + + + /** @return method object with given name and signature, or null + */ + public Method containsMethod( String name, String signature ) { + for (Iterator e = method_vec.iterator(); e.hasNext();) { + Method m = (Method) e.next(); + if (m.getName().equals(name) && m.getSignature().equals(signature)) { + return m; + } + } + return null; + } + + + /** + * Remove an attribute from this class. + * @param a attribute to remove + */ + public void removeAttribute( Attribute a ) { + attribute_vec.remove(a); + } + + + /** + * Remove a method from this class. + * @param m method to remove + */ + public void removeMethod( Method m ) { + method_vec.remove(m); + } + + + /** Replace given method with new one. If the old one does not exist + * add the new_ method to the class anyway. + */ + public void replaceMethod( Method old, Method new_ ) { + if (new_ == null) { + throw new ClassGenException("Replacement method must not be null"); + } + int i = method_vec.indexOf(old); + if (i < 0) { + method_vec.add(new_); + } else { + method_vec.set(i, new_); + } + } + + + /** Replace given field with new one. If the old one does not exist + * add the new_ field to the class anyway. + */ + public void replaceField( Field old, Field new_ ) { + if (new_ == null) { + throw new ClassGenException("Replacement method must not be null"); + } + int i = field_vec.indexOf(old); + if (i < 0) { + field_vec.add(new_); + } else { + field_vec.set(i, new_); + } + } + + + /** + * Remove a field to this class. + * @param f field to remove + */ + public void removeField( Field f ) { + field_vec.remove(f); + } + + + public String getClassName() { + return class_name; + } + + + public String getSuperclassName() { + return super_class_name; + } + + + public String getFileName() { + return file_name; + } + + + public void setClassName( String name ) { + class_name = name.replace('/', '.'); + class_name_index = cp.addClass(name); + } + + + public void setSuperclassName( String name ) { + super_class_name = name.replace('/', '.'); + superclass_name_index = cp.addClass(name); + } + + + public Method[] getMethods() { + return (Method[]) method_vec.toArray(new Method[method_vec.size()]); + } + + + public void setMethods( Method[] methods ) { + method_vec.clear(); + for (int m = 0; m < methods.length; m++) { + addMethod(methods[m]); + } + } + + + public void setMethodAt( Method method, int pos ) { + method_vec.set(pos, method); + } + + + public Method getMethodAt( int pos ) { + return (Method) method_vec.get(pos); + } + + + public String[] getInterfaceNames() { + int size = interface_vec.size(); + String[] interfaces = new String[size]; + interface_vec.toArray(interfaces); + return interfaces; + } + + + public int[] getInterfaces() { + int size = interface_vec.size(); + int[] interfaces = new int[size]; + for (int i = 0; i < size; i++) { + interfaces[i] = cp.addClass((String) interface_vec.get(i)); + } + return interfaces; + } + + + public Field[] getFields() { + return (Field[]) field_vec.toArray(new Field[field_vec.size()]); + } + + + public Attribute[] getAttributes() { + return (Attribute[]) attribute_vec.toArray(new Attribute[attribute_vec.size()]); + } + + // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? + public AnnotationEntryGen[] getAnnotationEntries() { + return (AnnotationEntryGen[]) annotation_vec.toArray(new AnnotationEntryGen[annotation_vec.size()]); + } + + + public ConstantPoolGen getConstantPool() { + return cp; + } + + + public void setConstantPool( ConstantPoolGen constant_pool ) { + cp = constant_pool; + } + + + public void setClassNameIndex( int class_name_index ) { + this.class_name_index = class_name_index; + class_name = cp.getConstantPool().getConstantString(class_name_index, + Constants.CONSTANT_Class).replace('/', '.'); + } + + + public void setSuperclassNameIndex( int superclass_name_index ) { + this.superclass_name_index = superclass_name_index; + super_class_name = cp.getConstantPool().getConstantString(superclass_name_index, + Constants.CONSTANT_Class).replace('/', '.'); + } + + + public int getSuperclassNameIndex() { + return superclass_name_index; + } + + + public int getClassNameIndex() { + return class_name_index; + } + + private ArrayList observers; + + + /** Add observer for this object. + */ + public void addObserver( ClassObserver o ) { + if (observers == null) { + observers = new ArrayList(); + } + observers.add(o); + } + + + /** Remove observer for this object. + */ + public void removeObserver( ClassObserver o ) { + if (observers != null) { + observers.remove(o); + } + } + + + /** Call notify() method on all observers. This method is not called + * automatically whenever the state has changed, but has to be + * called by the user after he has finished editing the object. + */ + public void update() { + if (observers != null) { + for (Iterator e = observers.iterator(); e.hasNext();) { + ((ClassObserver) e.next()).notify(this); + } + } + } + + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two ClassGen objects are said to be equal when + * their class names are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the class name. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ClassGenException.java b/java/org/apache/tomcat/util/bcel/generic/ClassGenException.java new file mode 100644 index 000000000..d478259d6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ClassGenException.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Thrown on internal errors. Extends RuntimeException so it hasn't to be declared + * in the throws clause every time. + * + * @version $Id$ + * @author M. Dahm + */ +public class ClassGenException extends RuntimeException { + + public ClassGenException() { + super(); + } + + + public ClassGenException(String s) { + super(s); + } + + public ClassGenException(String s, Throwable initCause) { + super(s, initCause); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ClassObserver.java b/java/org/apache/tomcat/util/bcel/generic/ClassObserver.java new file mode 100644 index 000000000..591bbd9a7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ClassObserver.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Implement this interface if you're interested in changes to a ClassGen object + * and register yourself with addObserver(). + * + * @version $Id$ + * @author M. Dahm + */ +public interface ClassObserver { + + public void notify( ClassGen clazz ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CodeExceptionGen.java b/java/org/apache/tomcat/util/bcel/generic/CodeExceptionGen.java new file mode 100644 index 000000000..fbb466e7b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CodeExceptionGen.java @@ -0,0 +1,184 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.classfile.CodeException; + +/** + * This class represents an exception handler, i.e., specifies the region where + * a handler is active and an instruction where the actual handling is done. + * pool as parameters. Opposed to the JVM specification the end of the handled + * region is set to be inclusive, i.e. all instructions between start and end + * are protected including the start and end instructions (handles) themselves. + * The end of the region is automatically mapped to be exclusive when calling + * getCodeException(), i.e., there is no difference semantically. + * + * @version $Id$ + * @author M. Dahm + * @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.
      + * + * This relies on that the instruction list has already been dumped + * to byte code or or that the `setPositions' methods has been + * called for the instruction list. + * + * @param cp constant pool + */ + public CodeException getCodeException( ConstantPoolGen cp ) { + return new CodeException(start_pc.getPosition(), end_pc.getPosition() + + end_pc.getInstruction().getLength(), handler_pc.getPosition(), + (catch_type == null) ? 0 : cp.addClass(catch_type)); + } + + + /* Set start of handler + * @param start_pc Start of handled region (inclusive) + */ + public void setStartPC( InstructionHandle start_pc ) { + BranchInstruction.notifyTarget(this.start_pc, start_pc, this); + this.start_pc = start_pc; + } + + + /* Set end of handler + * @param end_pc End of handled region (inclusive) + */ + public void setEndPC( InstructionHandle end_pc ) { + BranchInstruction.notifyTarget(this.end_pc, end_pc, this); + this.end_pc = end_pc; + } + + + /* Set handler code + * @param handler_pc Start of handler + */ + public void setHandlerPC( InstructionHandle handler_pc ) { + BranchInstruction.notifyTarget(this.handler_pc, handler_pc, this); + this.handler_pc = handler_pc; + } + + + /** + * @param old_ih old target, either start or end + * @param new_ih new target + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + boolean targeted = false; + if (start_pc == old_ih) { + targeted = true; + setStartPC(new_ih); + } + if (end_pc == old_ih) { + targeted = true; + setEndPC(new_ih); + } + if (handler_pc == old_ih) { + targeted = true; + setHandlerPC(new_ih); + } + if (!targeted) { + throw new ClassGenException("Not targeting " + old_ih + ", but {" + start_pc + ", " + + end_pc + ", " + handler_pc + "}"); + } + } + + + /** + * @return true, if ih is target of this handler + */ + public boolean containsTarget( InstructionHandle ih ) { + return (start_pc == ih) || (end_pc == ih) || (handler_pc == ih); + } + + + /** Sets the type of the Exception to catch. Set 'null' for ANY. */ + public void setCatchType( ObjectType catch_type ) { + this.catch_type = catch_type; + } + + + /** Gets the type of the Exception to catch, 'null' for ANY. */ + public ObjectType getCatchType() { + return catch_type; + } + + + /** @return start of handled region (inclusive) + */ + public InstructionHandle getStartPC() { + return start_pc; + } + + + /** @return end of handled region (inclusive) + */ + public InstructionHandle getEndPC() { + return end_pc; + } + + + /** @return start of handler + */ + public InstructionHandle getHandlerPC() { + return handler_pc; + } + + + public String toString() { + return "CodeExceptionGen(" + start_pc + ", " + end_pc + ", " + handler_pc + ")"; + } + + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/CompoundInstruction.java b/java/org/apache/tomcat/util/bcel/generic/CompoundInstruction.java new file mode 100644 index 000000000..698745fb4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/CompoundInstruction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Wrapper class for `compound' operations, virtual instructions that + * don't exist as byte code, but give a useful meaning. For example, + * the (virtual) PUSH instruction takes an arbitray argument and produces the + * appropiate code at dump time (ICONST, LDC, BIPUSH, ...). Also you can use the + * SWITCH instruction as a useful template for either LOOKUPSWITCH or + * TABLESWITCH. + * + * The interface provides the possibilty for the user to write + * `templates' or `macros' for such reuseable code patterns. + * + * @version $Id$ + * @author M. Dahm + * @see PUSH + * @see SWITCH + */ +public interface CompoundInstruction { + + public InstructionList getInstructionList(); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ConstantPoolGen.java b/java/org/apache/tomcat/util/bcel/generic/ConstantPoolGen.java new file mode 100644 index 000000000..676794cc1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ConstantPoolGen.java @@ -0,0 +1,783 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.HashMap; +import java.util.Map; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.classfile.ConstantCP; +import org.apache.tomcat.util.bcel.classfile.ConstantClass; +import org.apache.tomcat.util.bcel.classfile.ConstantDouble; +import org.apache.tomcat.util.bcel.classfile.ConstantFieldref; +import org.apache.tomcat.util.bcel.classfile.ConstantFloat; +import org.apache.tomcat.util.bcel.classfile.ConstantInteger; +import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantLong; +import org.apache.tomcat.util.bcel.classfile.ConstantMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantString; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; + +/** + * This class is used to build up a constant pool. The user adds + * constants via `addXXX' methods, `addString', `addClass', + * etc.. These methods return an index into the constant + * pool. Finally, `getFinalConstantPool()' returns the constant pool + * built up. Intermediate versions of the constant pool can be + * obtained with `getConstantPool()'. A constant pool has capacity for + * Constants.MAX_SHORT entries. Note that the first (0) is used by the + * JVM and that Double and Long constants need two slots. + * + * @version $Id$ + * @author M. Dahm + * @see Constant + */ +public class ConstantPoolGen implements java.io.Serializable { + + protected int size; + protected Constant[] constants; + protected int index = 1; // First entry (0) used by JVM + private static final String METHODREF_DELIM = ":"; + private static final String IMETHODREF_DELIM = "#"; + private static final String FIELDREF_DELIM = "&"; + private static final String NAT_DELIM = "%"; + + private static class Index implements java.io.Serializable { + + int index; + + + Index(int i) { + index = i; + } + } + + + /** + * Initialize with given array of constants. + * + * @param cs array of given constants, new ones will be appended + */ + public ConstantPoolGen(Constant[] cs) { + StringBuffer sb = new StringBuffer(256); + + size = Math.max(256, cs.length + 64); + constants = new Constant[size]; + + System.arraycopy(cs, 0, constants, 0, cs.length); + if (cs.length > 0) { + index = cs.length; + } + + + for (int i = 1; i < index; i++) { + Constant c = constants[i]; + if (c instanceof ConstantString) { + ConstantString s = (ConstantString) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; + String key = u8.getBytes(); + if (!string_table.containsKey(key)) { + string_table.put(key, new Index(i)); + } + } else if (c instanceof ConstantClass) { + ConstantClass s = (ConstantClass) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; + String key = u8.getBytes(); + if (!class_table.containsKey(key)) { + class_table.put(key, new Index(i)); + } + } else if (c instanceof ConstantNameAndType) { + ConstantNameAndType n = (ConstantNameAndType) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; + ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; + + sb.append(u8.getBytes()); + sb.append(NAT_DELIM); + sb.append(u8_2.getBytes()); + String key = sb.toString(); + sb.delete(0, sb.length()); + + if (!n_a_t_table.containsKey(key)) { + n_a_t_table.put(key, new Index(i)); + } + } else if (c instanceof ConstantUtf8) { + ConstantUtf8 u = (ConstantUtf8) c; + String key = u.getBytes(); + if (!utf8_table.containsKey(key)) { + utf8_table.put(key, new Index(i)); + } + } else if (c instanceof ConstantCP) { + ConstantCP m = (ConstantCP) c; + ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; + ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; + ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; + String class_name = u8.getBytes().replace('/', '.'); + u8 = (ConstantUtf8) constants[n.getNameIndex()]; + String method_name = u8.getBytes(); + u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; + String signature = u8.getBytes(); + String delim = METHODREF_DELIM; + if (c instanceof ConstantInterfaceMethodref) { + delim = IMETHODREF_DELIM; + } else if (c instanceof ConstantFieldref) { + delim = FIELDREF_DELIM; + } + + sb.append(class_name); + sb.append(delim); + sb.append(method_name); + sb.append(delim); + sb.append(signature); + String key = sb.toString(); + sb.delete(0, sb.length()); + + if (!cp_table.containsKey(key)) { + cp_table.put(key, new Index(i)); + } + } + } + } + + + /** + * Initialize with given constant pool. + */ + public ConstantPoolGen(ConstantPool cp) { + this(cp.getConstantPool()); + } + + + /** + * Create empty constant pool. + */ + public ConstantPoolGen() { + size = 256; + constants = new Constant[size]; + } + + + /** Resize internal array of constants. + */ + protected void adjustSize() { + if (index + 3 >= size) { + Constant[] cs = constants; + size *= 2; + constants = new Constant[size]; + System.arraycopy(cs, 0, constants, 0, index); + } + } + + private Map string_table = new HashMap(); + + + /** + * Look for ConstantString in ConstantPool containing String `str'. + * + * @param str String to search for + * @return index on success, -1 otherwise + */ + public int lookupString( String str ) { + Index index = (Index) string_table.get(str); + return (index != null) ? index.index : -1; + } + + + /** + * Add a new String constant to the ConstantPool, if it is not already in there. + * + * @param str String to add + * @return index of entry + */ + public int addString( String str ) { + int ret; + if ((ret = lookupString(str)) != -1) { + return ret; // Already in CP + } + int utf8 = addUtf8(str); + adjustSize(); + ConstantString s = new ConstantString(utf8); + ret = index; + constants[index++] = s; + if (!string_table.containsKey(str)) { + string_table.put(str, new Index(ret)); + } + return ret; + } + + private Map class_table = new HashMap(); + + + /** + * Look for ConstantClass in ConstantPool named `str'. + * + * @param str String to search for + * @return index on success, -1 otherwise + */ + public int lookupClass( String str ) { + Index index = (Index) class_table.get(str.replace('.', '/')); + return (index != null) ? index.index : -1; + } + + + private int addClass_( String clazz ) { + int ret; + if ((ret = lookupClass(clazz)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ConstantClass c = new ConstantClass(addUtf8(clazz)); + ret = index; + constants[index++] = c; + if (!class_table.containsKey(clazz)) { + class_table.put(clazz, new Index(ret)); + } + return ret; + } + + + /** + * Add a new Class reference to the ConstantPool, if it is not already in there. + * + * @param str Class to add + * @return index of entry + */ + public int addClass( String str ) { + return addClass_(str.replace('.', '/')); + } + + + /** + * Add a new Class reference to the ConstantPool for a given type. + * + * @param type Class to add + * @return index of entry + */ + public int addClass( ObjectType type ) { + return addClass(type.getClassName()); + } + + + /** + * Add a reference to an array class (e.g. String[][]) as needed by MULTIANEWARRAY + * instruction, e.g. to the ConstantPool. + * + * @param type type of array class + * @return index of entry + */ + public int addArrayClass( ArrayType type ) { + return addClass_(type.getSignature()); + } + + + /** + * Look for ConstantInteger in ConstantPool. + * + * @param n integer number to look for + * @return index on success, -1 otherwise + */ + public int lookupInteger( int n ) { + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantInteger) { + ConstantInteger c = (ConstantInteger) constants[i]; + if (c.getBytes() == n) { + return i; + } + } + } + return -1; + } + + + /** + * Add a new Integer constant to the ConstantPool, if it is not already in there. + * + * @param n integer number to add + * @return index of entry + */ + public int addInteger( int n ) { + int ret; + if ((ret = lookupInteger(n)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ret = index; + constants[index++] = new ConstantInteger(n); + return ret; + } + + + /** + * Look for ConstantFloat in ConstantPool. + * + * @param n Float number to look for + * @return index on success, -1 otherwise + */ + public int lookupFloat( float n ) { + int bits = Float.floatToIntBits(n); + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantFloat) { + ConstantFloat c = (ConstantFloat) constants[i]; + if (Float.floatToIntBits(c.getBytes()) == bits) { + return i; + } + } + } + return -1; + } + + + /** + * Add a new Float constant to the ConstantPool, if it is not already in there. + * + * @param n Float number to add + * @return index of entry + */ + public int addFloat( float n ) { + int ret; + if ((ret = lookupFloat(n)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ret = index; + constants[index++] = new ConstantFloat(n); + return ret; + } + + private Map utf8_table = new HashMap(); + + + /** + * Look for ConstantUtf8 in ConstantPool. + * + * @param n Utf8 string to look for + * @return index on success, -1 otherwise + */ + public int lookupUtf8( String n ) { + Index index = (Index) utf8_table.get(n); + return (index != null) ? index.index : -1; + } + + + /** + * Add a new Utf8 constant to the ConstantPool, if it is not already in there. + * + * @param n Utf8 string to add + * @return index of entry + */ + public int addUtf8( String n ) { + int ret; + if ((ret = lookupUtf8(n)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ret = index; + constants[index++] = new ConstantUtf8(n); + if (!utf8_table.containsKey(n)) { + utf8_table.put(n, new Index(ret)); + } + return ret; + } + + + /** + * Look for ConstantLong in ConstantPool. + * + * @param n Long number to look for + * @return index on success, -1 otherwise + */ + public int lookupLong( long n ) { + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantLong) { + ConstantLong c = (ConstantLong) constants[i]; + if (c.getBytes() == n) { + return i; + } + } + } + return -1; + } + + + /** + * Add a new long constant to the ConstantPool, if it is not already in there. + * + * @param n Long number to add + * @return index of entry + */ + public int addLong( long n ) { + int ret; + if ((ret = lookupLong(n)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ret = index; + constants[index] = new ConstantLong(n); + index += 2; // Wastes one entry according to spec + return ret; + } + + + /** + * Look for ConstantDouble in ConstantPool. + * + * @param n Double number to look for + * @return index on success, -1 otherwise + */ + public int lookupDouble( double n ) { + long bits = Double.doubleToLongBits(n); + for (int i = 1; i < index; i++) { + if (constants[i] instanceof ConstantDouble) { + ConstantDouble c = (ConstantDouble) constants[i]; + if (Double.doubleToLongBits(c.getBytes()) == bits) { + return i; + } + } + } + return -1; + } + + + /** + * Add a new double constant to the ConstantPool, if it is not already in there. + * + * @param n Double number to add + * @return index of entry + */ + public int addDouble( double n ) { + int ret; + if ((ret = lookupDouble(n)) != -1) { + return ret; // Already in CP + } + adjustSize(); + ret = index; + constants[index] = new ConstantDouble(n); + index += 2; // Wastes one entry according to spec + return ret; + } + + private Map n_a_t_table = new HashMap(); + + + /** + * Look for ConstantNameAndType in ConstantPool. + * + * @param name of variable/method + * @param signature of variable/method + * @return index on success, -1 otherwise + */ + public int lookupNameAndType( String name, String signature ) { + Index _index = (Index) n_a_t_table.get(name + NAT_DELIM + signature); + return (_index != null) ? _index.index : -1; + } + + + /** + * Add a new NameAndType constant to the ConstantPool if it is not already + * in there. + * + * @param name Name string to add + * @param signature signature string to add + * @return index of entry + */ + public int addNameAndType( String name, String signature ) { + int ret; + int name_index, signature_index; + if ((ret = lookupNameAndType(name, signature)) != -1) { + return ret; // Already in CP + } + adjustSize(); + name_index = addUtf8(name); + signature_index = addUtf8(signature); + ret = index; + constants[index++] = new ConstantNameAndType(name_index, signature_index); + String key = name + NAT_DELIM + signature; + if (!n_a_t_table.containsKey(key)) { + n_a_t_table.put(key, new Index(ret)); + } + return ret; + } + + private Map cp_table = new HashMap(); + + + /** + * Look for ConstantMethodref in ConstantPool. + * + * @param class_name Where to find method + * @param method_name Guess what + * @param signature return and argument types + * @return index on success, -1 otherwise + */ + public int lookupMethodref( String class_name, String method_name, String signature ) { + Index index = (Index) cp_table.get(class_name + METHODREF_DELIM + method_name + + METHODREF_DELIM + signature); + return (index != null) ? index.index : -1; + } + + + public int lookupMethodref( MethodGen method ) { + return lookupMethodref(method.getClassName(), method.getName(), method.getSignature()); + } + + + /** + * Add a new Methodref constant to the ConstantPool, if it is not already + * in there. + * + * @param class_name class name string to add + * @param method_name method name string to add + * @param signature method signature string to add + * @return index of entry + */ + public int addMethodref( String class_name, String method_name, String signature ) { + int ret, class_index, name_and_type_index; + if ((ret = lookupMethodref(class_name, method_name, signature)) != -1) { + return ret; // Already in CP + } + adjustSize(); + name_and_type_index = addNameAndType(method_name, signature); + class_index = addClass(class_name); + ret = index; + constants[index++] = new ConstantMethodref(class_index, name_and_type_index); + String key = class_name + METHODREF_DELIM + method_name + METHODREF_DELIM + signature; + if (!cp_table.containsKey(key)) { + cp_table.put(key, new Index(ret)); + } + return ret; + } + + + public int addMethodref( MethodGen method ) { + return addMethodref(method.getClassName(), method.getName(), method.getSignature()); + } + + + /** + * Look for ConstantInterfaceMethodref in ConstantPool. + * + * @param class_name Where to find method + * @param method_name Guess what + * @param signature return and argument types + * @return index on success, -1 otherwise + */ + public int lookupInterfaceMethodref( String class_name, String method_name, String signature ) { + Index index = (Index) cp_table.get(class_name + IMETHODREF_DELIM + method_name + + IMETHODREF_DELIM + signature); + return (index != null) ? index.index : -1; + } + + + public int lookupInterfaceMethodref( MethodGen method ) { + return lookupInterfaceMethodref(method.getClassName(), method.getName(), method + .getSignature()); + } + + + /** + * Add a new InterfaceMethodref constant to the ConstantPool, if it is not already + * in there. + * + * @param class_name class name string to add + * @param method_name method name string to add + * @param signature signature string to add + * @return index of entry + */ + public int addInterfaceMethodref( String class_name, String method_name, String signature ) { + int ret, class_index, name_and_type_index; + if ((ret = lookupInterfaceMethodref(class_name, method_name, signature)) != -1) { + return ret; // Already in CP + } + adjustSize(); + class_index = addClass(class_name); + name_and_type_index = addNameAndType(method_name, signature); + ret = index; + constants[index++] = new ConstantInterfaceMethodref(class_index, name_and_type_index); + String key = class_name + IMETHODREF_DELIM + method_name + IMETHODREF_DELIM + signature; + if (!cp_table.containsKey(key)) { + cp_table.put(key, new Index(ret)); + } + return ret; + } + + + public int addInterfaceMethodref( MethodGen method ) { + return addInterfaceMethodref(method.getClassName(), method.getName(), method.getSignature()); + } + + + /** + * Look for ConstantFieldref in ConstantPool. + * + * @param class_name Where to find method + * @param field_name Guess what + * @param signature return and argument types + * @return index on success, -1 otherwise + */ + public int lookupFieldref( String class_name, String field_name, String signature ) { + Index index = (Index) cp_table.get(class_name + FIELDREF_DELIM + field_name + + FIELDREF_DELIM + signature); + return (index != null) ? index.index : -1; + } + + + /** + * Add a new Fieldref constant to the ConstantPool, if it is not already + * in there. + * + * @param class_name class name string to add + * @param field_name field name string to add + * @param signature signature string to add + * @return index of entry + */ + public int addFieldref( String class_name, String field_name, String signature ) { + int ret; + int class_index, name_and_type_index; + if ((ret = lookupFieldref(class_name, field_name, signature)) != -1) { + return ret; // Already in CP + } + adjustSize(); + class_index = addClass(class_name); + name_and_type_index = addNameAndType(field_name, signature); + ret = index; + constants[index++] = new ConstantFieldref(class_index, name_and_type_index); + String key = class_name + FIELDREF_DELIM + field_name + FIELDREF_DELIM + signature; + if (!cp_table.containsKey(key)) { + cp_table.put(key, new Index(ret)); + } + return ret; + } + + + /** + * @param i index in constant pool + * @return constant pool entry at index i + */ + public Constant getConstant( int i ) { + return constants[i]; + } + + + /** + * Use with care! + * + * @param i index in constant pool + * @param c new constant pool entry at index i + */ + public void setConstant( int i, Constant c ) { + constants[i] = c; + } + + + /** + * @return intermediate constant pool + */ + public ConstantPool getConstantPool() { + return new ConstantPool(constants); + } + + + /** + * @return current size of constant pool + */ + public int getSize() { + return index; + } + + + /** + * @return constant pool with proper length + */ + public ConstantPool getFinalConstantPool() { + Constant[] cs = new Constant[index]; + System.arraycopy(constants, 0, cs, 0, index); + return new ConstantPool(cs); + } + + + /** + * @return String representation. + */ + public String toString() { + StringBuffer buf = new StringBuffer(); + for (int i = 1; i < index; i++) { + buf.append(i).append(")").append(constants[i]).append("\n"); + } + return buf.toString(); + } + + + /** Import constant from another ConstantPool and return new index. + */ + public int addConstant( Constant c, ConstantPoolGen cp ) { + Constant[] constants = cp.getConstantPool().getConstantPool(); + switch (c.getTag()) { + case Constants.CONSTANT_String: { + ConstantString s = (ConstantString) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()]; + return addString(u8.getBytes()); + } + case Constants.CONSTANT_Class: { + ConstantClass s = (ConstantClass) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()]; + return addClass(u8.getBytes()); + } + case Constants.CONSTANT_NameAndType: { + ConstantNameAndType n = (ConstantNameAndType) c; + ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()]; + ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()]; + return addNameAndType(u8.getBytes(), u8_2.getBytes()); + } + case Constants.CONSTANT_Utf8: + return addUtf8(((ConstantUtf8) c).getBytes()); + case Constants.CONSTANT_Double: + return addDouble(((ConstantDouble) c).getBytes()); + case Constants.CONSTANT_Float: + return addFloat(((ConstantFloat) c).getBytes()); + case Constants.CONSTANT_Long: + return addLong(((ConstantLong) c).getBytes()); + case Constants.CONSTANT_Integer: + return addInteger(((ConstantInteger) c).getBytes()); + case Constants.CONSTANT_InterfaceMethodref: + case Constants.CONSTANT_Methodref: + case Constants.CONSTANT_Fieldref: { + ConstantCP m = (ConstantCP) c; + ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()]; + ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()]; + ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()]; + String class_name = u8.getBytes().replace('/', '.'); + u8 = (ConstantUtf8) constants[n.getNameIndex()]; + String name = u8.getBytes(); + u8 = (ConstantUtf8) constants[n.getSignatureIndex()]; + String signature = u8.getBytes(); + switch (c.getTag()) { + case Constants.CONSTANT_InterfaceMethodref: + return addInterfaceMethodref(class_name, name, signature); + case Constants.CONSTANT_Methodref: + return addMethodref(class_name, name, signature); + case Constants.CONSTANT_Fieldref: + return addFieldref(class_name, name, signature); + default: // Never reached + throw new RuntimeException("Unknown constant type " + c); + } + } + default: // Never reached + throw new RuntimeException("Unknown constant type " + c); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ConstantPushInstruction.java b/java/org/apache/tomcat/util/bcel/generic/ConstantPushInstruction.java new file mode 100644 index 000000000..7ff35a7b1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ConstantPushInstruction.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes a push instruction that produces a literal on the stack + * such as SIPUSH, BIPUSH, ICONST, etc. + * + * @version $Id$ + * @author M. Dahm + + * @see ICONST + * @see SIPUSH + */ +public interface ConstantPushInstruction extends PushInstruction, TypedInstruction { + + public Number getValue(); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ConversionInstruction.java b/java/org/apache/tomcat/util/bcel/generic/ConversionInstruction.java new file mode 100644 index 000000000..f17b6e045 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ConversionInstruction.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Super class for the x2y family of instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class ConversionInstruction extends Instruction implements TypedInstruction, + StackProducer, StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ConversionInstruction() { + } + + + /** + * @param opcode opcode of instruction + */ + protected ConversionInstruction(short opcode) { + super(opcode, (short) 1); + } + + + /** @return type associated with the instruction + */ + public Type getType( ConstantPoolGen cp ) { + switch (opcode) { + case Constants.D2I: + case Constants.F2I: + case Constants.L2I: + return Type.INT; + case Constants.D2F: + case Constants.I2F: + case Constants.L2F: + return Type.FLOAT; + case Constants.D2L: + case Constants.F2L: + case Constants.I2L: + return Type.LONG; + case Constants.F2D: + case Constants.I2D: + case Constants.L2D: + return Type.DOUBLE; + case Constants.I2B: + return Type.BYTE; + case Constants.I2C: + return Type.CHAR; + case Constants.I2S: + return Type.SHORT; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/D2F.java b/java/org/apache/tomcat/util/bcel/generic/D2F.java new file mode 100644 index 000000000..b3fc3553e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/D2F.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * D2F - Convert double to float + *
      Stack: ..., value.word1, value.word2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class D2F extends ConversionInstruction { + + /** Convert double to float + */ + public D2F() { + super(org.apache.tomcat.util.bcel.Constants.D2F); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitD2F(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/D2I.java b/java/org/apache/tomcat/util/bcel/generic/D2I.java new file mode 100644 index 000000000..d78ed379d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/D2I.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * D2I - Convert double to int + *
      Stack: ..., value.word1, value.word2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class D2I extends ConversionInstruction { + + /** Convert double to int + */ + public D2I() { + super(org.apache.tomcat.util.bcel.Constants.D2I); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitD2I(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/D2L.java b/java/org/apache/tomcat/util/bcel/generic/D2L.java new file mode 100644 index 000000000..6b4c8c170 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/D2L.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * D2L - Convert double to long + *
      Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class D2L extends ConversionInstruction { + + /** Convert double to long + */ + public D2L() { + super(org.apache.tomcat.util.bcel.Constants.D2L); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitD2L(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DADD.java b/java/org/apache/tomcat/util/bcel/generic/DADD.java new file mode 100644 index 000000000..0edba761e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DADD.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DADD - Add doubles + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result1.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class DADD extends ArithmeticInstruction { + + /** Add doubles + */ + public DADD() { + super(org.apache.tomcat.util.bcel.Constants.DADD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDADD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DALOAD.java b/java/org/apache/tomcat/util/bcel/generic/DALOAD.java new file mode 100644 index 000000000..1c3154117 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DALOAD - Load double from array + *
      Stack: ..., arrayref, index -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DALOAD extends ArrayInstruction implements StackProducer { + + /** Load double from array + */ + public DALOAD() { + super(org.apache.tomcat.util.bcel.Constants.DALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitDALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DASTORE.java b/java/org/apache/tomcat/util/bcel/generic/DASTORE.java new file mode 100644 index 000000000..0bacc7142 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DASTORE - Store into double array + *
      Stack: ..., arrayref, index, value.word1, value.word2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DASTORE extends ArrayInstruction implements StackConsumer { + + /** Store double into array + */ + public DASTORE() { + super(org.apache.tomcat.util.bcel.Constants.DASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitDASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DCMPG.java b/java/org/apache/tomcat/util/bcel/generic/DCMPG.java new file mode 100644 index 000000000..0e9aca519 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DCMPG.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DCMPG - Compare doubles: value1 > value2 + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result + * + * @version $Id$ + * @author M. Dahm + */ +public class DCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public DCMPG() { + super(org.apache.tomcat.util.bcel.Constants.DCMPG, (short) 1); + } + + + /** @return Type.DOUBLE + */ + public Type getType( ConstantPoolGen cp ) { + return Type.DOUBLE; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitDCMPG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DCMPL.java b/java/org/apache/tomcat/util/bcel/generic/DCMPL.java new file mode 100644 index 000000000..4ce1572ba --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DCMPL.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DCMPL - Compare doubles: value1 < value2 + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result + * + * @version $Id$ + * @author M. Dahm + */ +public class DCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public DCMPL() { + super(org.apache.tomcat.util.bcel.Constants.DCMPL, (short) 1); + } + + + /** @return Type.DOUBLE + */ + public Type getType( ConstantPoolGen cp ) { + return Type.DOUBLE; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitDCMPL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DCONST.java b/java/org/apache/tomcat/util/bcel/generic/DCONST.java new file mode 100644 index 000000000..00fc1f996 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DCONST.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DCONST - Push 0.0 or 1.0, other values cause an exception + * + *
      Stack: ... -> ..., 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + private double value; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + DCONST() { + } + + + public DCONST(double f) { + super(org.apache.tomcat.util.bcel.Constants.DCONST_0, (short) 1); + if (f == 0.0) { + opcode = org.apache.tomcat.util.bcel.Constants.DCONST_0; + } else if (f == 1.0) { + opcode = org.apache.tomcat.util.bcel.Constants.DCONST_1; + } else { + throw new ClassGenException("DCONST can be used only for 0.0 and 1.0: " + f); + } + value = f; + } + + + public Number getValue() { + return new Double(value); + } + + + /** @return Type.DOUBLE + */ + public Type getType( ConstantPoolGen cp ) { + return Type.DOUBLE; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitDCONST(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DDIV.java b/java/org/apache/tomcat/util/bcel/generic/DDIV.java new file mode 100644 index 000000000..72df39089 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DDIV.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DDIV - Divide doubles + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class DDIV extends ArithmeticInstruction { + + /** Divide doubles + */ + public DDIV() { + super(org.apache.tomcat.util.bcel.Constants.DDIV); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDDIV(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DLOAD.java b/java/org/apache/tomcat/util/bcel/generic/DLOAD.java new file mode 100644 index 000000000..649f13cc8 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DLOAD.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DLOAD - Load double from local variable + *
      Stack ... -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DLOAD extends LoadInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + DLOAD() { + super(org.apache.tomcat.util.bcel.Constants.DLOAD, org.apache.tomcat.util.bcel.Constants.DLOAD_0); + } + + + /** Load double from local variable + * @param n index of local variable + */ + public DLOAD(int n) { + super(org.apache.tomcat.util.bcel.Constants.DLOAD, org.apache.tomcat.util.bcel.Constants.DLOAD_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitDLOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DMUL.java b/java/org/apache/tomcat/util/bcel/generic/DMUL.java new file mode 100644 index 000000000..99d78b792 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DMUL.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DMUL - Multiply doubles + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class DMUL extends ArithmeticInstruction { + + /** Multiply doubles + */ + public DMUL() { + super(org.apache.tomcat.util.bcel.Constants.DMUL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDMUL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DNEG.java b/java/org/apache/tomcat/util/bcel/generic/DNEG.java new file mode 100644 index 000000000..51da4998c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DNEG.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DNEG - Negate double + *
      Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DNEG extends ArithmeticInstruction { + + public DNEG() { + super(org.apache.tomcat.util.bcel.Constants.DNEG); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDNEG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DREM.java b/java/org/apache/tomcat/util/bcel/generic/DREM.java new file mode 100644 index 000000000..a6e03c08f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DREM.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DREM - Remainder of doubles + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class DREM extends ArithmeticInstruction { + + /** Remainder of doubles + */ + public DREM() { + super(org.apache.tomcat.util.bcel.Constants.DREM); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDREM(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DRETURN.java b/java/org/apache/tomcat/util/bcel/generic/DRETURN.java new file mode 100644 index 000000000..23b12bac3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DRETURN.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DRETURN - Return double from method + *
      Stack: ..., value.word1, value.word2 -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DRETURN extends ReturnInstruction { + + /** Return double from method + */ + public DRETURN() { + super(org.apache.tomcat.util.bcel.Constants.DRETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitDRETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DSTORE.java b/java/org/apache/tomcat/util/bcel/generic/DSTORE.java new file mode 100644 index 000000000..f24f51c06 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DSTORE.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DSTORE - Store double into local variable + *
      Stack: ..., value.word1, value.word2 -> ... 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DSTORE extends StoreInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + DSTORE() { + super(org.apache.tomcat.util.bcel.Constants.DSTORE, org.apache.tomcat.util.bcel.Constants.DSTORE_0); + } + + + /** Store double into local variable + * @param n index of local variable + */ + public DSTORE(int n) { + super(org.apache.tomcat.util.bcel.Constants.DSTORE, org.apache.tomcat.util.bcel.Constants.DSTORE_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitDSTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DSUB.java b/java/org/apache/tomcat/util/bcel/generic/DSUB.java new file mode 100644 index 000000000..6ae95df2e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DSUB.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DSUB - Substract doubles + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class DSUB extends ArithmeticInstruction { + + /** Substract doubles + */ + public DSUB() { + super(org.apache.tomcat.util.bcel.Constants.DSUB); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitDSUB(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP.java b/java/org/apache/tomcat/util/bcel/generic/DUP.java new file mode 100644 index 000000000..44bbfc804 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP - Duplicate top operand stack word + *
      Stack: ..., word -> ..., word, word
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP extends StackInstruction implements PushInstruction { + + public DUP() { + super(org.apache.tomcat.util.bcel.Constants.DUP); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitStackInstruction(this); + v.visitDUP(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP2.java b/java/org/apache/tomcat/util/bcel/generic/DUP2.java new file mode 100644 index 000000000..55cc50b6d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP2.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP2 - Duplicate two top operand stack words + *
      Stack: ..., word2, word1 -> ..., word2, word1, word2, word1
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP2 extends StackInstruction implements PushInstruction { + + public DUP2() { + super(org.apache.tomcat.util.bcel.Constants.DUP2); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitStackInstruction(this); + v.visitDUP2(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP2_X1.java b/java/org/apache/tomcat/util/bcel/generic/DUP2_X1.java new file mode 100644 index 000000000..70fb1b956 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP2_X1.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP2_X1 - Duplicate two top operand stack words and put three down + *
      Stack: ..., word3, word2, word1 -> ..., word2, word1, word3, word2, word1
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP2_X1 extends StackInstruction { + + public DUP2_X1() { + super(org.apache.tomcat.util.bcel.Constants.DUP2_X1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackInstruction(this); + v.visitDUP2_X1(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP2_X2.java b/java/org/apache/tomcat/util/bcel/generic/DUP2_X2.java new file mode 100644 index 000000000..13482682f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP2_X2.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP2_X2 - Duplicate two top operand stack words and put four down + *
      Stack: ..., word4, word3, word2, word1 -> ..., word2, word1, word4, word3, word2, word1
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP2_X2 extends StackInstruction { + + public DUP2_X2() { + super(org.apache.tomcat.util.bcel.Constants.DUP2_X2); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackInstruction(this); + v.visitDUP2_X2(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP_X1.java b/java/org/apache/tomcat/util/bcel/generic/DUP_X1.java new file mode 100644 index 000000000..f0dbcb342 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP_X1.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP_X1 - Duplicate top operand stack word and put two down + *
      Stack: ..., word2, word1 -> ..., word1, word2, word1
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP_X1 extends StackInstruction { + + public DUP_X1() { + super(org.apache.tomcat.util.bcel.Constants.DUP_X1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackInstruction(this); + v.visitDUP_X1(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/DUP_X2.java b/java/org/apache/tomcat/util/bcel/generic/DUP_X2.java new file mode 100644 index 000000000..4ff230cc3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/DUP_X2.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * DUP_X2 - Duplicate top operand stack word and put three down + *
      Stack: ..., word3, word2, word1 -> ..., word1, word3, word2, word1
      + * + * @version $Id$ + * @author M. Dahm + */ +public class DUP_X2 extends StackInstruction { + + public DUP_X2() { + super(org.apache.tomcat.util.bcel.Constants.DUP_X2); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackInstruction(this); + v.visitDUP_X2(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/ElementValueGen.java new file mode 100644 index 000000000..63e416c65 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ElementValueGen.java @@ -0,0 +1,168 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.apache.tomcat.util.bcel.classfile.AnnotationElementValue; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.ArrayElementValue; +import org.apache.tomcat.util.bcel.classfile.ClassElementValue; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.EnumElementValue; +import org.apache.tomcat.util.bcel.classfile.SimpleElementValue; + +public abstract class ElementValueGen +{ + protected int type; + + protected ConstantPoolGen cpGen; + + protected ElementValueGen(int type, ConstantPoolGen cpGen) + { + this.type = type; + this.cpGen = cpGen; + } + + /** + * Subtypes return an immutable variant of the ElementValueGen + */ + public abstract ElementValue getElementValue(); + + public int getElementValueType() + { + return type; + } + + public abstract String stringifyValue(); + + public abstract void dump(DataOutputStream dos) throws IOException; + + public static final int STRING = 's'; + + public static final int ENUM_CONSTANT = 'e'; + + public static final int CLASS = 'c'; + + public static final int ANNOTATION = '@'; + + public static final int ARRAY = '['; + + public static final int PRIMITIVE_INT = 'I'; + + public static final int PRIMITIVE_BYTE = 'B'; + + public static final int PRIMITIVE_CHAR = 'C'; + + public static final int PRIMITIVE_DOUBLE = 'D'; + + public static final int PRIMITIVE_FLOAT = 'F'; + + public static final int PRIMITIVE_LONG = 'J'; + + public static final int PRIMITIVE_SHORT = 'S'; + + public static final int PRIMITIVE_BOOLEAN = 'Z'; + + public static ElementValueGen readElementValue(DataInputStream dis, + ConstantPoolGen cpGen) throws IOException + { + int type = dis.readUnsignedByte(); + switch (type) + { + case 'B': // byte + return new SimpleElementValueGen(PRIMITIVE_BYTE, dis + .readUnsignedShort(), cpGen); + case 'C': // char + return new SimpleElementValueGen(PRIMITIVE_CHAR, dis + .readUnsignedShort(), cpGen); + case 'D': // double + return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis + .readUnsignedShort(), cpGen); + case 'F': // float + return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis + .readUnsignedShort(), cpGen); + case 'I': // int + return new SimpleElementValueGen(PRIMITIVE_INT, dis + .readUnsignedShort(), cpGen); + case 'J': // long + return new SimpleElementValueGen(PRIMITIVE_LONG, dis + .readUnsignedShort(), cpGen); + case 'S': // short + return new SimpleElementValueGen(PRIMITIVE_SHORT, dis + .readUnsignedShort(), cpGen); + case 'Z': // boolean + return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis + .readUnsignedShort(), cpGen); + case 's': // String + return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), + cpGen); + case 'e': // Enum constant + return new EnumElementValueGen(dis.readUnsignedShort(), dis + .readUnsignedShort(), cpGen); + case 'c': // Class + return new ClassElementValueGen(dis.readUnsignedShort(), cpGen); + case '@': // Annotation + // TODO: isRuntimeVisible ?????????? + // FIXME + return new AnnotationElementValueGen(ANNOTATION, + new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen + .getConstantPool(), true), cpGen, false), cpGen); + case '[': // Array + int numArrayVals = dis.readUnsignedShort(); + ElementValue[] evalues = new ElementValue[numArrayVals]; + for (int j = 0; j < numArrayVals; j++) + { + evalues[j] = ElementValue.readElementValue(dis, cpGen + .getConstantPool()); + } + return new ArrayElementValueGen(ARRAY, evalues, cpGen); + default: + throw new RuntimeException( + "Unexpected element value kind in annotation: " + type); + } + } + + protected ConstantPoolGen getConstantPool() + { + return cpGen; + } + + /** + * Creates an (modifiable) ElementValueGen copy of an (immutable) + * ElementValue - constant pool is assumed correct. + */ + public static ElementValueGen copy(ElementValue value, + ConstantPoolGen cpool, boolean copyPoolEntries) + { + switch (value.getElementValueType()) + { + case 'B': // byte + case 'C': // char + case 'D': // double + case 'F': // float + case 'I': // int + case 'J': // long + case 'S': // short + case 'Z': // boolean + case 's': // String + return new SimpleElementValueGen((SimpleElementValue) value, cpool, + copyPoolEntries); + case 'e': // Enum constant + return new EnumElementValueGen((EnumElementValue) value, cpool, + copyPoolEntries); + case '@': // Annotation + return new AnnotationElementValueGen( + (AnnotationElementValue) value, cpool, copyPoolEntries); + case '[': // Array + return new ArrayElementValueGen((ArrayElementValue) value, cpool, + copyPoolEntries); + case 'c': // Class + return new ClassElementValueGen((ClassElementValue) value, cpool, + copyPoolEntries); + default: + throw new RuntimeException("Not implemented yet! (" + + value.getElementValueType() + ")"); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ElementValuePairGen.java b/java/org/apache/tomcat/util/bcel/generic/ElementValuePairGen.java new file mode 100755 index 000000000..590c10c84 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ElementValuePairGen.java @@ -0,0 +1,93 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.ElementValuePair; + +public class ElementValuePairGen +{ + private int nameIdx; + + private ElementValueGen value; + + private ConstantPoolGen cpool; + + public ElementValuePairGen(ElementValuePair nvp, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + this.cpool = cpool; + // J5ASSERT: + // Could assert nvp.getNameString() points to the same thing as + // cpool.getConstant(nvp.getNameIndex()) + // if + // (!nvp.getNameString().equals(((ConstantUtf8)cpool.getConstant(nvp.getNameIndex())).getBytes())) + // { + // throw new RuntimeException("envp buggered"); + // } + if (copyPoolEntries) + { + nameIdx = cpool.addUtf8(nvp.getNameString()); + } + else + { + nameIdx = nvp.getNameIndex(); + } + value = ElementValueGen.copy(nvp.getValue(), cpool, copyPoolEntries); + } + + /** + * Retrieve an immutable version of this ElementNameValuePairGen + */ + public ElementValuePair getElementNameValuePair() + { + ElementValue immutableValue = value.getElementValue(); + return new ElementValuePair(nameIdx, immutableValue, cpool + .getConstantPool()); + } + + protected ElementValuePairGen(int idx, ElementValueGen value, + ConstantPoolGen cpool) + { + this.nameIdx = idx; + this.value = value; + this.cpool = cpool; + } + + public ElementValuePairGen(String name, ElementValueGen value, + ConstantPoolGen cpool) + { + this.nameIdx = cpool.addUtf8(name); + this.value = value; + this.cpool = cpool; + } + + protected void dump(DataOutputStream dos) throws IOException + { + dos.writeShort(nameIdx); // u2 name of the element + value.dump(dos); + } + + public int getNameIndex() + { + return nameIdx; + } + + public final String getNameString() + { + // ConstantString cu8 = (ConstantString)cpool.getConstant(nameIdx); + return ((ConstantUtf8) cpool.getConstant(nameIdx)).getBytes(); + } + + public final ElementValueGen getValue() + { + return value; + } + + public String toString() + { + return "ElementValuePair:[" + getNameString() + "=" + + value.stringifyValue() + "]"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/EmptyVisitor.java b/java/org/apache/tomcat/util/bcel/generic/EmptyVisitor.java new file mode 100644 index 000000000..52507d5bc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/EmptyVisitor.java @@ -0,0 +1,745 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Supplies empty method bodies to be overridden by subclasses. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class EmptyVisitor implements Visitor { + + public void visitStackInstruction( StackInstruction obj ) { + } + + + public void visitLocalVariableInstruction( LocalVariableInstruction obj ) { + } + + + public void visitBranchInstruction( BranchInstruction obj ) { + } + + + public void visitLoadClass( LoadClass obj ) { + } + + + public void visitFieldInstruction( FieldInstruction obj ) { + } + + + public void visitIfInstruction( IfInstruction obj ) { + } + + + public void visitConversionInstruction( ConversionInstruction obj ) { + } + + + public void visitPopInstruction( PopInstruction obj ) { + } + + + public void visitJsrInstruction( JsrInstruction obj ) { + } + + + public void visitGotoInstruction( GotoInstruction obj ) { + } + + + public void visitStoreInstruction( StoreInstruction obj ) { + } + + + public void visitTypedInstruction( TypedInstruction obj ) { + } + + + public void visitSelect( Select obj ) { + } + + + public void visitUnconditionalBranch( UnconditionalBranch obj ) { + } + + + public void visitPushInstruction( PushInstruction obj ) { + } + + + public void visitArithmeticInstruction( ArithmeticInstruction obj ) { + } + + + public void visitCPInstruction( CPInstruction obj ) { + } + + + public void visitInvokeInstruction( InvokeInstruction obj ) { + } + + + public void visitArrayInstruction( ArrayInstruction obj ) { + } + + + public void visitAllocationInstruction( AllocationInstruction obj ) { + } + + + public void visitReturnInstruction( ReturnInstruction obj ) { + } + + + public void visitFieldOrMethod( FieldOrMethod obj ) { + } + + + public void visitConstantPushInstruction( ConstantPushInstruction obj ) { + } + + + public void visitExceptionThrower( ExceptionThrower obj ) { + } + + + public void visitLoadInstruction( LoadInstruction obj ) { + } + + + public void visitVariableLengthInstruction( VariableLengthInstruction obj ) { + } + + + public void visitStackProducer( StackProducer obj ) { + } + + + public void visitStackConsumer( StackConsumer obj ) { + } + + + public void visitACONST_NULL( ACONST_NULL obj ) { + } + + + public void visitGETSTATIC( GETSTATIC obj ) { + } + + + public void visitIF_ICMPLT( IF_ICMPLT obj ) { + } + + + public void visitMONITOREXIT( MONITOREXIT obj ) { + } + + + public void visitIFLT( IFLT obj ) { + } + + + public void visitLSTORE( LSTORE obj ) { + } + + + public void visitPOP2( POP2 obj ) { + } + + + public void visitBASTORE( BASTORE obj ) { + } + + + public void visitISTORE( ISTORE obj ) { + } + + + public void visitCHECKCAST( CHECKCAST obj ) { + } + + + public void visitFCMPG( FCMPG obj ) { + } + + + public void visitI2F( I2F obj ) { + } + + + public void visitATHROW( ATHROW obj ) { + } + + + public void visitDCMPL( DCMPL obj ) { + } + + + public void visitARRAYLENGTH( ARRAYLENGTH obj ) { + } + + + public void visitDUP( DUP obj ) { + } + + + public void visitINVOKESTATIC( INVOKESTATIC obj ) { + } + + + public void visitLCONST( LCONST obj ) { + } + + + public void visitDREM( DREM obj ) { + } + + + public void visitIFGE( IFGE obj ) { + } + + + public void visitCALOAD( CALOAD obj ) { + } + + + public void visitLASTORE( LASTORE obj ) { + } + + + public void visitI2D( I2D obj ) { + } + + + public void visitDADD( DADD obj ) { + } + + + public void visitINVOKESPECIAL( INVOKESPECIAL obj ) { + } + + + public void visitIAND( IAND obj ) { + } + + + public void visitPUTFIELD( PUTFIELD obj ) { + } + + + public void visitILOAD( ILOAD obj ) { + } + + + public void visitDLOAD( DLOAD obj ) { + } + + + public void visitDCONST( DCONST obj ) { + } + + + public void visitNEW( NEW obj ) { + } + + + public void visitIFNULL( IFNULL obj ) { + } + + + public void visitLSUB( LSUB obj ) { + } + + + public void visitL2I( L2I obj ) { + } + + + public void visitISHR( ISHR obj ) { + } + + + public void visitTABLESWITCH( TABLESWITCH obj ) { + } + + + public void visitIINC( IINC obj ) { + } + + + public void visitDRETURN( DRETURN obj ) { + } + + + public void visitFSTORE( FSTORE obj ) { + } + + + public void visitDASTORE( DASTORE obj ) { + } + + + public void visitIALOAD( IALOAD obj ) { + } + + + public void visitDDIV( DDIV obj ) { + } + + + public void visitIF_ICMPGE( IF_ICMPGE obj ) { + } + + + public void visitLAND( LAND obj ) { + } + + + public void visitIDIV( IDIV obj ) { + } + + + public void visitLOR( LOR obj ) { + } + + + public void visitCASTORE( CASTORE obj ) { + } + + + public void visitFREM( FREM obj ) { + } + + + public void visitLDC( LDC obj ) { + } + + + public void visitBIPUSH( BIPUSH obj ) { + } + + + public void visitDSTORE( DSTORE obj ) { + } + + + public void visitF2L( F2L obj ) { + } + + + public void visitFMUL( FMUL obj ) { + } + + + public void visitLLOAD( LLOAD obj ) { + } + + + public void visitJSR( JSR obj ) { + } + + + public void visitFSUB( FSUB obj ) { + } + + + public void visitSASTORE( SASTORE obj ) { + } + + + public void visitALOAD( ALOAD obj ) { + } + + + public void visitDUP2_X2( DUP2_X2 obj ) { + } + + + public void visitRETURN( RETURN obj ) { + } + + + public void visitDALOAD( DALOAD obj ) { + } + + + public void visitSIPUSH( SIPUSH obj ) { + } + + + public void visitDSUB( DSUB obj ) { + } + + + public void visitL2F( L2F obj ) { + } + + + public void visitIF_ICMPGT( IF_ICMPGT obj ) { + } + + + public void visitF2D( F2D obj ) { + } + + + public void visitI2L( I2L obj ) { + } + + + public void visitIF_ACMPNE( IF_ACMPNE obj ) { + } + + + public void visitPOP( POP obj ) { + } + + + public void visitI2S( I2S obj ) { + } + + + public void visitIFEQ( IFEQ obj ) { + } + + + public void visitSWAP( SWAP obj ) { + } + + + public void visitIOR( IOR obj ) { + } + + + public void visitIREM( IREM obj ) { + } + + + public void visitIASTORE( IASTORE obj ) { + } + + + public void visitNEWARRAY( NEWARRAY obj ) { + } + + + public void visitINVOKEINTERFACE( INVOKEINTERFACE obj ) { + } + + + public void visitINEG( INEG obj ) { + } + + + public void visitLCMP( LCMP obj ) { + } + + + public void visitJSR_W( JSR_W obj ) { + } + + + public void visitMULTIANEWARRAY( MULTIANEWARRAY obj ) { + } + + + public void visitDUP_X2( DUP_X2 obj ) { + } + + + public void visitSALOAD( SALOAD obj ) { + } + + + public void visitIFNONNULL( IFNONNULL obj ) { + } + + + public void visitDMUL( DMUL obj ) { + } + + + public void visitIFNE( IFNE obj ) { + } + + + public void visitIF_ICMPLE( IF_ICMPLE obj ) { + } + + + public void visitLDC2_W( LDC2_W obj ) { + } + + + public void visitGETFIELD( GETFIELD obj ) { + } + + + public void visitLADD( LADD obj ) { + } + + + public void visitNOP( NOP obj ) { + } + + + public void visitFALOAD( FALOAD obj ) { + } + + + public void visitINSTANCEOF( INSTANCEOF obj ) { + } + + + public void visitIFLE( IFLE obj ) { + } + + + public void visitLXOR( LXOR obj ) { + } + + + public void visitLRETURN( LRETURN obj ) { + } + + + public void visitFCONST( FCONST obj ) { + } + + + public void visitIUSHR( IUSHR obj ) { + } + + + public void visitBALOAD( BALOAD obj ) { + } + + + public void visitDUP2( DUP2 obj ) { + } + + + public void visitIF_ACMPEQ( IF_ACMPEQ obj ) { + } + + + public void visitIMPDEP1( IMPDEP1 obj ) { + } + + + public void visitMONITORENTER( MONITORENTER obj ) { + } + + + public void visitLSHL( LSHL obj ) { + } + + + public void visitDCMPG( DCMPG obj ) { + } + + + public void visitD2L( D2L obj ) { + } + + + public void visitIMPDEP2( IMPDEP2 obj ) { + } + + + public void visitL2D( L2D obj ) { + } + + + public void visitRET( RET obj ) { + } + + + public void visitIFGT( IFGT obj ) { + } + + + public void visitIXOR( IXOR obj ) { + } + + + public void visitINVOKEVIRTUAL( INVOKEVIRTUAL obj ) { + } + + + public void visitFASTORE( FASTORE obj ) { + } + + + public void visitIRETURN( IRETURN obj ) { + } + + + public void visitIF_ICMPNE( IF_ICMPNE obj ) { + } + + + public void visitFLOAD( FLOAD obj ) { + } + + + public void visitLDIV( LDIV obj ) { + } + + + public void visitPUTSTATIC( PUTSTATIC obj ) { + } + + + public void visitAALOAD( AALOAD obj ) { + } + + + public void visitD2I( D2I obj ) { + } + + + public void visitIF_ICMPEQ( IF_ICMPEQ obj ) { + } + + + public void visitAASTORE( AASTORE obj ) { + } + + + public void visitARETURN( ARETURN obj ) { + } + + + public void visitDUP2_X1( DUP2_X1 obj ) { + } + + + public void visitFNEG( FNEG obj ) { + } + + + public void visitGOTO_W( GOTO_W obj ) { + } + + + public void visitD2F( D2F obj ) { + } + + + public void visitGOTO( GOTO obj ) { + } + + + public void visitISUB( ISUB obj ) { + } + + + public void visitF2I( F2I obj ) { + } + + + public void visitDNEG( DNEG obj ) { + } + + + public void visitICONST( ICONST obj ) { + } + + + public void visitFDIV( FDIV obj ) { + } + + + public void visitI2B( I2B obj ) { + } + + + public void visitLNEG( LNEG obj ) { + } + + + public void visitLREM( LREM obj ) { + } + + + public void visitIMUL( IMUL obj ) { + } + + + public void visitIADD( IADD obj ) { + } + + + public void visitLSHR( LSHR obj ) { + } + + + public void visitLOOKUPSWITCH( LOOKUPSWITCH obj ) { + } + + + public void visitDUP_X1( DUP_X1 obj ) { + } + + + public void visitFCMPL( FCMPL obj ) { + } + + + public void visitI2C( I2C obj ) { + } + + + public void visitLMUL( LMUL obj ) { + } + + + public void visitLUSHR( LUSHR obj ) { + } + + + public void visitISHL( ISHL obj ) { + } + + + public void visitLALOAD( LALOAD obj ) { + } + + + public void visitASTORE( ASTORE obj ) { + } + + + public void visitANEWARRAY( ANEWARRAY obj ) { + } + + + public void visitFRETURN( FRETURN obj ) { + } + + + public void visitFADD( FADD obj ) { + } + + + public void visitBREAKPOINT( BREAKPOINT obj ) { + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/EnumElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/EnumElementValueGen.java new file mode 100644 index 000000000..2e78d1e78 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/EnumElementValueGen.java @@ -0,0 +1,119 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.EnumElementValue; + +public class EnumElementValueGen extends ElementValueGen +{ + // For enum types, these two indices point to the type and value + private int typeIdx; + + private int valueIdx; + + /** + * This ctor assumes the constant pool already contains the right type and + * value - as indicated by typeIdx and valueIdx. This ctor is used for + * deserialization + */ + protected EnumElementValueGen(int typeIdx, int valueIdx, + ConstantPoolGen cpool) + { + super(ElementValueGen.ENUM_CONSTANT, cpool); + if (type != ENUM_CONSTANT) + throw new RuntimeException( + "Only element values of type enum can be built with this ctor - type specified: " + type); + this.typeIdx = typeIdx; + this.valueIdx = valueIdx; + } + + /** + * Return immutable variant of this EnumElementValue + */ + public ElementValue getElementValue() + { + System.err.println("Duplicating value: " + getEnumTypeString() + ":" + + getEnumValueString()); + return new EnumElementValue(type, typeIdx, valueIdx, cpGen + .getConstantPool()); + } + + public EnumElementValueGen(ObjectType t, String value, ConstantPoolGen cpool) + { + super(ElementValueGen.ENUM_CONSTANT, cpool); + typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t); + valueIdx = cpool.addUtf8(value);// was addString(value); + } + + public EnumElementValueGen(EnumElementValue value, ConstantPoolGen cpool, + boolean copyPoolEntries) + { + super(ENUM_CONSTANT, cpool); + if (copyPoolEntries) + { + typeIdx = cpool.addUtf8(value.getEnumTypeString());// was + // addClass(value.getEnumTypeString()); + valueIdx = cpool.addUtf8(value.getEnumValueString()); // was + // addString(value.getEnumValueString()); + } + else + { + typeIdx = value.getTypeIndex(); + valueIdx = value.getValueIndex(); + } + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e') + dos.writeShort(typeIdx); // u2 + dos.writeShort(valueIdx); // u2 + } + + public String stringifyValue() + { + ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant( + valueIdx); + return cu8.getBytes(); + // ConstantString cu8 = + // (ConstantString)getConstantPool().getConstant(valueIdx); + // return + // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + } + + // BCELBUG: Should we need to call utility.signatureToString() on the output + // here? + public String getEnumTypeString() + { + // Constant cc = getConstantPool().getConstant(typeIdx); + // ConstantClass cu8 = + // (ConstantClass)getConstantPool().getConstant(typeIdx); + // return + // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); + return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)) + .getBytes(); + // return Utility.signatureToString(cu8.getBytes()); + } + + public String getEnumValueString() + { + return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)) + .getBytes(); + // ConstantString cu8 = + // (ConstantString)getConstantPool().getConstant(valueIdx); + // return + // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + } + + public int getValueIndex() + { + return valueIdx; + } + + public int getTypeIndex() + { + return typeIdx; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ExceptionThrower.java b/java/org/apache/tomcat/util/bcel/generic/ExceptionThrower.java new file mode 100644 index 000000000..f62cca0c1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ExceptionThrower.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote an instruction that may throw a run-time or a linking + * exception (or both) during execution. This is not quite the truth + * as such; because all instructions may throw an + * java.lang.VirtualMachineError. These exceptions are omitted. + * + * The Lava Language Specification specifies exactly which + * RUN-TIME and which LINKING exceptions each + * instruction may throw which is reflected by the implementers. Due + * to the structure of the JVM specification, it may be possible that + * an Instruction implementing this interface returns a Class[] of + * size 0. + * + * Please note that we speak of an "exception" here when we mean any + * "Throwable" object; so this term is equally used for "Exception" + * and "Error" objects. + * + * @version $Id$ + * @author Enver Haase + */ +public interface ExceptionThrower { + + public java.lang.Class[] getExceptions(); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/F2D.java b/java/org/apache/tomcat/util/bcel/generic/F2D.java new file mode 100644 index 000000000..d65deed64 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/F2D.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * F2D - Convert float to double + *
      Stack: ..., value -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class F2D extends ConversionInstruction { + + /** Convert float to double + */ + public F2D() { + super(org.apache.tomcat.util.bcel.Constants.F2D); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitF2D(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/F2I.java b/java/org/apache/tomcat/util/bcel/generic/F2I.java new file mode 100644 index 000000000..4d19be932 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/F2I.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * F2I - Convert float to int + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class F2I extends ConversionInstruction { + + /** Convert float to int + */ + public F2I() { + super(org.apache.tomcat.util.bcel.Constants.F2I); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitF2I(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/F2L.java b/java/org/apache/tomcat/util/bcel/generic/F2L.java new file mode 100644 index 000000000..d102be2a6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/F2L.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * F2L - Convert float to long + *
      Stack: ..., value -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class F2L extends ConversionInstruction { + + /** Convert float to long + */ + public F2L() { + super(org.apache.tomcat.util.bcel.Constants.F2L); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitF2L(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FADD.java b/java/org/apache/tomcat/util/bcel/generic/FADD.java new file mode 100644 index 000000000..464c8d84e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FADD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FADD - Add floats + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FADD extends ArithmeticInstruction { + + /** Add floats + */ + public FADD() { + super(org.apache.tomcat.util.bcel.Constants.FADD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFADD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FALOAD.java b/java/org/apache/tomcat/util/bcel/generic/FALOAD.java new file mode 100644 index 000000000..3f9daa539 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FALOAD - Load float from array + *
      Stack: ..., arrayref, index -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FALOAD extends ArrayInstruction implements StackProducer { + + /** Load float from array + */ + public FALOAD() { + super(org.apache.tomcat.util.bcel.Constants.FALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitFALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FASTORE.java b/java/org/apache/tomcat/util/bcel/generic/FASTORE.java new file mode 100644 index 000000000..d4691fab4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FASTORE - Store into float array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FASTORE extends ArrayInstruction implements StackConsumer { + + /** Store float into array + */ + public FASTORE() { + super(org.apache.tomcat.util.bcel.Constants.FASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitFASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FCMPG.java b/java/org/apache/tomcat/util/bcel/generic/FCMPG.java new file mode 100644 index 000000000..3e1f3ca00 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FCMPG.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FCMPG - Compare floats: value1 > value2 + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FCMPG extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public FCMPG() { + super(org.apache.tomcat.util.bcel.Constants.FCMPG, (short) 1); + } + + + /** @return Type.FLOAT + */ + public Type getType( ConstantPoolGen cp ) { + return Type.FLOAT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitFCMPG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FCMPL.java b/java/org/apache/tomcat/util/bcel/generic/FCMPL.java new file mode 100644 index 000000000..300618084 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FCMPL.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FCMPL - Compare floats: value1 < value2 + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FCMPL extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public FCMPL() { + super(org.apache.tomcat.util.bcel.Constants.FCMPL, (short) 1); + } + + + /** @return Type.FLOAT + */ + public Type getType( ConstantPoolGen cp ) { + return Type.FLOAT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitFCMPL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FCONST.java b/java/org/apache/tomcat/util/bcel/generic/FCONST.java new file mode 100644 index 000000000..ffa61234f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FCONST.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FCONST - Push 0.0, 1.0 or 2.0, other values cause an exception + * + *
      Stack: ... -> ..., 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + private float value; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + FCONST() { + } + + + public FCONST(float f) { + super(org.apache.tomcat.util.bcel.Constants.FCONST_0, (short) 1); + if (f == 0.0) { + opcode = org.apache.tomcat.util.bcel.Constants.FCONST_0; + } else if (f == 1.0) { + opcode = org.apache.tomcat.util.bcel.Constants.FCONST_1; + } else if (f == 2.0) { + opcode = org.apache.tomcat.util.bcel.Constants.FCONST_2; + } else { + throw new ClassGenException("FCONST can be used only for 0.0, 1.0 and 2.0: " + f); + } + value = f; + } + + + public Number getValue() { + return new Float(value); + } + + + /** @return Type.FLOAT + */ + public Type getType( ConstantPoolGen cp ) { + return Type.FLOAT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitFCONST(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FDIV.java b/java/org/apache/tomcat/util/bcel/generic/FDIV.java new file mode 100644 index 000000000..aaec4569f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FDIV.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FDIV - Divide floats + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FDIV extends ArithmeticInstruction { + + /** Divide floats + */ + public FDIV() { + super(org.apache.tomcat.util.bcel.Constants.FDIV); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFDIV(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FLOAD.java b/java/org/apache/tomcat/util/bcel/generic/FLOAD.java new file mode 100644 index 000000000..007bae14a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FLOAD.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FLOAD - Load float from local variable + *
      Stack ... -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FLOAD extends LoadInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + FLOAD() { + super(org.apache.tomcat.util.bcel.Constants.FLOAD, org.apache.tomcat.util.bcel.Constants.FLOAD_0); + } + + + /** Load float from local variable + * @param n index of local variable + */ + public FLOAD(int n) { + super(org.apache.tomcat.util.bcel.Constants.FLOAD, org.apache.tomcat.util.bcel.Constants.FLOAD_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitFLOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FMUL.java b/java/org/apache/tomcat/util/bcel/generic/FMUL.java new file mode 100644 index 000000000..e0c786f4a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FMUL.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FMUL - Multiply floats + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FMUL extends ArithmeticInstruction { + + /** Multiply floats + */ + public FMUL() { + super(org.apache.tomcat.util.bcel.Constants.FMUL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFMUL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FNEG.java b/java/org/apache/tomcat/util/bcel/generic/FNEG.java new file mode 100644 index 000000000..56aeb3113 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FNEG.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FNEG - Negate float + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FNEG extends ArithmeticInstruction { + + public FNEG() { + super(org.apache.tomcat.util.bcel.Constants.FNEG); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFNEG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FREM.java b/java/org/apache/tomcat/util/bcel/generic/FREM.java new file mode 100644 index 000000000..2f3e836da --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FREM.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FREM - Remainder of floats + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FREM extends ArithmeticInstruction { + + /** Remainder of floats + */ + public FREM() { + super(org.apache.tomcat.util.bcel.Constants.FREM); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFREM(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FRETURN.java b/java/org/apache/tomcat/util/bcel/generic/FRETURN.java new file mode 100644 index 000000000..db49cbfa7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FRETURN.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FRETURN - Return float from method + *
      Stack: ..., value -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FRETURN extends ReturnInstruction { + + /** Return float from method + */ + public FRETURN() { + super(org.apache.tomcat.util.bcel.Constants.FRETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitFRETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FSTORE.java b/java/org/apache/tomcat/util/bcel/generic/FSTORE.java new file mode 100644 index 000000000..f3b52c0a8 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FSTORE.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FSTORE - Store float into local variable + *
      Stack: ..., value -> ... 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FSTORE extends StoreInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + FSTORE() { + super(org.apache.tomcat.util.bcel.Constants.FSTORE, org.apache.tomcat.util.bcel.Constants.FSTORE_0); + } + + + /** Store float into local variable + * @param n index of local variable + */ + public FSTORE(int n) { + super(org.apache.tomcat.util.bcel.Constants.FSTORE, org.apache.tomcat.util.bcel.Constants.FSTORE_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitFSTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FSUB.java b/java/org/apache/tomcat/util/bcel/generic/FSUB.java new file mode 100644 index 000000000..c496bfa04 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FSUB.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * FSUB - Substract floats + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class FSUB extends ArithmeticInstruction { + + /** Substract floats + */ + public FSUB() { + super(org.apache.tomcat.util.bcel.Constants.FSUB); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitFSUB(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FieldGen.java b/java/org/apache/tomcat/util/bcel/generic/FieldGen.java new file mode 100644 index 000000000..325399b70 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FieldGen.java @@ -0,0 +1,374 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.Annotations; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.classfile.ConstantObject; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantValue; +import org.apache.tomcat.util.bcel.classfile.Field; +import org.apache.tomcat.util.bcel.classfile.Utility; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * Template class for building up a field. The only extraordinary thing + * one can do is to add a constant value attribute to a field (which must of + * course be compatible with to the declared type). + * + * @version $Id$ + * @author M. Dahm + * @see Field + */ +public class FieldGen extends FieldGenOrMethodGen { + + private Object value = null; + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + FieldGen THIS = (FieldGen) o1; + FieldGen THAT = (FieldGen) o2; + return THIS.getName().equals(THAT.getName()) + && THIS.getSignature().equals(THAT.getSignature()); + } + + + public int hashCode( Object o ) { + FieldGen THIS = (FieldGen) o; + return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + } + }; + + + /** + * Declare a field. If it is static (isStatic() == true) and has a + * basic type like int or String it may have an initial value + * associated with it as defined by setInitValue(). + * + * @param access_flags access qualifiers + * @param type field type + * @param name field name + * @param cp constant pool + */ + public FieldGen(int access_flags, Type type, String name, ConstantPoolGen cp) { + setAccessFlags(access_flags); + setType(type); + setName(name); + setConstantPool(cp); + } + + + /** + * Instantiate from existing field. + * + * @param field Field object + * @param cp constant pool (must contain the same entries as the field's constant pool) + */ + public FieldGen(Field field, ConstantPoolGen cp) { + this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp); + Attribute[] attrs = field.getAttributes(); + for (int i = 0; i < attrs.length; i++) { + if (attrs[i] instanceof ConstantValue) { + setValue(((ConstantValue) attrs[i]).getConstantValueIndex()); + } else if (attrs[i] instanceof Annotations) { + Annotations runtimeAnnotations = (Annotations)attrs[i]; + AnnotationEntry[] annotationEntries = runtimeAnnotations.getAnnotationEntries(); + for (int j = 0; j < annotationEntries.length; j++) { + AnnotationEntry element = annotationEntries[j]; + addAnnotationEntry(new AnnotationEntryGen(element,cp,false)); + } + } else { + addAttribute(attrs[i]); + } + } + } + + + private void setValue( int index ) { + ConstantPool cp = this.cp.getConstantPool(); + Constant c = cp.getConstant(index); + value = ((ConstantObject) c).getConstantValue(cp); + } + + + /** + * Set (optional) initial value of field, otherwise it will be set to null/0/false + * by the JVM automatically. + */ + public void setInitValue( String str ) { + checkType(new ObjectType("java.lang.String")); + if (str != null) { + value = str; + } + } + + + public void setInitValue( long l ) { + checkType(Type.LONG); + if (l != 0L) { + value = new Long(l); + } + } + + + public void setInitValue( int i ) { + checkType(Type.INT); + if (i != 0) { + value = new Integer(i); + } + } + + + public void setInitValue( short s ) { + checkType(Type.SHORT); + if (s != 0) { + value = new Integer(s); + } + } + + + public void setInitValue( char c ) { + checkType(Type.CHAR); + if (c != 0) { + value = new Integer(c); + } + } + + + public void setInitValue( byte b ) { + checkType(Type.BYTE); + if (b != 0) { + value = new Integer(b); + } + } + + + public void setInitValue( boolean b ) { + checkType(Type.BOOLEAN); + if (b) { + value = new Integer(1); + } + } + + + public void setInitValue( float f ) { + checkType(Type.FLOAT); + if (f != 0.0) { + value = new Float(f); + } + } + + + public void setInitValue( double d ) { + checkType(Type.DOUBLE); + if (d != 0.0) { + value = new Double(d); + } + } + + + /** Remove any initial value. + */ + public void cancelInitValue() { + value = null; + } + + + private void checkType( Type atype ) { + if (type == null) { + throw new ClassGenException("You haven't defined the type of the field yet"); + } + if (!isFinal()) { + throw new ClassGenException("Only final fields may have an initial value!"); + } + if (!type.equals(atype)) { + throw new ClassGenException("Types are not compatible: " + type + " vs. " + atype); + } + } + + + /** + * Get field object after having set up all necessary values. + */ + public Field getField() { + String signature = getSignature(); + int name_index = cp.addUtf8(name); + int signature_index = cp.addUtf8(signature); + if (value != null) { + checkType(type); + int index = addConstant(); + addAttribute(new ConstantValue(cp.addUtf8("ConstantValue"), 2, index, cp + .getConstantPool())); + } + addAnnotationsAsAttribute(cp); + return new Field(access_flags, name_index, signature_index, getAttributes(), cp + .getConstantPool()); + } + + private void addAnnotationsAsAttribute(ConstantPoolGen cp) { + Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotation_vec); + for (int i = 0; i < attrs.length; i++) { + addAttribute(attrs[i]); + } + } + + + private int addConstant() { + switch (type.getType()) { + case Constants.T_INT: + case Constants.T_CHAR: + case Constants.T_BYTE: + case Constants.T_BOOLEAN: + case Constants.T_SHORT: + return cp.addInteger(((Integer) value).intValue()); + case Constants.T_FLOAT: + return cp.addFloat(((Float) value).floatValue()); + case Constants.T_DOUBLE: + return cp.addDouble(((Double) value).doubleValue()); + case Constants.T_LONG: + return cp.addLong(((Long) value).longValue()); + case Constants.T_REFERENCE: + return cp.addString(((String) value)); + default: + throw new RuntimeException("Oops: Unhandled : " + type.getType()); + } + } + + + public String getSignature() { + return type.getSignature(); + } + + private List observers; + + + /** Add observer for this object. + */ + public void addObserver( FieldObserver o ) { + if (observers == null) { + observers = new ArrayList(); + } + observers.add(o); + } + + + /** Remove observer for this object. + */ + public void removeObserver( FieldObserver o ) { + if (observers != null) { + observers.remove(o); + } + } + + + /** Call notify() method on all observers. This method is not called + * automatically whenever the state has changed, but has to be + * called by the user after he has finished editing the object. + */ + public void update() { + if (observers != null) { + for (Iterator e = observers.iterator(); e.hasNext();) { + ((FieldObserver) e.next()).notify(this); + } + } + } + + + public String getInitValue() { + if (value != null) { + return value.toString(); + } else { + return null; + } + } + + + /** + * Return string representation close to declaration format, + * `public static final short MAX = 100', e.g.. + * + * @return String representation of field + */ + public final String toString() { + String name, signature, access; // Short cuts to constant pool + access = Utility.accessToString(access_flags); + access = access.equals("") ? "" : (access + " "); + signature = type.toString(); + name = getName(); + StringBuffer buf = new StringBuffer(32); + buf.append(access).append(signature).append(" ").append(name); + String value = getInitValue(); + if (value != null) { + buf.append(" = ").append(value); + } + return buf.toString(); + } + + + /** @return deep copy of this field + */ + public FieldGen copy( ConstantPoolGen cp ) { + FieldGen fg = (FieldGen) clone(); + fg.setConstantPool(cp); + return fg; + } + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two FieldGen objects are said to be equal when + * their names and signatures are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the field's name XOR signature. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FieldGenOrMethodGen.java b/java/org/apache/tomcat/util/bcel/generic/FieldGenOrMethodGen.java new file mode 100644 index 000000000..f8c1e71c5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FieldGenOrMethodGen.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.ArrayList; +import java.util.List; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.AccessFlags; +import org.apache.tomcat.util.bcel.classfile.Attribute; + +/** + * Super class for FieldGen and MethodGen objects, since they have + * some methods in common! + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable { + + protected String name; + protected Type type; + protected ConstantPoolGen cp; + private List attribute_vec = new ArrayList(); + protected ArrayList annotation_vec= new ArrayList(); + + + protected FieldGenOrMethodGen() { + } + + + public void setType( Type type ) { + if (type.getType() == Constants.T_ADDRESS) { + throw new IllegalArgumentException("Type can not be " + type); + } + this.type = type; + } + + + public Type getType() { + return type; + } + + + /** @return name of method/field. + */ + public String getName() { + return name; + } + + + public void setName( String name ) { + this.name = name; + } + + + public ConstantPoolGen getConstantPool() { + return cp; + } + + + public void setConstantPool( ConstantPoolGen cp ) { + this.cp = cp; + } + + + /** + * Add an attribute to this method. Currently, the JVM knows about + * the `Code', `ConstantValue', `Synthetic' and `Exceptions' + * attributes. Other attributes will be ignored by the JVM but do no + * harm. + * + * @param a attribute to be added + */ + public void addAttribute( Attribute a ) { + attribute_vec.add(a); + } + + public void addAnnotationEntry(AnnotationEntryGen ag) + { + annotation_vec.add(ag); + } + + + /** + * Remove an attribute. + */ + public void removeAttribute( Attribute a ) { + attribute_vec.remove(a); + } + + public void removeAnnotationEntry(AnnotationEntryGen ag) + { + annotation_vec.remove(ag); + } + + + /** + * Remove all attributes. + */ + public void removeAttributes() { + attribute_vec.clear(); + } + + public void removeAnnotationEntries() + { + annotation_vec.clear(); + } + + + /** + * @return all attributes of this method. + */ + public Attribute[] getAttributes() { + Attribute[] attributes = new Attribute[attribute_vec.size()]; + attribute_vec.toArray(attributes); + return attributes; + } + + public AnnotationEntryGen[] getAnnotationEntries() { + AnnotationEntryGen[] annotations = new AnnotationEntryGen[annotation_vec.size()]; + annotation_vec.toArray(annotations); + return annotations; + } + + + /** @return signature of method/field. + */ + public abstract String getSignature(); + + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FieldInstruction.java b/java/org/apache/tomcat/util/bcel/generic/FieldInstruction.java new file mode 100644 index 000000000..b3a8707b3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FieldInstruction.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.classfile.ConstantPool; + +/** + * Super class for the GET/PUTxxx family of instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class FieldInstruction extends FieldOrMethod implements TypedInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + FieldInstruction() { + } + + + /** + * @param index to constant pool + */ + protected FieldInstruction(short opcode, int index) { + super(opcode, index); + } + + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString( ConstantPool cp ) { + return org.apache.tomcat.util.bcel.Constants.OPCODE_NAMES[opcode] + " " + + cp.constantToString(index, org.apache.tomcat.util.bcel.Constants.CONSTANT_Fieldref); + } + + + /** @return size of field (1 or 2) + */ + protected int getFieldSize( ConstantPoolGen cpg ) { + return Type.getTypeSize(getSignature(cpg)); + } + + + /** @return return type of referenced field + */ + public Type getType( ConstantPoolGen cpg ) { + return getFieldType(cpg); + } + + + /** @return type of field + */ + public Type getFieldType( ConstantPoolGen cpg ) { + return Type.getType(getSignature(cpg)); + } + + + /** @return name of referenced field. + */ + public String getFieldName( ConstantPoolGen cpg ) { + return getName(cpg); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FieldObserver.java b/java/org/apache/tomcat/util/bcel/generic/FieldObserver.java new file mode 100644 index 000000000..da42468e0 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FieldObserver.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Imnplement this interface if you're interested in changes to a FieldGen object + * and register yourself with addObserver(). + * + * @version $Id$ + * @author M. Dahm + */ +public interface FieldObserver { + + public void notify( FieldGen field ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/FieldOrMethod.java b/java/org/apache/tomcat/util/bcel/generic/FieldOrMethod.java new file mode 100644 index 000000000..01d3b9533 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/FieldOrMethod.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.classfile.ConstantCP; +import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; + +/** + * Super class for InvokeInstruction and FieldInstruction, since they have + * some methods in common! + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class FieldOrMethod extends CPInstruction implements LoadClass { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + FieldOrMethod() { + } + + + /** + * @param index to constant pool + */ + protected FieldOrMethod(short opcode, int index) { + super(opcode, index); + } + + + /** @return signature of referenced method/field. + */ + public String getSignature( ConstantPoolGen cpg ) { + ConstantPool cp = cpg.getConstantPool(); + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + return ((ConstantUtf8) cp.getConstant(cnat.getSignatureIndex())).getBytes(); + } + + + /** @return name of referenced method/field. + */ + public String getName( ConstantPoolGen cpg ) { + ConstantPool cp = cpg.getConstantPool(); + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + ConstantNameAndType cnat = (ConstantNameAndType) cp.getConstant(cmr.getNameAndTypeIndex()); + return ((ConstantUtf8) cp.getConstant(cnat.getNameIndex())).getBytes(); + } + + + /** @return name of the referenced class/interface + * @deprecated If the instruction references an array class, + * this method will return "java.lang.Object". + * For code generated by Java 1.5, this answer is + * sometimes wrong (e.g., if the "clone()" method is + * called on an array). A better idea is to use + * the getReferenceType() method, which correctly distinguishes + * between class types and array types. + */ + public String getClassName( ConstantPoolGen cpg ) { + ConstantPool cp = cpg.getConstantPool(); + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + String className = cp.getConstantString(cmr.getClassIndex(), + org.apache.tomcat.util.bcel.Constants.CONSTANT_Class); + if (className.startsWith("[")) { + // Turn array classes into java.lang.Object. + return "java.lang.Object"; + } + return className.replace('/', '.'); + } + + + /** @return type of the referenced class/interface + * @deprecated If the instruction references an array class, + * the ObjectType returned will be invalid. Use + * getReferenceType() instead. + */ + public ObjectType getClassType( ConstantPoolGen cpg ) { + return new ObjectType(getClassName(cpg)); + } + + + /** + * Return the reference type representing the class, interface, + * or array class referenced by the instruction. + * @param cpg the ConstantPoolGen used to create the instruction + * @return an ObjectType (if the referenced class type is a class + * or interface), or an ArrayType (if the referenced class + * type is an array class) + */ + public ReferenceType getReferenceType( ConstantPoolGen cpg ) { + ConstantPool cp = cpg.getConstantPool(); + ConstantCP cmr = (ConstantCP) cp.getConstant(index); + String className = cp.getConstantString(cmr.getClassIndex(), + org.apache.tomcat.util.bcel.Constants.CONSTANT_Class); + if (className.startsWith("[")) { + return (ArrayType) Type.getType(className); + } else { + className = className.replace('/', '.'); + return new ObjectType(className); + } + } + + + /** @return type of the referenced class/interface + */ + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + return getClassType(cpg); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/GETFIELD.java b/java/org/apache/tomcat/util/bcel/generic/GETFIELD.java new file mode 100644 index 000000000..22c29fdc0 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/GETFIELD.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * GETFIELD - Fetch field from object + *
      Stack: ..., objectref -> ..., value
      + * OR + *
      Stack: ..., objectref -> ..., value.word1, value.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class GETFIELD extends FieldInstruction implements ExceptionThrower, StackConsumer, + StackProducer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + GETFIELD() { + } + + + public GETFIELD(int index) { + super(Constants.GETFIELD, index); + } + + + public int produceStack( ConstantPoolGen cpg ) { + return getFieldSize(cpg); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitFieldInstruction(this); + v.visitGETFIELD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/GETSTATIC.java b/java/org/apache/tomcat/util/bcel/generic/GETSTATIC.java new file mode 100644 index 000000000..aab6f1787 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/GETSTATIC.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * GETSTATIC - Fetch static field from class + *
      Stack: ..., -> ..., value
      + * OR + *
      Stack: ..., -> ..., value.word1, value.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class GETSTATIC extends FieldInstruction implements PushInstruction, ExceptionThrower { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + GETSTATIC() { + } + + + public GETSTATIC(int index) { + super(Constants.GETSTATIC, index); + } + + + public int produceStack( ConstantPoolGen cpg ) { + return getFieldSize(cpg); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[1 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitFieldInstruction(this); + v.visitGETSTATIC(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/GOTO.java b/java/org/apache/tomcat/util/bcel/generic/GOTO.java new file mode 100644 index 000000000..f7484b58a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/GOTO.java @@ -0,0 +1,89 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * GOTO - Branch always (to relative offset, not absolute address) + * + * @version $Id$ + * @author M. Dahm + */ +public class GOTO extends GotoInstruction implements VariableLengthInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + GOTO() { + } + + + public GOTO(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.GOTO, target); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + index = getTargetOffset(); + if (opcode == org.apache.tomcat.util.bcel.Constants.GOTO) { + super.dump(out); + } else { // GOTO_W + index = getTargetOffset(); + out.writeByte(opcode); + out.writeInt(index); + } + } + + + /** Called in pass 2 of InstructionList.setPositions() in order to update + * the branch target, that may shift due to variable length instructions. + */ + protected int updatePosition( int offset, int max_offset ) { + int i = getTargetOffset(); // Depending on old position value + position += offset; // Position may be shifted by preceding expansions + if (Math.abs(i) >= (32767 - max_offset)) { // to large for short (estimate) + opcode = org.apache.tomcat.util.bcel.Constants.GOTO_W; + length = 5; + return 2; // 5 - 3 + } + return 0; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitVariableLengthInstruction(this); + v.visitUnconditionalBranch(this); + v.visitBranchInstruction(this); + v.visitGotoInstruction(this); + v.visitGOTO(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/GOTO_W.java b/java/org/apache/tomcat/util/bcel/generic/GOTO_W.java new file mode 100644 index 000000000..0e38a7439 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/GOTO_W.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * GOTO_W - Branch always (to relative offset, not absolute address) + * + * @version $Id$ + * @author M. Dahm + */ +public class GOTO_W extends GotoInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + GOTO_W() { + } + + + public GOTO_W(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.GOTO_W, target); + length = 5; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + index = getTargetOffset(); + out.writeByte(opcode); + out.writeInt(index); + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + index = bytes.readInt(); + length = 5; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitUnconditionalBranch(this); + v.visitBranchInstruction(this); + v.visitGotoInstruction(this); + v.visitGOTO_W(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/GotoInstruction.java b/java/org/apache/tomcat/util/bcel/generic/GotoInstruction.java new file mode 100644 index 000000000..cd82eab5d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/GotoInstruction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Super class for GOTO + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class GotoInstruction extends BranchInstruction implements UnconditionalBranch { + + GotoInstruction(short opcode, InstructionHandle target) { + super(opcode, target); + } + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + GotoInstruction() { + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2B.java b/java/org/apache/tomcat/util/bcel/generic/I2B.java new file mode 100644 index 000000000..c7ca71043 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2B.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2B - Convert int to byte + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2B extends ConversionInstruction { + + /** Convert int to byte + */ + public I2B() { + super(org.apache.tomcat.util.bcel.Constants.I2B); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2B(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2C.java b/java/org/apache/tomcat/util/bcel/generic/I2C.java new file mode 100644 index 000000000..f6feaf25d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2C.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2C - Convert int to char + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2C extends ConversionInstruction { + + /** Convert int to char + */ + public I2C() { + super(org.apache.tomcat.util.bcel.Constants.I2C); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2C(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2D.java b/java/org/apache/tomcat/util/bcel/generic/I2D.java new file mode 100644 index 000000000..c1b8807b6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2D.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2D - Convert int to double + *
      Stack: ..., value -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2D extends ConversionInstruction { + + /** Convert int to double + */ + public I2D() { + super(org.apache.tomcat.util.bcel.Constants.I2D); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2D(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2F.java b/java/org/apache/tomcat/util/bcel/generic/I2F.java new file mode 100644 index 000000000..e6d3b0c61 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2F.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2F - Convert int to float + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2F extends ConversionInstruction { + + /** Convert int to float + */ + public I2F() { + super(org.apache.tomcat.util.bcel.Constants.I2F); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2F(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2L.java b/java/org/apache/tomcat/util/bcel/generic/I2L.java new file mode 100644 index 000000000..df23b7dc2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2L.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2L - Convert int to long + *
      Stack: ..., value -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2L extends ConversionInstruction { + + /** Convert int to long + */ + public I2L() { + super(org.apache.tomcat.util.bcel.Constants.I2L); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2L(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/I2S.java b/java/org/apache/tomcat/util/bcel/generic/I2S.java new file mode 100644 index 000000000..1c4525429 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/I2S.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * I2S - Convert int to short + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class I2S extends ConversionInstruction { + + public I2S() { + super(org.apache.tomcat.util.bcel.Constants.I2S); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitI2S(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IADD.java b/java/org/apache/tomcat/util/bcel/generic/IADD.java new file mode 100644 index 000000000..48f0d8557 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IADD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IADD - Add ints + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IADD extends ArithmeticInstruction { + + /** Add ints + */ + public IADD() { + super(org.apache.tomcat.util.bcel.Constants.IADD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIADD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IALOAD.java b/java/org/apache/tomcat/util/bcel/generic/IALOAD.java new file mode 100644 index 000000000..9511a282b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IALOAD.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IALOAD - Load int from array + *
      Stack: ..., arrayref, index -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IALOAD extends ArrayInstruction implements StackProducer { + + /** + * Load int from array + */ + public IALOAD() { + super(org.apache.tomcat.util.bcel.Constants.IALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitIALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IAND.java b/java/org/apache/tomcat/util/bcel/generic/IAND.java new file mode 100644 index 000000000..10c240df0 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IAND.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IAND - Bitwise AND int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IAND extends ArithmeticInstruction { + + public IAND() { + super(org.apache.tomcat.util.bcel.Constants.IAND); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIAND(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IASTORE.java b/java/org/apache/tomcat/util/bcel/generic/IASTORE.java new file mode 100644 index 000000000..1207d6e18 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IASTORE.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IASTORE - Store into int array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IASTORE extends ArrayInstruction implements StackConsumer { + + /** + * Store into int array + */ + public IASTORE() { + super(org.apache.tomcat.util.bcel.Constants.IASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitIASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ICONST.java b/java/org/apache/tomcat/util/bcel/generic/ICONST.java new file mode 100644 index 000000000..239570c3c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ICONST.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ICONST - Push value between -1, ..., 5, other values cause an exception + * + *
      Stack: ... -> ..., 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ICONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + private int value; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ICONST() { + } + + + public ICONST(int i) { + super(org.apache.tomcat.util.bcel.Constants.ICONST_0, (short) 1); + if ((i >= -1) && (i <= 5)) { + opcode = (short) (org.apache.tomcat.util.bcel.Constants.ICONST_0 + i); // Even works for i == -1 + } else { + throw new ClassGenException("ICONST can be used only for value between -1 and 5: " + i); + } + value = i; + } + + + public Number getValue() { + return new Integer(value); + } + + + /** @return Type.INT + */ + public Type getType( ConstantPoolGen cp ) { + return Type.INT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitICONST(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IDIV.java b/java/org/apache/tomcat/util/bcel/generic/IDIV.java new file mode 100644 index 000000000..ec999af5f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IDIV.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IDIV - Divide ints + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IDIV extends ArithmeticInstruction implements ExceptionThrower { + + /** Divide ints + */ + public IDIV() { + super(org.apache.tomcat.util.bcel.Constants.IDIV); + } + + + /** @return exceptions this instruction may cause + */ + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIDIV(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFEQ.java b/java/org/apache/tomcat/util/bcel/generic/IFEQ.java new file mode 100644 index 000000000..334ea9e8b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFEQ.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFEQ - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFEQ extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFEQ() { + } + + + public IFEQ(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFEQ, target); + } + + + /** + * @return negation of instruction, e.g. IFEQ.negate() == IFNE + */ + public IfInstruction negate() { + return new IFNE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFEQ(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFGE.java b/java/org/apache/tomcat/util/bcel/generic/IFGE.java new file mode 100644 index 000000000..2fdb428b9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFGE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFGE - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFGE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFGE() { + } + + + public IFGE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFGE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFLT(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFGE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFGT.java b/java/org/apache/tomcat/util/bcel/generic/IFGT.java new file mode 100644 index 000000000..0d94ac77e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFGT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFGT - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFGT extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFGT() { + } + + + public IFGT(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFGT, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFLE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFGT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFLE.java b/java/org/apache/tomcat/util/bcel/generic/IFLE.java new file mode 100644 index 000000000..c59da8c35 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFLE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFLE - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFLE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFLE() { + } + + + public IFLE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFLE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFGT(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFLE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFLT.java b/java/org/apache/tomcat/util/bcel/generic/IFLT.java new file mode 100644 index 000000000..560bf9baa --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFLT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFLT - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFLT extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFLT() { + } + + + public IFLT(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFLT, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFGE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFLT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFNE.java b/java/org/apache/tomcat/util/bcel/generic/IFNE.java new file mode 100644 index 000000000..f32bb7f1e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFNE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFNE - Branch if int comparison with zero succeeds + * + *
      Stack: ..., value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFNE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFNE() { + } + + + public IFNE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFNE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFEQ(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFNE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFNONNULL.java b/java/org/apache/tomcat/util/bcel/generic/IFNONNULL.java new file mode 100644 index 000000000..1248d0d35 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFNONNULL.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFNONNULL - Branch if reference is not null + * + *
      Stack: ..., reference -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFNONNULL extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFNONNULL() { + } + + + public IFNONNULL(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFNONNULL, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFNULL(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFNONNULL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IFNULL.java b/java/org/apache/tomcat/util/bcel/generic/IFNULL.java new file mode 100644 index 000000000..80e93877d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IFNULL.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IFNULL - Branch if reference is not null + * + *
      Stack: ..., reference -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IFNULL extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IFNULL() { + } + + + public IFNULL(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IFNULL, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IFNONNULL(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIFNULL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ACMPEQ.java b/java/org/apache/tomcat/util/bcel/generic/IF_ACMPEQ.java new file mode 100644 index 000000000..8b0527649 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ACMPEQ.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ACMPEQ - Branch if reference comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ACMPEQ extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ACMPEQ() { + } + + + public IF_ACMPEQ(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ACMPEQ, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ACMPNE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ACMPEQ(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ACMPNE.java b/java/org/apache/tomcat/util/bcel/generic/IF_ACMPNE.java new file mode 100644 index 000000000..02f821d26 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ACMPNE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ACMPNE - Branch if reference comparison doesn't succeed + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ACMPNE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ACMPNE() { + } + + + public IF_ACMPNE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ACMPNE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ACMPEQ(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ACMPNE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPEQ.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPEQ.java new file mode 100644 index 000000000..b8822da5b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPEQ.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPEQ - Branch if int comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPEQ extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPEQ() { + } + + + public IF_ICMPEQ(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPEQ, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPNE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPEQ(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGE.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGE.java new file mode 100644 index 000000000..b24fd7761 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPGE - Branch if int comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPGE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPGE() { + } + + + public IF_ICMPGE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPGE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPLT(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPGE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGT.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGT.java new file mode 100644 index 000000000..580311c65 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPGT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPGT - Branch if int comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPGT extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPGT() { + } + + + public IF_ICMPGT(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPGT, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPLE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPGT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLE.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLE.java new file mode 100644 index 000000000..1caa276f7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPLE - Branch if int comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPLE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPLE() { + } + + + public IF_ICMPLE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPLE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPGT(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPLE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLT.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLT.java new file mode 100644 index 000000000..b5cf633e0 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPLT.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPLT - Branch if int comparison succeeds + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPLT extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPLT() { + } + + + public IF_ICMPLT(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPLT, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPGE(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPLT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IF_ICMPNE.java b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPNE.java new file mode 100644 index 000000000..5852e8276 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IF_ICMPNE.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IF_ICMPNE - Branch if int comparison doesn't succeed + * + *
      Stack: ..., value1, value2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IF_ICMPNE extends IfInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IF_ICMPNE() { + } + + + public IF_ICMPNE(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.IF_ICMPNE, target); + } + + + /** + * @return negation of instruction + */ + public IfInstruction negate() { + return new IF_ICMPEQ(target); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitBranchInstruction(this); + v.visitIfInstruction(this); + v.visitIF_ICMPNE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IINC.java b/java/org/apache/tomcat/util/bcel/generic/IINC.java new file mode 100644 index 000000000..4d62e1e6e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IINC.java @@ -0,0 +1,158 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * IINC - Increment local variable by constant + * + * @version $Id$ + * @author M. Dahm + */ +public class IINC extends LocalVariableInstruction { + + private boolean wide; + private int c; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IINC() { + } + + + /** + * @param n index of local variable + * @param c increment factor + */ + public IINC(int n, int c) { + super(); // Default behaviour of LocalVariableInstruction causes error + this.opcode = org.apache.tomcat.util.bcel.Constants.IINC; + this.length = (short) 3; + setIndex(n); // May set wide as side effect + setIncrement(c); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + if (wide) { + out.writeByte(org.apache.tomcat.util.bcel.Constants.WIDE); + } + out.writeByte(opcode); + if (wide) { + out.writeShort(n); + out.writeShort(c); + } else { + out.writeByte(n); + out.writeByte(c); + } + } + + + private final void setWide() { + wide = (n > org.apache.tomcat.util.bcel.Constants.MAX_BYTE) || (Math.abs(c) > Byte.MAX_VALUE); + if (wide) { + length = 6; // wide byte included + } else { + length = 3; + } + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + this.wide = wide; + if (wide) { + length = 6; + n = bytes.readUnsignedShort(); + c = bytes.readShort(); + } else { + length = 3; + n = bytes.readUnsignedByte(); + c = bytes.readByte(); + } + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + c; + } + + + /** + * Set index of local variable. + */ + public final void setIndex( int n ) { + if (n < 0) { + throw new ClassGenException("Negative index value: " + n); + } + this.n = n; + setWide(); + } + + + /** + * @return increment factor + */ + public final int getIncrement() { + return c; + } + + + /** + * Set increment factor. + */ + public final void setIncrement( int c ) { + this.c = c; + setWide(); + } + + + /** @return int type + */ + public Type getType( ConstantPoolGen cp ) { + return Type.INT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLocalVariableInstruction(this); + v.visitIINC(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ILOAD.java b/java/org/apache/tomcat/util/bcel/generic/ILOAD.java new file mode 100644 index 000000000..404d6a4de --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ILOAD.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ILOAD - Load int from local variable onto stack + *
      Stack: ... -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ILOAD extends LoadInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ILOAD() { + super(org.apache.tomcat.util.bcel.Constants.ILOAD, org.apache.tomcat.util.bcel.Constants.ILOAD_0); + } + + + /** Load int from local variable + * @param n index of local variable + */ + public ILOAD(int n) { + super(org.apache.tomcat.util.bcel.Constants.ILOAD, org.apache.tomcat.util.bcel.Constants.ILOAD_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitILOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IMPDEP1.java b/java/org/apache/tomcat/util/bcel/generic/IMPDEP1.java new file mode 100644 index 000000000..00d2b06ce --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IMPDEP1.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IMPDEP1 - Implementation dependent + * + * @version $Id$ + * @author M. Dahm + */ +public class IMPDEP1 extends Instruction { + + public IMPDEP1() { + super(org.apache.tomcat.util.bcel.Constants.IMPDEP1, (short) 1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitIMPDEP1(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IMPDEP2.java b/java/org/apache/tomcat/util/bcel/generic/IMPDEP2.java new file mode 100644 index 000000000..7b110c1f3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IMPDEP2.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IMPDEP2 - Implementation dependent + * + * @version $Id$ + * @author M. Dahm + */ +public class IMPDEP2 extends Instruction { + + public IMPDEP2() { + super(org.apache.tomcat.util.bcel.Constants.IMPDEP2, (short) 1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitIMPDEP2(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IMUL.java b/java/org/apache/tomcat/util/bcel/generic/IMUL.java new file mode 100644 index 000000000..39e23c643 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IMUL.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IMUL - Multiply ints + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IMUL extends ArithmeticInstruction { + + /** Multiply ints + */ + public IMUL() { + super(org.apache.tomcat.util.bcel.Constants.IMUL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIMUL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INEG.java b/java/org/apache/tomcat/util/bcel/generic/INEG.java new file mode 100644 index 000000000..33a23f03a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INEG.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * INEG - Negate int + *
      Stack: ..., value -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class INEG extends ArithmeticInstruction { + + public INEG() { + super(org.apache.tomcat.util.bcel.Constants.INEG); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitINEG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INSTANCEOF.java b/java/org/apache/tomcat/util/bcel/generic/INSTANCEOF.java new file mode 100644 index 000000000..061abf10a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INSTANCEOF.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * INSTANCEOF - Determine if object is of given type + *
      Stack: ..., objectref -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class INSTANCEOF extends CPInstruction implements LoadClass, ExceptionThrower, + StackProducer, StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + INSTANCEOF() { + } + + + public INSTANCEOF(int index) { + super(org.apache.tomcat.util.bcel.Constants.INSTANCEOF, index); + } + + + public Class[] getExceptions() { + return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION; + } + + + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return (t instanceof ObjectType) ? (ObjectType) t : null; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLoadClass(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitINSTANCEOF(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INVOKEINTERFACE.java b/java/org/apache/tomcat/util/bcel/generic/INVOKEINTERFACE.java new file mode 100644 index 000000000..ae9fc8135 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INVOKEINTERFACE.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * INVOKEINTERFACE - Invoke interface method + *
      Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public final class INVOKEINTERFACE extends InvokeInstruction { + + private int nargs; // Number of arguments on stack (number of stack slots), called "count" in vmspec2 + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + INVOKEINTERFACE() { + } + + + public INVOKEINTERFACE(int index, int nargs) { + super(Constants.INVOKEINTERFACE, index); + length = 5; + if (nargs < 1) { + throw new ClassGenException("Number of arguments must be > 0 " + nargs); + } + this.nargs = nargs; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + out.writeByte(nargs); + out.writeByte(0); + } + + + /** + * The count argument according to the Java Language Specification, + * Second Edition. + */ + public int getCount() { + return nargs; + } + + + /** + * Read needed data (i.e., index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + super.initFromFile(bytes, wide); + length = 5; + nargs = bytes.readUnsignedByte(); + bytes.readByte(); // Skip 0 byte + } + + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString( ConstantPool cp ) { + return super.toString(cp) + " " + nargs; + } + + + public int consumeStack( ConstantPoolGen cpg ) { // nargs is given in byte-code + return nargs; // nargs includes this reference + } + + + public Class[] getExceptions() { + Class[] cs = new Class[4 + ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 3] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ILLEGAL_ACCESS_ERROR; + cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length + 1] = ExceptionConstants.ABSTRACT_METHOD_ERROR; + cs[ExceptionConstants.EXCS_INTERFACE_METHOD_RESOLUTION.length] = ExceptionConstants.UNSATISFIED_LINK_ERROR; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitInvokeInstruction(this); + v.visitINVOKEINTERFACE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INVOKESPECIAL.java b/java/org/apache/tomcat/util/bcel/generic/INVOKESPECIAL.java new file mode 100644 index 000000000..092e5e410 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INVOKESPECIAL.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * INVOKESPECIAL - Invoke instance method; special handling for superclass, private + * and instance initialization method invocations + * + *
      Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class INVOKESPECIAL extends InvokeInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + INVOKESPECIAL() { + } + + + public INVOKESPECIAL(int index) { + super(Constants.INVOKESPECIAL, index); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[4 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 3] = ExceptionConstants.UNSATISFIED_LINK_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ABSTRACT_METHOD_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitInvokeInstruction(this); + v.visitINVOKESPECIAL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INVOKESTATIC.java b/java/org/apache/tomcat/util/bcel/generic/INVOKESTATIC.java new file mode 100644 index 000000000..3efbd9504 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INVOKESTATIC.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * INVOKESTATIC - Invoke a class (static) method + * + *
      Stack: ..., [arg1, [arg2 ...]] -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class INVOKESTATIC extends InvokeInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + INVOKESTATIC() { + } + + + public INVOKESTATIC(int index) { + super(Constants.INVOKESTATIC, index); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.UNSATISFIED_LINK_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitInvokeInstruction(this); + v.visitINVOKESTATIC(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/INVOKEVIRTUAL.java b/java/org/apache/tomcat/util/bcel/generic/INVOKEVIRTUAL.java new file mode 100644 index 000000000..461693656 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/INVOKEVIRTUAL.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * INVOKEVIRTUAL - Invoke instance method; dispatch based on class + * + *
      Stack: ..., objectref, [arg1, [arg2 ...]] -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class INVOKEVIRTUAL extends InvokeInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + INVOKEVIRTUAL() { + } + + + public INVOKEVIRTUAL(int index) { + super(Constants.INVOKEVIRTUAL, index); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[4 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 3] = ExceptionConstants.UNSATISFIED_LINK_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 2] = ExceptionConstants.ABSTRACT_METHOD_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitInvokeInstruction(this); + v.visitINVOKEVIRTUAL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IOR.java b/java/org/apache/tomcat/util/bcel/generic/IOR.java new file mode 100644 index 000000000..d6cf5cd1b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IOR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IOR - Bitwise OR int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IOR extends ArithmeticInstruction { + + public IOR() { + super(org.apache.tomcat.util.bcel.Constants.IOR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIOR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IREM.java b/java/org/apache/tomcat/util/bcel/generic/IREM.java new file mode 100644 index 000000000..67b3cac54 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IREM.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IREM - Remainder of int + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IREM extends ArithmeticInstruction implements ExceptionThrower { + + /** Remainder of ints + */ + public IREM() { + super(org.apache.tomcat.util.bcel.Constants.IREM); + } + + + /** @return exceptions this instruction may cause + */ + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIREM(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IRETURN.java b/java/org/apache/tomcat/util/bcel/generic/IRETURN.java new file mode 100644 index 000000000..e21b5ac25 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IRETURN.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IRETURN - Return int from method + *
      Stack: ..., value -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IRETURN extends ReturnInstruction { + + /** Return int from method + */ + public IRETURN() { + super(org.apache.tomcat.util.bcel.Constants.IRETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitIRETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ISHL.java b/java/org/apache/tomcat/util/bcel/generic/ISHL.java new file mode 100644 index 000000000..516dfb077 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ISHL.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ISHL - Arithmetic shift left int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ISHL extends ArithmeticInstruction { + + public ISHL() { + super(org.apache.tomcat.util.bcel.Constants.ISHL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitISHL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ISHR.java b/java/org/apache/tomcat/util/bcel/generic/ISHR.java new file mode 100644 index 000000000..d8bbb010a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ISHR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ISHR - Arithmetic shift right int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ISHR extends ArithmeticInstruction { + + public ISHR() { + super(org.apache.tomcat.util.bcel.Constants.ISHR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitISHR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ISTORE.java b/java/org/apache/tomcat/util/bcel/generic/ISTORE.java new file mode 100644 index 000000000..f0a0ca197 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ISTORE.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ISTORE - Store int from stack into local variable + *
      Stack: ..., value -> ... 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ISTORE extends StoreInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ISTORE() { + super(org.apache.tomcat.util.bcel.Constants.ISTORE, org.apache.tomcat.util.bcel.Constants.ISTORE_0); + } + + + /** Store int into local variable + * @param n index of local variable + */ + public ISTORE(int n) { + super(org.apache.tomcat.util.bcel.Constants.ISTORE, org.apache.tomcat.util.bcel.Constants.ISTORE_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitISTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ISUB.java b/java/org/apache/tomcat/util/bcel/generic/ISUB.java new file mode 100644 index 000000000..67b5a6665 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ISUB.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * ISUB - Substract ints + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class ISUB extends ArithmeticInstruction { + + /** Substract ints + */ + public ISUB() { + super(org.apache.tomcat.util.bcel.Constants.ISUB); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitISUB(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IUSHR.java b/java/org/apache/tomcat/util/bcel/generic/IUSHR.java new file mode 100644 index 000000000..f2bc5b472 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IUSHR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IUSHR - Logical shift right int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IUSHR extends ArithmeticInstruction { + + public IUSHR() { + super(org.apache.tomcat.util.bcel.Constants.IUSHR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIUSHR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IXOR.java b/java/org/apache/tomcat/util/bcel/generic/IXOR.java new file mode 100644 index 000000000..d898b1681 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IXOR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * IXOR - Bitwise XOR int + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class IXOR extends ArithmeticInstruction { + + public IXOR() { + super(org.apache.tomcat.util.bcel.Constants.IXOR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitIXOR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IfInstruction.java b/java/org/apache/tomcat/util/bcel/generic/IfInstruction.java new file mode 100644 index 000000000..df8895000 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IfInstruction.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Super class for the IFxxx family of instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class IfInstruction extends BranchInstruction implements StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + IfInstruction() { + } + + + /** + * @param opcode opcode of instruction + * @param target Target instruction to branch to + */ + protected IfInstruction(short opcode, InstructionHandle target) { + super(opcode, target); + } + + + /** + * @return negation of instruction, e.g. IFEQ.negate() == IFNE + */ + public abstract IfInstruction negate(); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/IndexedInstruction.java b/java/org/apache/tomcat/util/bcel/generic/IndexedInstruction.java new file mode 100644 index 000000000..be50d6317 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/IndexedInstruction.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote entity that refers to an index, e.g. local variable instructions, + * RET, CPInstruction, etc. + * + * @version $Id$ + * @author M. Dahm + */ +public interface IndexedInstruction { + + public int getIndex(); + + + public void setIndex( int index ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/Instruction.java b/java/org/apache/tomcat/util/bcel/generic/Instruction.java new file mode 100644 index 000000000..e294bf78f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/Instruction.java @@ -0,0 +1,548 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.Locale; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Abstract super class for all Java byte codes. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class Instruction implements Cloneable, Serializable { + + protected short length = 1; // Length of instruction in bytes + protected short opcode = -1; // Opcode number + private static InstructionComparator cmp = InstructionComparator.DEFAULT; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + Instruction() { + } + + + public Instruction(short opcode, short length) { + this.length = length; + this.opcode = opcode; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); // Common for all instructions + } + + + /** @return name of instruction, i.e., opcode name + */ + public String getName() { + return Constants.OPCODE_NAMES[opcode]; + } + + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" + * "("<length of instruction>")" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + if (verbose) { + return getName() + "[" + opcode + "](" + length + ")"; + } else { + return getName(); + } + } + + + /** + * @return mnemonic for instruction in verbose format + */ + public String toString() { + return toString(true); + } + + + /** + * @return mnemonic for instruction with sumbolic references resolved + */ + public String toString( ConstantPool cp ) { + return toString(false); + } + + + /** + * Use with caution, since `BranchInstruction's have a `target' reference which + * is not copied correctly (only basic types are). This also applies for + * `Select' instructions with their multiple branch targets. + * + * @see BranchInstruction + * @return (shallow) copy of an instruction + */ + public Instruction copy() { + Instruction i = null; + // "Constant" instruction, no need to duplicate + if (InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null) { + i = this; + } else { + try { + i = (Instruction) clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + } + } + return i; + } + + + /** + * Read needed data (e.g. index) from file. + * + * @param bytes byte sequence to read from + * @param wide "wide" instruction flag + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + } + + + /** + * Read an instruction from (byte code) input stream and return the + * appropiate object. + * + * @param bytes input stream bytes + * @return instruction object being read + */ + public static final Instruction readInstruction( ByteSequence bytes ) throws IOException { + boolean wide = false; + short opcode = (short) bytes.readUnsignedByte(); + Instruction obj = null; + if (opcode == Constants.WIDE) { // Read next opcode after wide byte + wide = true; + opcode = (short) bytes.readUnsignedByte(); + } + if (InstructionConstants.INSTRUCTIONS[opcode] != null) { + return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available + } + + switch (opcode) { + case Constants.BIPUSH: + obj = new BIPUSH(); + break; + case Constants.SIPUSH: + obj = new SIPUSH(); + break; + case Constants.LDC: + obj = new LDC(); + break; + case Constants.LDC_W: + obj = new LDC_W(); + break; + case Constants.LDC2_W: + obj = new LDC2_W(); + break; + case Constants.ILOAD: + obj = new ILOAD(); + break; + case Constants.LLOAD: + obj = new LLOAD(); + break; + case Constants.FLOAD: + obj = new FLOAD(); + break; + case Constants.DLOAD: + obj = new DLOAD(); + break; + case Constants.ALOAD: + obj = new ALOAD(); + break; + case Constants.ILOAD_0: + obj = new ILOAD(0); + break; + case Constants.ILOAD_1: + obj = new ILOAD(1); + break; + case Constants.ILOAD_2: + obj = new ILOAD(2); + break; + case Constants.ILOAD_3: + obj = new ILOAD(3); + break; + case Constants.LLOAD_0: + obj = new LLOAD(0); + break; + case Constants.LLOAD_1: + obj = new LLOAD(1); + break; + case Constants.LLOAD_2: + obj = new LLOAD(2); + break; + case Constants.LLOAD_3: + obj = new LLOAD(3); + break; + case Constants.FLOAD_0: + obj = new FLOAD(0); + break; + case Constants.FLOAD_1: + obj = new FLOAD(1); + break; + case Constants.FLOAD_2: + obj = new FLOAD(2); + break; + case Constants.FLOAD_3: + obj = new FLOAD(3); + break; + case Constants.DLOAD_0: + obj = new DLOAD(0); + break; + case Constants.DLOAD_1: + obj = new DLOAD(1); + break; + case Constants.DLOAD_2: + obj = new DLOAD(2); + break; + case Constants.DLOAD_3: + obj = new DLOAD(3); + break; + case Constants.ALOAD_0: + obj = new ALOAD(0); + break; + case Constants.ALOAD_1: + obj = new ALOAD(1); + break; + case Constants.ALOAD_2: + obj = new ALOAD(2); + break; + case Constants.ALOAD_3: + obj = new ALOAD(3); + break; + case Constants.ISTORE: + obj = new ISTORE(); + break; + case Constants.LSTORE: + obj = new LSTORE(); + break; + case Constants.FSTORE: + obj = new FSTORE(); + break; + case Constants.DSTORE: + obj = new DSTORE(); + break; + case Constants.ASTORE: + obj = new ASTORE(); + break; + case Constants.ISTORE_0: + obj = new ISTORE(0); + break; + case Constants.ISTORE_1: + obj = new ISTORE(1); + break; + case Constants.ISTORE_2: + obj = new ISTORE(2); + break; + case Constants.ISTORE_3: + obj = new ISTORE(3); + break; + case Constants.LSTORE_0: + obj = new LSTORE(0); + break; + case Constants.LSTORE_1: + obj = new LSTORE(1); + break; + case Constants.LSTORE_2: + obj = new LSTORE(2); + break; + case Constants.LSTORE_3: + obj = new LSTORE(3); + break; + case Constants.FSTORE_0: + obj = new FSTORE(0); + break; + case Constants.FSTORE_1: + obj = new FSTORE(1); + break; + case Constants.FSTORE_2: + obj = new FSTORE(2); + break; + case Constants.FSTORE_3: + obj = new FSTORE(3); + break; + case Constants.DSTORE_0: + obj = new DSTORE(0); + break; + case Constants.DSTORE_1: + obj = new DSTORE(1); + break; + case Constants.DSTORE_2: + obj = new DSTORE(2); + break; + case Constants.DSTORE_3: + obj = new DSTORE(3); + break; + case Constants.ASTORE_0: + obj = new ASTORE(0); + break; + case Constants.ASTORE_1: + obj = new ASTORE(1); + break; + case Constants.ASTORE_2: + obj = new ASTORE(2); + break; + case Constants.ASTORE_3: + obj = new ASTORE(3); + break; + case Constants.IINC: + obj = new IINC(); + break; + case Constants.IFEQ: + obj = new IFEQ(); + break; + case Constants.IFNE: + obj = new IFNE(); + break; + case Constants.IFLT: + obj = new IFLT(); + break; + case Constants.IFGE: + obj = new IFGE(); + break; + case Constants.IFGT: + obj = new IFGT(); + break; + case Constants.IFLE: + obj = new IFLE(); + break; + case Constants.IF_ICMPEQ: + obj = new IF_ICMPEQ(); + break; + case Constants.IF_ICMPNE: + obj = new IF_ICMPNE(); + break; + case Constants.IF_ICMPLT: + obj = new IF_ICMPLT(); + break; + case Constants.IF_ICMPGE: + obj = new IF_ICMPGE(); + break; + case Constants.IF_ICMPGT: + obj = new IF_ICMPGT(); + break; + case Constants.IF_ICMPLE: + obj = new IF_ICMPLE(); + break; + case Constants.IF_ACMPEQ: + obj = new IF_ACMPEQ(); + break; + case Constants.IF_ACMPNE: + obj = new IF_ACMPNE(); + break; + case Constants.GOTO: + obj = new GOTO(); + break; + case Constants.JSR: + obj = new JSR(); + break; + case Constants.RET: + obj = new RET(); + break; + case Constants.TABLESWITCH: + obj = new TABLESWITCH(); + break; + case Constants.LOOKUPSWITCH: + obj = new LOOKUPSWITCH(); + break; + case Constants.GETSTATIC: + obj = new GETSTATIC(); + break; + case Constants.PUTSTATIC: + obj = new PUTSTATIC(); + break; + case Constants.GETFIELD: + obj = new GETFIELD(); + break; + case Constants.PUTFIELD: + obj = new PUTFIELD(); + break; + case Constants.INVOKEVIRTUAL: + obj = new INVOKEVIRTUAL(); + break; + case Constants.INVOKESPECIAL: + obj = new INVOKESPECIAL(); + break; + case Constants.INVOKESTATIC: + obj = new INVOKESTATIC(); + break; + case Constants.INVOKEINTERFACE: + obj = new INVOKEINTERFACE(); + break; + case Constants.NEW: + obj = new NEW(); + break; + case Constants.NEWARRAY: + obj = new NEWARRAY(); + break; + case Constants.ANEWARRAY: + obj = new ANEWARRAY(); + break; + case Constants.CHECKCAST: + obj = new CHECKCAST(); + break; + case Constants.INSTANCEOF: + obj = new INSTANCEOF(); + break; + case Constants.MULTIANEWARRAY: + obj = new MULTIANEWARRAY(); + break; + case Constants.IFNULL: + obj = new IFNULL(); + break; + case Constants.IFNONNULL: + obj = new IFNONNULL(); + break; + case Constants.GOTO_W: + obj = new GOTO_W(); + break; + case Constants.JSR_W: + obj = new JSR_W(); + break; + case Constants.BREAKPOINT: + obj = new BREAKPOINT(); + break; + case Constants.IMPDEP1: + obj = new IMPDEP1(); + break; + case Constants.IMPDEP2: + obj = new IMPDEP2(); + break; + default: + throw new ClassGenException("Illegal opcode detected: " + opcode); + + } + + if (wide + && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) { + throw new ClassGenException("Illegal opcode after wide: " + opcode); + } + obj.setOpcode(opcode); + obj.initFromFile(bytes, wide); // Do further initializations, if any + return obj; + } + + /** + * This method also gives right results for instructions whose + * effect on the stack depends on the constant pool entry they + * reference. + * @return Number of words consumed from stack by this instruction, + * or Constants.UNPREDICTABLE, if this can not be computed statically + */ + public int consumeStack( ConstantPoolGen cpg ) { + return Constants.CONSUME_STACK[opcode]; + } + + + /** + * This method also gives right results for instructions whose + * effect on the stack depends on the constant pool entry they + * reference. + * @return Number of words produced onto stack by this instruction, + * or Constants.UNPREDICTABLE, if this can not be computed statically + */ + public int produceStack( ConstantPoolGen cpg ) { + return Constants.PRODUCE_STACK[opcode]; + } + + + /** + * @return this instructions opcode + */ + public short getOpcode() { + return opcode; + } + + + /** + * @return length (in bytes) of instruction + */ + public int getLength() { + return length; + } + + + /** + * Needed in readInstruction. + */ + private void setOpcode( short opcode ) { + this.opcode = opcode; + } + + + /** Some instructions may be reused, so don't do anything by default. + */ + void dispose() { + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public abstract void accept( Visitor v ); + + + /** Get Comparator object used in the equals() method to determine + * equality of instructions. + * + * @return currently used comparator for equals() + */ + public static InstructionComparator getComparator() { + return cmp; + } + + + /** Set comparator to be used for equals(). + */ + public static void setComparator( InstructionComparator c ) { + cmp = c; + } + + + /** Check for equality, delegated to comparator + * @return true if that is an Instruction and has the same opcode + */ + public boolean equals( Object that ) { + return (that instanceof Instruction) ? cmp.equals(this, (Instruction) that) : false; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionComparator.java b/java/org/apache/tomcat/util/bcel/generic/InstructionComparator.java new file mode 100644 index 000000000..71bac694d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionComparator.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Equality of instructions isn't clearly to be defined. You might + * wish, for example, to compare whether instructions have the same + * meaning. E.g., whether two INVOKEVIRTUALs describe the same + * call.
      The DEFAULT comparator however, considers two instructions + * to be equal if they have same opcode and point to the same indexes + * (if any) in the constant pool or the same local variable index. Branch + * instructions must have the same target. + * + * @see Instruction + * @version $Id$ + * @author M. Dahm + */ +public interface InstructionComparator { + + public static final InstructionComparator DEFAULT = new InstructionComparator() { + + public boolean equals( Instruction i1, Instruction i2 ) { + if (i1.opcode == i2.opcode) { + if (i1 instanceof Select) { + InstructionHandle[] t1 = ((Select) i1).getTargets(); + InstructionHandle[] t2 = ((Select) i2).getTargets(); + if (t1.length == t2.length) { + for (int i = 0; i < t1.length; i++) { + if (t1[i] != t2[i]) { + return false; + } + } + return true; + } + } else if (i1 instanceof BranchInstruction) { + return ((BranchInstruction) i1).target == ((BranchInstruction) i2).target; + } else if (i1 instanceof ConstantPushInstruction) { + return ((ConstantPushInstruction) i1).getValue().equals( + ((ConstantPushInstruction) i2).getValue()); + } else if (i1 instanceof IndexedInstruction) { + return ((IndexedInstruction) i1).getIndex() == ((IndexedInstruction) i2) + .getIndex(); + } else if (i1 instanceof NEWARRAY) { + return ((NEWARRAY) i1).getTypecode() == ((NEWARRAY) i2).getTypecode(); + } else { + return true; + } + } + return false; + } + }; + + + public boolean equals( Instruction i1, Instruction i2 ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionConstants.java b/java/org/apache/tomcat/util/bcel/generic/InstructionConstants.java new file mode 100644 index 000000000..817015a48 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionConstants.java @@ -0,0 +1,286 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * This interface contains shareable instruction objects. + * + * In order to save memory you can use some instructions multiply, + * since they have an immutable state and are directly derived from + * Instruction. I.e. they have no instance fields that could be + * changed. Since some of these instructions like ICONST_0 occur + * very frequently this can save a lot of time and space. This + * feature is an adaptation of the FlyWeight design pattern, we + * just use an array instead of a factory. + * + * The Instructions can also accessed directly under their names, so + * it's possible to write il.append(Instruction.ICONST_0); + * + * @version $Id$ + * @author M. Dahm + */ +public interface InstructionConstants { + + /** Predefined instruction objects + */ + public static final Instruction NOP = new NOP(); + public static final Instruction ACONST_NULL = new ACONST_NULL(); + public static final Instruction ICONST_M1 = new ICONST(-1); + public static final Instruction ICONST_0 = new ICONST(0); + public static final Instruction ICONST_1 = new ICONST(1); + public static final Instruction ICONST_2 = new ICONST(2); + public static final Instruction ICONST_3 = new ICONST(3); + public static final Instruction ICONST_4 = new ICONST(4); + public static final Instruction ICONST_5 = new ICONST(5); + public static final Instruction LCONST_0 = new LCONST(0); + public static final Instruction LCONST_1 = new LCONST(1); + public static final Instruction FCONST_0 = new FCONST(0); + public static final Instruction FCONST_1 = new FCONST(1); + public static final Instruction FCONST_2 = new FCONST(2); + public static final Instruction DCONST_0 = new DCONST(0); + public static final Instruction DCONST_1 = new DCONST(1); + public static final ArrayInstruction IALOAD = new IALOAD(); + public static final ArrayInstruction LALOAD = new LALOAD(); + public static final ArrayInstruction FALOAD = new FALOAD(); + public static final ArrayInstruction DALOAD = new DALOAD(); + public static final ArrayInstruction AALOAD = new AALOAD(); + public static final ArrayInstruction BALOAD = new BALOAD(); + public static final ArrayInstruction CALOAD = new CALOAD(); + public static final ArrayInstruction SALOAD = new SALOAD(); + public static final ArrayInstruction IASTORE = new IASTORE(); + public static final ArrayInstruction LASTORE = new LASTORE(); + public static final ArrayInstruction FASTORE = new FASTORE(); + public static final ArrayInstruction DASTORE = new DASTORE(); + public static final ArrayInstruction AASTORE = new AASTORE(); + public static final ArrayInstruction BASTORE = new BASTORE(); + public static final ArrayInstruction CASTORE = new CASTORE(); + public static final ArrayInstruction SASTORE = new SASTORE(); + public static final StackInstruction POP = new POP(); + public static final StackInstruction POP2 = new POP2(); + public static final StackInstruction DUP = new DUP(); + public static final StackInstruction DUP_X1 = new DUP_X1(); + public static final StackInstruction DUP_X2 = new DUP_X2(); + public static final StackInstruction DUP2 = new DUP2(); + public static final StackInstruction DUP2_X1 = new DUP2_X1(); + public static final StackInstruction DUP2_X2 = new DUP2_X2(); + public static final StackInstruction SWAP = new SWAP(); + public static final ArithmeticInstruction IADD = new IADD(); + public static final ArithmeticInstruction LADD = new LADD(); + public static final ArithmeticInstruction FADD = new FADD(); + public static final ArithmeticInstruction DADD = new DADD(); + public static final ArithmeticInstruction ISUB = new ISUB(); + public static final ArithmeticInstruction LSUB = new LSUB(); + public static final ArithmeticInstruction FSUB = new FSUB(); + public static final ArithmeticInstruction DSUB = new DSUB(); + public static final ArithmeticInstruction IMUL = new IMUL(); + public static final ArithmeticInstruction LMUL = new LMUL(); + public static final ArithmeticInstruction FMUL = new FMUL(); + public static final ArithmeticInstruction DMUL = new DMUL(); + public static final ArithmeticInstruction IDIV = new IDIV(); + public static final ArithmeticInstruction LDIV = new LDIV(); + public static final ArithmeticInstruction FDIV = new FDIV(); + public static final ArithmeticInstruction DDIV = new DDIV(); + public static final ArithmeticInstruction IREM = new IREM(); + public static final ArithmeticInstruction LREM = new LREM(); + public static final ArithmeticInstruction FREM = new FREM(); + public static final ArithmeticInstruction DREM = new DREM(); + public static final ArithmeticInstruction INEG = new INEG(); + public static final ArithmeticInstruction LNEG = new LNEG(); + public static final ArithmeticInstruction FNEG = new FNEG(); + public static final ArithmeticInstruction DNEG = new DNEG(); + public static final ArithmeticInstruction ISHL = new ISHL(); + public static final ArithmeticInstruction LSHL = new LSHL(); + public static final ArithmeticInstruction ISHR = new ISHR(); + public static final ArithmeticInstruction LSHR = new LSHR(); + public static final ArithmeticInstruction IUSHR = new IUSHR(); + public static final ArithmeticInstruction LUSHR = new LUSHR(); + public static final ArithmeticInstruction IAND = new IAND(); + public static final ArithmeticInstruction LAND = new LAND(); + public static final ArithmeticInstruction IOR = new IOR(); + public static final ArithmeticInstruction LOR = new LOR(); + public static final ArithmeticInstruction IXOR = new IXOR(); + public static final ArithmeticInstruction LXOR = new LXOR(); + public static final ConversionInstruction I2L = new I2L(); + public static final ConversionInstruction I2F = new I2F(); + public static final ConversionInstruction I2D = new I2D(); + public static final ConversionInstruction L2I = new L2I(); + public static final ConversionInstruction L2F = new L2F(); + public static final ConversionInstruction L2D = new L2D(); + public static final ConversionInstruction F2I = new F2I(); + public static final ConversionInstruction F2L = new F2L(); + public static final ConversionInstruction F2D = new F2D(); + public static final ConversionInstruction D2I = new D2I(); + public static final ConversionInstruction D2L = new D2L(); + public static final ConversionInstruction D2F = new D2F(); + public static final ConversionInstruction I2B = new I2B(); + public static final ConversionInstruction I2C = new I2C(); + public static final ConversionInstruction I2S = new I2S(); + public static final Instruction LCMP = new LCMP(); + public static final Instruction FCMPL = new FCMPL(); + public static final Instruction FCMPG = new FCMPG(); + public static final Instruction DCMPL = new DCMPL(); + public static final Instruction DCMPG = new DCMPG(); + public static final ReturnInstruction IRETURN = new IRETURN(); + public static final ReturnInstruction LRETURN = new LRETURN(); + public static final ReturnInstruction FRETURN = new FRETURN(); + public static final ReturnInstruction DRETURN = new DRETURN(); + public static final ReturnInstruction ARETURN = new ARETURN(); + public static final ReturnInstruction RETURN = new RETURN(); + public static final Instruction ARRAYLENGTH = new ARRAYLENGTH(); + public static final Instruction ATHROW = new ATHROW(); + public static final Instruction MONITORENTER = new MONITORENTER(); + public static final Instruction MONITOREXIT = new MONITOREXIT(); + /** You can use these constants in multiple places safely, if you can guarantee + * that you will never alter their internal values, e.g. call setIndex(). + */ + public static final LocalVariableInstruction THIS = new ALOAD(0); + public static final LocalVariableInstruction ALOAD_0 = THIS; + public static final LocalVariableInstruction ALOAD_1 = new ALOAD(1); + public static final LocalVariableInstruction ALOAD_2 = new ALOAD(2); + public static final LocalVariableInstruction ILOAD_0 = new ILOAD(0); + public static final LocalVariableInstruction ILOAD_1 = new ILOAD(1); + public static final LocalVariableInstruction ILOAD_2 = new ILOAD(2); + public static final LocalVariableInstruction ASTORE_0 = new ASTORE(0); + public static final LocalVariableInstruction ASTORE_1 = new ASTORE(1); + public static final LocalVariableInstruction ASTORE_2 = new ASTORE(2); + public static final LocalVariableInstruction ISTORE_0 = new ISTORE(0); + public static final LocalVariableInstruction ISTORE_1 = new ISTORE(1); + public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2); + /** Get object via its opcode, for immutable instructions like + * branch instructions entries are set to null. + */ + public static final Instruction[] INSTRUCTIONS = new Instruction[256]; + /** Interfaces may have no static initializers, so we simulate this + * with an inner class. + */ + static final Clinit bla = new Clinit(); + + static class Clinit { + + Clinit() { + INSTRUCTIONS[Constants.NOP] = NOP; + INSTRUCTIONS[Constants.ACONST_NULL] = ACONST_NULL; + INSTRUCTIONS[Constants.ICONST_M1] = ICONST_M1; + INSTRUCTIONS[Constants.ICONST_0] = ICONST_0; + INSTRUCTIONS[Constants.ICONST_1] = ICONST_1; + INSTRUCTIONS[Constants.ICONST_2] = ICONST_2; + INSTRUCTIONS[Constants.ICONST_3] = ICONST_3; + INSTRUCTIONS[Constants.ICONST_4] = ICONST_4; + INSTRUCTIONS[Constants.ICONST_5] = ICONST_5; + INSTRUCTIONS[Constants.LCONST_0] = LCONST_0; + INSTRUCTIONS[Constants.LCONST_1] = LCONST_1; + INSTRUCTIONS[Constants.FCONST_0] = FCONST_0; + INSTRUCTIONS[Constants.FCONST_1] = FCONST_1; + INSTRUCTIONS[Constants.FCONST_2] = FCONST_2; + INSTRUCTIONS[Constants.DCONST_0] = DCONST_0; + INSTRUCTIONS[Constants.DCONST_1] = DCONST_1; + INSTRUCTIONS[Constants.IALOAD] = IALOAD; + INSTRUCTIONS[Constants.LALOAD] = LALOAD; + INSTRUCTIONS[Constants.FALOAD] = FALOAD; + INSTRUCTIONS[Constants.DALOAD] = DALOAD; + INSTRUCTIONS[Constants.AALOAD] = AALOAD; + INSTRUCTIONS[Constants.BALOAD] = BALOAD; + INSTRUCTIONS[Constants.CALOAD] = CALOAD; + INSTRUCTIONS[Constants.SALOAD] = SALOAD; + INSTRUCTIONS[Constants.IASTORE] = IASTORE; + INSTRUCTIONS[Constants.LASTORE] = LASTORE; + INSTRUCTIONS[Constants.FASTORE] = FASTORE; + INSTRUCTIONS[Constants.DASTORE] = DASTORE; + INSTRUCTIONS[Constants.AASTORE] = AASTORE; + INSTRUCTIONS[Constants.BASTORE] = BASTORE; + INSTRUCTIONS[Constants.CASTORE] = CASTORE; + INSTRUCTIONS[Constants.SASTORE] = SASTORE; + INSTRUCTIONS[Constants.POP] = POP; + INSTRUCTIONS[Constants.POP2] = POP2; + INSTRUCTIONS[Constants.DUP] = DUP; + INSTRUCTIONS[Constants.DUP_X1] = DUP_X1; + INSTRUCTIONS[Constants.DUP_X2] = DUP_X2; + INSTRUCTIONS[Constants.DUP2] = DUP2; + INSTRUCTIONS[Constants.DUP2_X1] = DUP2_X1; + INSTRUCTIONS[Constants.DUP2_X2] = DUP2_X2; + INSTRUCTIONS[Constants.SWAP] = SWAP; + INSTRUCTIONS[Constants.IADD] = IADD; + INSTRUCTIONS[Constants.LADD] = LADD; + INSTRUCTIONS[Constants.FADD] = FADD; + INSTRUCTIONS[Constants.DADD] = DADD; + INSTRUCTIONS[Constants.ISUB] = ISUB; + INSTRUCTIONS[Constants.LSUB] = LSUB; + INSTRUCTIONS[Constants.FSUB] = FSUB; + INSTRUCTIONS[Constants.DSUB] = DSUB; + INSTRUCTIONS[Constants.IMUL] = IMUL; + INSTRUCTIONS[Constants.LMUL] = LMUL; + INSTRUCTIONS[Constants.FMUL] = FMUL; + INSTRUCTIONS[Constants.DMUL] = DMUL; + INSTRUCTIONS[Constants.IDIV] = IDIV; + INSTRUCTIONS[Constants.LDIV] = LDIV; + INSTRUCTIONS[Constants.FDIV] = FDIV; + INSTRUCTIONS[Constants.DDIV] = DDIV; + INSTRUCTIONS[Constants.IREM] = IREM; + INSTRUCTIONS[Constants.LREM] = LREM; + INSTRUCTIONS[Constants.FREM] = FREM; + INSTRUCTIONS[Constants.DREM] = DREM; + INSTRUCTIONS[Constants.INEG] = INEG; + INSTRUCTIONS[Constants.LNEG] = LNEG; + INSTRUCTIONS[Constants.FNEG] = FNEG; + INSTRUCTIONS[Constants.DNEG] = DNEG; + INSTRUCTIONS[Constants.ISHL] = ISHL; + INSTRUCTIONS[Constants.LSHL] = LSHL; + INSTRUCTIONS[Constants.ISHR] = ISHR; + INSTRUCTIONS[Constants.LSHR] = LSHR; + INSTRUCTIONS[Constants.IUSHR] = IUSHR; + INSTRUCTIONS[Constants.LUSHR] = LUSHR; + INSTRUCTIONS[Constants.IAND] = IAND; + INSTRUCTIONS[Constants.LAND] = LAND; + INSTRUCTIONS[Constants.IOR] = IOR; + INSTRUCTIONS[Constants.LOR] = LOR; + INSTRUCTIONS[Constants.IXOR] = IXOR; + INSTRUCTIONS[Constants.LXOR] = LXOR; + INSTRUCTIONS[Constants.I2L] = I2L; + INSTRUCTIONS[Constants.I2F] = I2F; + INSTRUCTIONS[Constants.I2D] = I2D; + INSTRUCTIONS[Constants.L2I] = L2I; + INSTRUCTIONS[Constants.L2F] = L2F; + INSTRUCTIONS[Constants.L2D] = L2D; + INSTRUCTIONS[Constants.F2I] = F2I; + INSTRUCTIONS[Constants.F2L] = F2L; + INSTRUCTIONS[Constants.F2D] = F2D; + INSTRUCTIONS[Constants.D2I] = D2I; + INSTRUCTIONS[Constants.D2L] = D2L; + INSTRUCTIONS[Constants.D2F] = D2F; + INSTRUCTIONS[Constants.I2B] = I2B; + INSTRUCTIONS[Constants.I2C] = I2C; + INSTRUCTIONS[Constants.I2S] = I2S; + INSTRUCTIONS[Constants.LCMP] = LCMP; + INSTRUCTIONS[Constants.FCMPL] = FCMPL; + INSTRUCTIONS[Constants.FCMPG] = FCMPG; + INSTRUCTIONS[Constants.DCMPL] = DCMPL; + INSTRUCTIONS[Constants.DCMPG] = DCMPG; + INSTRUCTIONS[Constants.IRETURN] = IRETURN; + INSTRUCTIONS[Constants.LRETURN] = LRETURN; + INSTRUCTIONS[Constants.FRETURN] = FRETURN; + INSTRUCTIONS[Constants.DRETURN] = DRETURN; + INSTRUCTIONS[Constants.ARETURN] = ARETURN; + INSTRUCTIONS[Constants.RETURN] = RETURN; + INSTRUCTIONS[Constants.ARRAYLENGTH] = ARRAYLENGTH; + INSTRUCTIONS[Constants.ATHROW] = ATHROW; + INSTRUCTIONS[Constants.MONITORENTER] = MONITORENTER; + INSTRUCTIONS[Constants.MONITOREXIT] = MONITOREXIT; + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionFactory.java b/java/org/apache/tomcat/util/bcel/generic/InstructionFactory.java new file mode 100644 index 000000000..152f8c408 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionFactory.java @@ -0,0 +1,748 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Instances of this class may be used, e.g., to generate typed + * versions of instructions. Its main purpose is to be used as the + * byte code generating backend of a compiler. You can subclass it to + * add your own create methods. + * + * @version $Id$ + * @author M. Dahm + * @see Constants + */ +public class InstructionFactory implements InstructionConstants, java.io.Serializable { + + private static final String[] short_names = { + "C", "F", "D", "B", "S", "I", "L" + }; + + protected ClassGen cg; + protected ConstantPoolGen cp; + + + public InstructionFactory(ClassGen cg, ConstantPoolGen cp) { + this.cg = cg; + this.cp = cp; + } + + + /** Initialize with ClassGen object + */ + public InstructionFactory(ClassGen cg) { + this(cg, cg.getConstantPool()); + } + + + /** Initialize just with ConstantPoolGen object + */ + public InstructionFactory(ConstantPoolGen cp) { + this(null, cp); + } + + + /** Create an invoke instruction. + * + * @param class_name name of the called class + * @param name name of the called method + * @param ret_type return type of method + * @param arg_types argument types of method + * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL, + * or INVOKESPECIAL + * @see Constants + */ + public InvokeInstruction createInvoke( String class_name, String name, Type ret_type, + Type[] arg_types, short kind ) { + int index; + int nargs = 0; + String signature = Type.getMethodSignature(ret_type, arg_types); + for (int i = 0; i < arg_types.length; i++) { + nargs += arg_types[i].getSize(); + } + if (kind == Constants.INVOKEINTERFACE) { + index = cp.addInterfaceMethodref(class_name, name, signature); + } else { + index = cp.addMethodref(class_name, name, signature); + } + switch (kind) { + case Constants.INVOKESPECIAL: + return new INVOKESPECIAL(index); + case Constants.INVOKEVIRTUAL: + return new INVOKEVIRTUAL(index); + case Constants.INVOKESTATIC: + return new INVOKESTATIC(index); + case Constants.INVOKEINTERFACE: + return new INVOKEINTERFACE(index, nargs + 1); + default: + throw new RuntimeException("Oops: Unknown invoke kind:" + kind); + } + } + + + /** Create a call to the most popular System.out.println() method. + * + * @param s the string to print + */ + public InstructionList createPrintln( String s ) { + InstructionList il = new InstructionList(); + int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;"); + int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V"); + il.append(new GETSTATIC(out)); + il.append(new PUSH(cp, s)); + il.append(new INVOKEVIRTUAL(println)); + return il; + } + + + /** Uses PUSH to push a constant value onto the stack. + * @param value must be of type Number, Boolean, Character or String + */ + public Instruction createConstant( Object value ) { + PUSH push; + if (value instanceof Number) { + push = new PUSH(cp, (Number) value); + } else if (value instanceof String) { + push = new PUSH(cp, (String) value); + } else if (value instanceof Boolean) { + push = new PUSH(cp, (Boolean) value); + } else if (value instanceof Character) { + push = new PUSH(cp, (Character) value); + } else { + throw new ClassGenException("Illegal type: " + value.getClass()); + } + return push.getInstruction(); + } + + private static class MethodObject { + + Type[] arg_types; + Type result_type; + String class_name; + String name; + int access; + + + MethodObject(String c, String n, Type r, Type[] a, int acc) { + class_name = c; + name = n; + result_type = r; + arg_types = a; + access = acc; + } + } + + + private InvokeInstruction createInvoke( MethodObject m, short kind ) { + return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind); + } + + private static MethodObject[] append_mos = { + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.STRING + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.OBJECT + }, Constants.ACC_PUBLIC), + null, + null, // indices 2, 3 + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.BOOLEAN + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.CHAR + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.FLOAT + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.DOUBLE + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.INT + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte) + new Type[] { + Type.INT + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short) + new Type[] { + Type.INT + }, Constants.ACC_PUBLIC), + new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] { + Type.LONG + }, Constants.ACC_PUBLIC) + }; + + + private static final boolean isString( Type type ) { + return ((type instanceof ObjectType) && ((ObjectType) type).getClassName().equals( + "java.lang.String")); + } + + + public Instruction createAppend( Type type ) { + byte t = type.getType(); + if (isString(type)) { + return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL); + } + switch (t) { + case Constants.T_BOOLEAN: + case Constants.T_CHAR: + case Constants.T_FLOAT: + case Constants.T_DOUBLE: + case Constants.T_BYTE: + case Constants.T_SHORT: + case Constants.T_INT: + case Constants.T_LONG: + return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL); + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL); + default: + throw new RuntimeException("Oops: No append for this type? " + type); + } + } + + + /** Create a field instruction. + * + * @param class_name name of the accessed class + * @param name name of the referenced field + * @param type type of field + * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC + * @see Constants + */ + public FieldInstruction createFieldAccess( String class_name, String name, Type type, short kind ) { + int index; + String signature = type.getSignature(); + index = cp.addFieldref(class_name, name, signature); + switch (kind) { + case Constants.GETFIELD: + return new GETFIELD(index); + case Constants.PUTFIELD: + return new PUTFIELD(index); + case Constants.GETSTATIC: + return new GETSTATIC(index); + case Constants.PUTSTATIC: + return new PUTSTATIC(index); + default: + throw new RuntimeException("Oops: Unknown getfield kind:" + kind); + } + } + + + /** Create reference to `this' + */ + public static Instruction createThis() { + return new ALOAD(0); + } + + + /** Create typed return + */ + public static ReturnInstruction createReturn( Type type ) { + switch (type.getType()) { + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return ARETURN; + case Constants.T_INT: + case Constants.T_SHORT: + case Constants.T_BOOLEAN: + case Constants.T_CHAR: + case Constants.T_BYTE: + return IRETURN; + case Constants.T_FLOAT: + return FRETURN; + case Constants.T_DOUBLE: + return DRETURN; + case Constants.T_LONG: + return LRETURN; + case Constants.T_VOID: + return RETURN; + default: + throw new RuntimeException("Invalid type: " + type); + } + } + + + private static final ArithmeticInstruction createBinaryIntOp( char first, String op ) { + switch (first) { + case '-': + return ISUB; + case '+': + return IADD; + case '%': + return IREM; + case '*': + return IMUL; + case '/': + return IDIV; + case '&': + return IAND; + case '|': + return IOR; + case '^': + return IXOR; + case '<': + return ISHL; + case '>': + return op.equals(">>>") + ? (ArithmeticInstruction) IUSHR + : (ArithmeticInstruction) ISHR; + default: + throw new RuntimeException("Invalid operand " + op); + } + } + + + private static final ArithmeticInstruction createBinaryLongOp( char first, String op ) { + switch (first) { + case '-': + return LSUB; + case '+': + return LADD; + case '%': + return LREM; + case '*': + return LMUL; + case '/': + return LDIV; + case '&': + return LAND; + case '|': + return LOR; + case '^': + return LXOR; + case '<': + return LSHL; + case '>': + return op.equals(">>>") + ? (ArithmeticInstruction) LUSHR + : (ArithmeticInstruction) LSHR; + default: + throw new RuntimeException("Invalid operand " + op); + } + } + + + private static final ArithmeticInstruction createBinaryFloatOp( char op ) { + switch (op) { + case '-': + return FSUB; + case '+': + return FADD; + case '*': + return FMUL; + case '/': + return FDIV; + case '%': + return FREM; + default: + throw new RuntimeException("Invalid operand " + op); + } + } + + + private static final ArithmeticInstruction createBinaryDoubleOp( char op ) { + switch (op) { + case '-': + return DSUB; + case '+': + return DADD; + case '*': + return DMUL; + case '/': + return DDIV; + case '%': + return DREM; + default: + throw new RuntimeException("Invalid operand " + op); + } + } + + + /** + * Create binary operation for simple basic types, such as int and float. + * + * @param op operation, such as "+", "*", "<<", etc. + */ + public static ArithmeticInstruction createBinaryOperation( String op, Type type ) { + char first = op.toCharArray()[0]; + switch (type.getType()) { + case Constants.T_BYTE: + case Constants.T_SHORT: + case Constants.T_INT: + case Constants.T_CHAR: + return createBinaryIntOp(first, op); + case Constants.T_LONG: + return createBinaryLongOp(first, op); + case Constants.T_FLOAT: + return createBinaryFloatOp(first); + case Constants.T_DOUBLE: + return createBinaryDoubleOp(first); + default: + throw new RuntimeException("Invalid type " + type); + } + } + + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static StackInstruction createPop( int size ) { + return (size == 2) ? (StackInstruction) POP2 : (StackInstruction) POP; + } + + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static StackInstruction createDup( int size ) { + return (size == 2) ? (StackInstruction) DUP2 : (StackInstruction) DUP; + } + + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static StackInstruction createDup_2( int size ) { + return (size == 2) ? (StackInstruction) DUP2_X2 : (StackInstruction) DUP_X2; + } + + + /** + * @param size size of operand, either 1 (int, e.g.) or 2 (double) + */ + public static StackInstruction createDup_1( int size ) { + return (size == 2) ? (StackInstruction) DUP2_X1 : (StackInstruction) DUP_X1; + } + + + /** + * @param index index of local variable + */ + public static LocalVariableInstruction createStore( Type type, int index ) { + switch (type.getType()) { + case Constants.T_BOOLEAN: + case Constants.T_CHAR: + case Constants.T_BYTE: + case Constants.T_SHORT: + case Constants.T_INT: + return new ISTORE(index); + case Constants.T_FLOAT: + return new FSTORE(index); + case Constants.T_DOUBLE: + return new DSTORE(index); + case Constants.T_LONG: + return new LSTORE(index); + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return new ASTORE(index); + default: + throw new RuntimeException("Invalid type " + type); + } + } + + + /** + * @param index index of local variable + */ + public static LocalVariableInstruction createLoad( Type type, int index ) { + switch (type.getType()) { + case Constants.T_BOOLEAN: + case Constants.T_CHAR: + case Constants.T_BYTE: + case Constants.T_SHORT: + case Constants.T_INT: + return new ILOAD(index); + case Constants.T_FLOAT: + return new FLOAD(index); + case Constants.T_DOUBLE: + return new DLOAD(index); + case Constants.T_LONG: + return new LLOAD(index); + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return new ALOAD(index); + default: + throw new RuntimeException("Invalid type " + type); + } + } + + + /** + * @param type type of elements of array, i.e., array.getElementType() + */ + public static ArrayInstruction createArrayLoad( Type type ) { + switch (type.getType()) { + case Constants.T_BOOLEAN: + case Constants.T_BYTE: + return BALOAD; + case Constants.T_CHAR: + return CALOAD; + case Constants.T_SHORT: + return SALOAD; + case Constants.T_INT: + return IALOAD; + case Constants.T_FLOAT: + return FALOAD; + case Constants.T_DOUBLE: + return DALOAD; + case Constants.T_LONG: + return LALOAD; + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return AALOAD; + default: + throw new RuntimeException("Invalid type " + type); + } + } + + + /** + * @param type type of elements of array, i.e., array.getElementType() + */ + public static ArrayInstruction createArrayStore( Type type ) { + switch (type.getType()) { + case Constants.T_BOOLEAN: + case Constants.T_BYTE: + return BASTORE; + case Constants.T_CHAR: + return CASTORE; + case Constants.T_SHORT: + return SASTORE; + case Constants.T_INT: + return IASTORE; + case Constants.T_FLOAT: + return FASTORE; + case Constants.T_DOUBLE: + return DASTORE; + case Constants.T_LONG: + return LASTORE; + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return AASTORE; + default: + throw new RuntimeException("Invalid type " + type); + } + } + + + /** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g., + * if the operands are basic types and CHECKCAST if they are reference types. + */ + public Instruction createCast( Type src_type, Type dest_type ) { + if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) { + byte dest = dest_type.getType(); + byte src = src_type.getType(); + if (dest == Constants.T_LONG + && (src == Constants.T_CHAR || src == Constants.T_BYTE || src == Constants.T_SHORT)) { + src = Constants.T_INT; + } + String name = "org.apache.tomcat.util.bcel.generic." + short_names[src - Constants.T_CHAR] + "2" + + short_names[dest - Constants.T_CHAR]; + Instruction i = null; + try { + i = (Instruction) java.lang.Class.forName(name).newInstance(); + } catch (Exception e) { + throw new RuntimeException("Could not find instruction: " + name, e); + } + return i; + } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) { + if (dest_type instanceof ArrayType) { + return new CHECKCAST(cp.addArrayClass((ArrayType) dest_type)); + } else { + return new CHECKCAST(cp.addClass(((ObjectType) dest_type).getClassName())); + } + } else { + throw new RuntimeException("Can not cast " + src_type + " to " + dest_type); + } + } + + + public GETFIELD createGetField( String class_name, String name, Type t ) { + return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature())); + } + + + public GETSTATIC createGetStatic( String class_name, String name, Type t ) { + return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature())); + } + + + public PUTFIELD createPutField( String class_name, String name, Type t ) { + return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature())); + } + + + public PUTSTATIC createPutStatic( String class_name, String name, Type t ) { + return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature())); + } + + + public CHECKCAST createCheckCast( ReferenceType t ) { + if (t instanceof ArrayType) { + return new CHECKCAST(cp.addArrayClass((ArrayType) t)); + } else { + return new CHECKCAST(cp.addClass((ObjectType) t)); + } + } + + + public INSTANCEOF createInstanceOf( ReferenceType t ) { + if (t instanceof ArrayType) { + return new INSTANCEOF(cp.addArrayClass((ArrayType) t)); + } else { + return new INSTANCEOF(cp.addClass((ObjectType) t)); + } + } + + + public NEW createNew( ObjectType t ) { + return new NEW(cp.addClass(t)); + } + + + public NEW createNew( String s ) { + return createNew(new ObjectType(s)); + } + + + /** Create new array of given size and type. + * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction + */ + public Instruction createNewArray( Type t, short dim ) { + if (dim == 1) { + if (t instanceof ObjectType) { + return new ANEWARRAY(cp.addClass((ObjectType) t)); + } else if (t instanceof ArrayType) { + return new ANEWARRAY(cp.addArrayClass((ArrayType) t)); + } else { + return new NEWARRAY(((BasicType) t).getType()); + } + } else { + ArrayType at; + if (t instanceof ArrayType) { + at = (ArrayType) t; + } else { + at = new ArrayType(t, dim); + } + return new MULTIANEWARRAY(cp.addArrayClass(at), dim); + } + } + + + /** Create "null" value for reference types, 0 for basic types like int + */ + public static Instruction createNull( Type type ) { + switch (type.getType()) { + case Constants.T_ARRAY: + case Constants.T_OBJECT: + return ACONST_NULL; + case Constants.T_INT: + case Constants.T_SHORT: + case Constants.T_BOOLEAN: + case Constants.T_CHAR: + case Constants.T_BYTE: + return ICONST_0; + case Constants.T_FLOAT: + return FCONST_0; + case Constants.T_DOUBLE: + return DCONST_0; + case Constants.T_LONG: + return LCONST_0; + case Constants.T_VOID: + return NOP; + default: + throw new RuntimeException("Invalid type: " + type); + } + } + + + /** Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH. + * For those you should use the SWITCH compound instruction. + */ + public static BranchInstruction createBranchInstruction( short opcode, InstructionHandle target ) { + switch (opcode) { + case Constants.IFEQ: + return new IFEQ(target); + case Constants.IFNE: + return new IFNE(target); + case Constants.IFLT: + return new IFLT(target); + case Constants.IFGE: + return new IFGE(target); + case Constants.IFGT: + return new IFGT(target); + case Constants.IFLE: + return new IFLE(target); + case Constants.IF_ICMPEQ: + return new IF_ICMPEQ(target); + case Constants.IF_ICMPNE: + return new IF_ICMPNE(target); + case Constants.IF_ICMPLT: + return new IF_ICMPLT(target); + case Constants.IF_ICMPGE: + return new IF_ICMPGE(target); + case Constants.IF_ICMPGT: + return new IF_ICMPGT(target); + case Constants.IF_ICMPLE: + return new IF_ICMPLE(target); + case Constants.IF_ACMPEQ: + return new IF_ACMPEQ(target); + case Constants.IF_ACMPNE: + return new IF_ACMPNE(target); + case Constants.GOTO: + return new GOTO(target); + case Constants.JSR: + return new JSR(target); + case Constants.IFNULL: + return new IFNULL(target); + case Constants.IFNONNULL: + return new IFNONNULL(target); + case Constants.GOTO_W: + return new GOTO_W(target); + case Constants.JSR_W: + return new JSR_W(target); + default: + throw new RuntimeException("Invalid opcode: " + opcode); + } + } + + + public void setClassGen( ClassGen c ) { + cg = c; + } + + + public ClassGen getClassGen() { + return cg; + } + + + public void setConstantPool( ConstantPoolGen c ) { + cp = c; + } + + + public ConstantPoolGen getConstantPool() { + return cp; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionHandle.java b/java/org/apache/tomcat/util/bcel/generic/InstructionHandle.java new file mode 100644 index 000000000..e9423e1e6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionHandle.java @@ -0,0 +1,290 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Instances of this class give users a handle to the instructions contained in + * an InstructionList. Instruction objects may be used more than once within a + * list, this is useful because it saves memory and may be much faster. + * + * Within an InstructionList an InstructionHandle object is wrapped + * around all instructions, i.e., it implements a cell in a + * doubly-linked list. From the outside only the next and the + * previous instruction (handle) are accessible. One + * can traverse the list via an Enumeration returned by + * InstructionList.elements(). + * + * @version $Id$ + * @author M. Dahm + * @see Instruction + * @see BranchHandle + * @see InstructionList + */ +public class InstructionHandle implements java.io.Serializable { + + InstructionHandle next, prev; // Will be set from the outside + Instruction instruction; + protected int i_position = -1; // byte code offset of instruction + private Set targeters; + private Map attributes; + + + public final InstructionHandle getNext() { + return next; + } + + + public final InstructionHandle getPrev() { + return prev; + } + + + public final Instruction getInstruction() { + return instruction; + } + + + /** + * Replace current instruction contained in this handle. + * Old instruction is disposed using Instruction.dispose(). + */ + public void setInstruction( Instruction i ) { // Overridden in BranchHandle + if (i == null) { + throw new ClassGenException("Assigning null to handle"); + } + if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) { + throw new ClassGenException("Assigning branch instruction " + i + " to plain handle"); + } + if (instruction != null) { + instruction.dispose(); + } + instruction = i; + } + + + /** + * Temporarily swap the current instruction, without disturbing + * anything. Meant to be used by a debugger, implementing + * breakpoints. Current instruction is returned. + */ + public Instruction swapInstruction( Instruction i ) { + Instruction oldInstruction = instruction; + instruction = i; + return oldInstruction; + } + + + /*private*/protected InstructionHandle(Instruction i) { + setInstruction(i); + } + + private static InstructionHandle ih_list = null; // List of reusable handles + + + /** Factory method. + */ + static final InstructionHandle getInstructionHandle( Instruction i ) { + if (ih_list == null) { + return new InstructionHandle(i); + } else { + InstructionHandle ih = ih_list; + ih_list = ih.next; + ih.setInstruction(i); + return ih; + } + } + + + /** + * Called by InstructionList.setPositions when setting the position for every + * instruction. In the presence of variable length instructions `setPositions()' + * performs multiple passes over the instruction list to calculate the + * correct (byte) positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param max_offset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + protected int updatePosition( int offset, int max_offset ) { + i_position += offset; + return 0; + } + + + /** @return the position, i.e., the byte code offset of the contained + * instruction. This is accurate only after + * InstructionList.setPositions() has been called. + */ + public int getPosition() { + return i_position; + } + + + /** Set the position, i.e., the byte code offset of the contained + * instruction. + */ + void setPosition( int pos ) { + i_position = pos; + } + + + /** Overridden in BranchHandle + */ + protected void addHandle() { + next = ih_list; + ih_list = this; + } + + + /** + * Delete contents, i.e., remove user access and make handle reusable. + */ + void dispose() { + next = prev = null; + instruction.dispose(); + instruction = null; + i_position = -1; + attributes = null; + removeAllTargeters(); + addHandle(); + } + + + /** Remove all targeters, if any. + */ + public void removeAllTargeters() { + if (targeters != null) { + targeters.clear(); + } + } + + + /** + * Denote this handle isn't referenced anymore by t. + */ + public void removeTargeter( InstructionTargeter t ) { + if (targeters != null) { + targeters.remove(t); + } + } + + + /** + * Denote this handle is being referenced by t. + */ + public void addTargeter( InstructionTargeter t ) { + if (targeters == null) { + targeters = new HashSet(); + } + //if(!targeters.contains(t)) + targeters.add(t); + } + + + public boolean hasTargeters() { + return (targeters != null) && (targeters.size() > 0); + } + + + /** + * @return null, if there are no targeters + */ + public InstructionTargeter[] getTargeters() { + if (!hasTargeters()) { + return new InstructionTargeter[0]; + } + InstructionTargeter[] t = new InstructionTargeter[targeters.size()]; + targeters.toArray(t); + return t; + } + + + /** @return a (verbose) string representation of the contained instruction. + */ + public String toString( boolean verbose ) { + return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose); + } + + + /** @return a string representation of the contained instruction. + */ + public String toString() { + return toString(true); + } + + + /** Add an attribute to an instruction handle. + * + * @param key the key object to store/retrieve the attribute + * @param attr the attribute to associate with this handle + */ + public void addAttribute( Object key, Object attr ) { + if (attributes == null) { + attributes = new HashMap(3); + } + attributes.put(key, attr); + } + + + /** Delete an attribute of an instruction handle. + * + * @param key the key object to retrieve the attribute + */ + public void removeAttribute( Object key ) { + if (attributes != null) { + attributes.remove(key); + } + } + + + /** Get attribute of an instruction handle. + * + * @param key the key object to store/retrieve the attribute + */ + public Object getAttribute( Object key ) { + if (attributes != null) { + return attributes.get(key); + } + return null; + } + + + /** @return all attributes associated with this handle + */ + public Collection getAttributes() { + if (attributes == null) { + attributes = new HashMap(3); + } + return attributes.values(); + } + + + /** Convenience method, simply calls accept() on the contained instruction. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + instruction.accept(v); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionList.java b/java/org/apache/tomcat/util/bcel/generic/InstructionList.java new file mode 100644 index 000000000..dff58d052 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionList.java @@ -0,0 +1,1277 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * This class is a container for a list of Instruction objects. Instructions can + * be appended, inserted, moved, deleted, etc.. Instructions are being + * wrapped into InstructionHandles 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 getByteCode. + * + * @version $Id$ + * @author M. Dahm + * @see Instruction + * @see InstructionHandle + * @see BranchHandle + */ +public class InstructionList implements Serializable { + + private InstructionHandle start = null, end = null; + private int length = 0; // number of elements in list + private int[] byte_positions; // byte code offsets corresponding to instructions + + + /** + * Create (empty) instruction list. + */ + public InstructionList() { + } + + + /** + * Create instruction list containing one instruction. + * @param i initial instruction + */ + public InstructionList(Instruction i) { + append(i); + } + + + /** + * Create instruction list containing one instruction. + * @param i initial instruction + */ + public InstructionList(BranchInstruction i) { + append(i); + } + + + /** + * Initialize list with (nonnull) compound instruction. Consumes argument + * list, i.e., it becomes empty. + * + * @param c compound instruction (list) + */ + public InstructionList(CompoundInstruction c) { + append(c.getInstructionList()); + } + + + /** + * Test for empty list. + */ + public boolean isEmpty() { + return start == null; + } // && end == null + + + /** + * Find the target instruction (handle) that corresponds to the given target + * position (byte code offset). + * + * @param ihs array of instruction handles, i.e. il.getInstructionHandles() + * @param pos array of positions corresponding to ihs, i.e. il.getInstructionPositions() + * @param count length of arrays + * @param target target position to search for + * @return target position's instruction handle if available + */ + public static InstructionHandle findHandle( InstructionHandle[] ihs, int[] pos, int count, + int target ) { + int l = 0, r = count - 1; + /* Do a binary search since the pos array is orderd. + */ + do { + int i = (l + r) / 2; + int j = pos[i]; + if (j == target) { + return ihs[i]; + } else if (target < j) { + r = i - 1; + } else { + l = i + 1; + } + } while (l <= r); + return null; + } + + + /** + * Get instruction handle for instruction at byte code position pos. + * This only works properly, if the list is freshly initialized from a byte array or + * setPositions() has been called before this method. + * + * @param pos byte code position to search for + * @return target position's instruction handle if available + */ + public InstructionHandle findHandle( int pos ) { + int[] positions = byte_positions; + InstructionHandle ih = start; + for (int i = 0; i < length; i++) { + if(positions[i] == pos) { + return ih; + } + ih = ih.next; + } + return null; + } + + + /** + * Initialize instruction list from byte array. + * + * @param code byte array containing the instructions + */ + public InstructionList(byte[] code) { + ByteSequence bytes = new ByteSequence(code); + InstructionHandle[] ihs = new InstructionHandle[code.length]; + int[] pos = new int[code.length]; // Can't be more than that + int count = 0; // Contains actual length + /* Pass 1: Create an object for each byte code and append them + * to the list. + */ + try { + while (bytes.available() > 0) { + // Remember byte offset and associate it with the instruction + int off = bytes.getIndex(); + pos[count] = off; + /* Read one instruction from the byte stream, the byte position is set + * accordingly. + */ + Instruction i = Instruction.readInstruction(bytes); + InstructionHandle ih; + if (i instanceof BranchInstruction) { + ih = append((BranchInstruction) i); + } else { + ih = append(i); + } + ih.setPosition(off); + ihs[count] = ih; + count++; + } + } catch (IOException e) { + throw new ClassGenException(e.toString(), e); + } + byte_positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, byte_positions, 0, count); + /* Pass 2: Look for BranchInstruction and update their targets, i.e., + * convert offsets to instruction handles. + */ + for (int i = 0; i < count; i++) { + if (ihs[i] instanceof BranchHandle) { + BranchInstruction bi = (BranchInstruction) ihs[i].instruction; + int target = bi.position + bi.getIndex(); /* Byte code position: + * relative -> absolute. */ + // Search for target position + InstructionHandle ih = findHandle(ihs, pos, count, target); + if (ih == null) { + throw new ClassGenException("Couldn't find target for branch: " + bi); + } + bi.setTarget(ih); // Update target + // If it is a Select instruction, update all branch targets + if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH + Select s = (Select) bi; + int[] indices = s.getIndices(); + for (int j = 0; j < indices.length; j++) { + target = bi.position + indices[j]; + ih = findHandle(ihs, pos, count, target); + if (ih == null) { + throw new ClassGenException("Couldn't find target for switch: " + bi); + } + s.setTarget(j, ih); // Update target + } + } + } + } + } + + + /** + * Append another list after instruction (handle) ih contained in this list. + * Consumes argument list, i.e., it becomes empty. + * + * @param ih where to append the instruction list + * @param il Instruction list to append to this one + * @return instruction handle pointing to the first appended instruction + */ + public InstructionHandle append( InstructionHandle ih, InstructionList il ) { + if (il == null) { + throw new ClassGenException("Appending null InstructionList"); + } + if (il.isEmpty()) { + return ih; + } + InstructionHandle next = ih.next, ret = il.start; + ih.next = il.start; + il.start.prev = ih; + il.end.next = next; + if (next != null) { + next.prev = il.end; + } else { + end = il.end; // Update end ... + } + length += il.length; // Update length + il.clear(); + return ret; + } + + + /** + * Append another list after instruction i contained in this list. + * Consumes argument list, i.e., it becomes empty. + * + * @param i where to append the instruction list + * @param il Instruction list to append to this one + * @return instruction handle pointing to the first 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 first appended instruction + */ + public InstructionHandle append( InstructionList il ) { + if (il == null) { + throw new ClassGenException("Appending null InstructionList"); + } + if (il.isEmpty()) { + return null; + } + if (isEmpty()) { + start = il.start; + end = il.end; + length = il.length; + il.clear(); + return start; + } else { + return append(end, il); // was end.instruction + } + } + + + /** + * Append an instruction to the end of this list. + * + * @param ih instruction to append + */ + private void append( InstructionHandle ih ) { + if (isEmpty()) { + start = end = ih; + ih.next = ih.prev = null; + } else { + end.next = ih; + ih.prev = end; + ih.next = null; + end = ih; + } + length++; // Update length + } + + + /** + * Append an instruction to the end of this list. + * + * @param i instruction to append + * @return instruction handle of the appended instruction + */ + public InstructionHandle append( Instruction i ) { + InstructionHandle ih = InstructionHandle.getInstructionHandle(i); + append(ih); + return ih; + } + + + /** + * Append a branch instruction to the end of this list. + * + * @param i branch instruction to append + * @return branch instruction handle of the appended instruction + */ + public BranchHandle append( BranchInstruction i ) { + BranchHandle ih = BranchHandle.getBranchHandle(i); + append(ih); + return ih; + } + + + /** + * Append a single instruction j after another instruction i, which + * must be in this list of course! + * + * @param i Instruction in list + * @param j Instruction to append after i in list + * @return instruction handle of the first appended instruction + */ + public InstructionHandle append( Instruction i, Instruction j ) { + return append(i, new InstructionList(j)); + } + + + /** + * Append a compound instruction, after instruction i. + * + * @param i Instruction in list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first appended instruction + */ + public InstructionHandle append( Instruction i, CompoundInstruction c ) { + return append(i, c.getInstructionList()); + } + + + /** + * Append a compound instruction. + * + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first appended instruction + */ + public InstructionHandle append( CompoundInstruction c ) { + return append(c.getInstructionList()); + } + + + /** + * Append a compound instruction. + * + * @param ih where to append the instruction list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first appended instruction + */ + public InstructionHandle append( InstructionHandle ih, CompoundInstruction c ) { + return append(ih, c.getInstructionList()); + } + + + /** + * Append an instruction after instruction (handle) ih contained in this list. + * + * @param ih where to append the instruction list + * @param i Instruction to append + * @return instruction handle pointing to the first 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 first appended instruction + */ + public BranchHandle append( InstructionHandle ih, BranchInstruction i ) { + BranchHandle bh = BranchHandle.getBranchHandle(i); + InstructionList il = new InstructionList(); + il.append(bh); + append(ih, il); + return bh; + } + + + /** + * Insert another list before Instruction handle ih contained in this list. + * Consumes argument list, i.e., it becomes empty. + * + * @param ih where to append the instruction list + * @param il Instruction list to insert + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( InstructionHandle ih, InstructionList il ) { + if (il == null) { + throw new ClassGenException("Inserting null InstructionList"); + } + if (il.isEmpty()) { + return ih; + } + InstructionHandle prev = ih.prev, ret = il.start; + ih.prev = il.end; + il.end.next = ih; + il.start.prev = prev; + if (prev != null) { + prev.next = il.start; + } else { + start = il.start; // Update start ... + } + length += il.length; // Update length + il.clear(); + return ret; + } + + + /** + * Insert another list. + * + * @param il list to insert before start of this list + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( InstructionList il ) { + if (isEmpty()) { + append(il); // Code is identical for this case + return start; + } else { + return insert(start, il); + } + } + + + /** + * Insert an instruction at start of this list. + * + * @param ih instruction to insert + */ + private void insert( InstructionHandle ih ) { + if (isEmpty()) { + start = end = ih; + ih.next = ih.prev = null; + } else { + start.prev = ih; + ih.next = start; + ih.prev = null; + start = ih; + } + length++; + } + + + /** + * Insert another list before Instruction i contained in this list. + * Consumes argument list, i.e., it becomes empty. + * + * @param i where to append the instruction list + * @param il Instruction list to insert + * @return instruction handle pointing to the first inserted instruction, + * i.e., il.getStart() + */ + public InstructionHandle insert( Instruction i, InstructionList il ) { + InstructionHandle ih; + if ((ih = findInstruction1(i)) == null) { + throw new ClassGenException("Instruction " + i + " is not contained in this list."); + } + return insert(ih, il); + } + + + /** + * Insert an instruction at start of this list. + * + * @param i instruction to insert + * @return instruction handle of the inserted instruction + */ + public InstructionHandle insert( Instruction i ) { + InstructionHandle ih = InstructionHandle.getInstructionHandle(i); + insert(ih); + return ih; + } + + + /** + * Insert a branch instruction at start of this list. + * + * @param i branch instruction to insert + * @return branch instruction handle of the appended instruction + */ + public BranchHandle insert( BranchInstruction i ) { + BranchHandle ih = BranchHandle.getBranchHandle(i); + insert(ih); + return ih; + } + + + /** + * Insert a single instruction j before another instruction i, which + * must be in this list of course! + * + * @param i Instruction in list + * @param j Instruction to insert before i in list + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( Instruction i, Instruction j ) { + return insert(i, new InstructionList(j)); + } + + + /** + * Insert a compound instruction before instruction i. + * + * @param i Instruction in list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( Instruction i, CompoundInstruction c ) { + return insert(i, c.getInstructionList()); + } + + + /** + * Insert a compound instruction. + * + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( CompoundInstruction c ) { + return insert(c.getInstructionList()); + } + + + /** + * Insert an instruction before instruction (handle) ih contained in this list. + * + * @param ih where to insert to the instruction list + * @param i Instruction to insert + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( InstructionHandle ih, Instruction i ) { + return insert(ih, new InstructionList(i)); + } + + + /** + * Insert a compound instruction. + * + * @param ih where to insert the instruction list + * @param c The composite instruction (containing an InstructionList) + * @return instruction handle of the first inserted instruction + */ + public InstructionHandle insert( InstructionHandle ih, CompoundInstruction c ) { + return insert(ih, c.getInstructionList()); + } + + + /** + * Insert an instruction before instruction (handle) ih contained in this list. + * + * @param ih where to insert to the instruction list + * @param i Instruction to insert + * @return instruction handle of the first inserted instruction + */ + public BranchHandle insert( InstructionHandle ih, BranchInstruction i ) { + BranchHandle bh = BranchHandle.getBranchHandle(i); + InstructionList il = new InstructionList(); + il.append(bh); + insert(ih, il); + return bh; + } + + + /** + * Take all instructions (handles) from "start" to "end" and append them after the + * new location "target". Of course, "end" must be after "start" and target must + * not be located withing this range. If you want to move something to the start of + * the list use null as value for target.
      + * Any instruction targeters pointing to handles within the block, keep their targets. + * + * @param start of moved block + * @param end of moved block + * @param target of moved block + */ + public void move( InstructionHandle start, InstructionHandle end, InstructionHandle target ) { + // Step 1: Check constraints + if ((start == null) || (end == null)) { + throw new ClassGenException("Invalid null handle: From " + start + " to " + end); + } + if ((target == start) || (target == end)) { + throw new ClassGenException("Invalid range: From " + start + " to " + end + + " contains target " + target); + } + for (InstructionHandle ih = start; ih != end.next; ih = ih.next) { + if (ih == null) { + throw new ClassGenException("Invalid range: From " + start + " to " + end); + } else if (ih == target) { + throw new ClassGenException("Invalid range: From " + start + " to " + end + + " contains target " + target); + } + } + // Step 2: Temporarily remove the given instructions from the list + InstructionHandle prev = start.prev, next = end.next; + if (prev != null) { + prev.next = next; + } else { + this.start = next; + } + if (next != null) { + next.prev = prev; + } else { + this.end = prev; + } + start.prev = end.next = null; + // Step 3: append after target + if (target == null) { // append to start of list + if (this.start != null) { + this.start.prev = end; + } + end.next = this.start; + this.start = start; + } else { + next = target.next; + target.next = start; + start.prev = target; + end.next = next; + if (next != null) { + next.prev = end; + } else { + this.end = end; + } + } + } + + + /** + * Move a single instruction (handle) to a new location. + * + * @param ih moved instruction + * @param target new location of moved instruction + */ + public void move( InstructionHandle ih, InstructionHandle target ) { + move(ih, ih, target); + } + + + /** + * Remove from instruction `prev' to instruction `next' both contained + * in this list. Throws TargetLostException when one of the removed instruction handles + * is still being targeted. + * + * @param prev where to start deleting (predecessor, exclusive) + * @param next where to end deleting (successor, exclusive) + */ + private void remove( InstructionHandle prev, InstructionHandle next ) + throws TargetLostException { + InstructionHandle first, last; // First and last deleted instruction + if ((prev == null) && (next == null)) { + first = start; + last = end; + start = end = null; + } else { + if (prev == null) { // At start of list + first = start; + start = next; + } else { + first = prev.next; + prev.next = next; + } + if (next == null) { // At end of list + last = end; + end = prev; + } else { + last = next.prev; + next.prev = prev; + } + } + first.prev = null; // Completely separated from rest of list + last.next = null; + List target_vec = new ArrayList(); + for (InstructionHandle ih = first; ih != null; ih = ih.next) { + ih.getInstruction().dispose(); // e.g. BranchInstructions release their targets + } + StringBuffer buf = new StringBuffer("{ "); + for (InstructionHandle ih = first; ih != null; ih = next) { + next = ih.next; + length--; + if (ih.hasTargeters()) { // Still got targeters? + target_vec.add(ih); + buf.append(ih.toString(true) + " "); + ih.next = ih.prev = null; + } else { + ih.dispose(); + } + } + buf.append("}"); + if (!target_vec.isEmpty()) { + InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; + target_vec.toArray(targeted); + throw new TargetLostException(targeted, buf.toString()); + } + } + + + /** + * Remove instruction from this list. The corresponding Instruction + * handles must not be reused! + * + * @param ih instruction (handle) to remove + */ + public void delete( InstructionHandle ih ) throws TargetLostException { + remove(ih.prev, ih.next); + } + + + /** + * Remove instruction from this list. The corresponding Instruction + * handles must not be reused! + * + * @param i instruction to remove + */ + public void delete( Instruction i ) throws TargetLostException { + InstructionHandle ih; + if ((ih = findInstruction1(i)) == null) { + throw new ClassGenException("Instruction " + i + " is not contained in this list."); + } + delete(ih); + } + + + /** + * Remove instructions from instruction `from' to instruction `to' contained + * in this list. The user must ensure that `from' is an instruction before + * `to', or risk havoc. The corresponding Instruction handles must not be reused! + * + * @param from where to start deleting (inclusive) + * @param to where to end deleting (inclusive) + */ + public void delete( InstructionHandle from, InstructionHandle to ) throws TargetLostException { + remove(from.prev, to.next); + } + + + /** + * Remove instructions from instruction `from' to instruction `to' contained + * in this list. The user must ensure that `from' is an instruction before + * `to', or risk havoc. The corresponding Instruction handles must not be reused! + * + * @param from where to start deleting (inclusive) + * @param to where to end deleting (inclusive) + */ + public void delete( Instruction from, Instruction to ) throws TargetLostException { + InstructionHandle from_ih, to_ih; + if ((from_ih = findInstruction1(from)) == null) { + throw new ClassGenException("Instruction " + from + " is not contained in this list."); + } + if ((to_ih = findInstruction2(to)) == null) { + throw new ClassGenException("Instruction " + to + " is not contained in this list."); + } + delete(from_ih, to_ih); + } + + + /** + * Search for given Instruction reference, start at beginning of list. + * + * @param i instruction to search for + * @return instruction found on success, null otherwise + */ + private InstructionHandle findInstruction1( Instruction i ) { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + if (ih.instruction == i) { + return ih; + } + } + return null; + } + + + /** + * Search for given Instruction reference, start at end of list + * + * @param i instruction to search for + * @return instruction found on success, null otherwise + */ + private InstructionHandle findInstruction2( Instruction i ) { + for (InstructionHandle ih = end; ih != null; ih = ih.prev) { + if (ih.instruction == i) { + return ih; + } + } + return null; + } + + + public boolean contains( InstructionHandle i ) { + if (i == null) { + return false; + } + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + if (ih == i) { + return true; + } + } + return false; + } + + + public boolean contains( Instruction i ) { + return findInstruction1(i) != null; + } + + + public void setPositions() { + setPositions(false); + } + + + /** + * Give all instructions their position number (offset in byte stream), i.e., + * make the list ready to be dumped. + * + * @param check Perform sanity checks, e.g. if all targeted instructions really belong + * to this list + */ + public void setPositions( boolean check ) { + int max_additional_bytes = 0, additional_bytes = 0; + int index = 0, count = 0; + int[] pos = new int[length]; + /* Pass 0: Sanity checks + */ + if (check) { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + if (i instanceof BranchInstruction) { // target instruction within list? + Instruction inst = ((BranchInstruction) i).getTarget().instruction; + if (!contains(inst)) { + throw new ClassGenException("Branch target of " + + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not in instruction list"); + } + if (i instanceof Select) { + InstructionHandle[] targets = ((Select) i).getTargets(); + for (int j = 0; j < targets.length; j++) { + inst = targets[j].instruction; + if (!contains(inst)) { + throw new ClassGenException("Branch target of " + + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not in instruction list"); + } + } + } + if (!(ih instanceof BranchHandle)) { + throw new ClassGenException("Branch instruction " + + Constants.OPCODE_NAMES[i.opcode] + ":" + inst + + " not contained in BranchHandle."); + } + } + } + } + /* Pass 1: Set position numbers and sum up the maximum number of bytes an + * instruction may be shifted. + */ + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + ih.setPosition(index); + pos[count++] = index; + /* Get an estimate about how many additional bytes may be added, because + * BranchInstructions may have variable length depending on the target + * offset (short vs. int) or alignment issues (TABLESWITCH and + * LOOKUPSWITCH). + */ + switch (i.getOpcode()) { + case Constants.JSR: + case Constants.GOTO: + max_additional_bytes += 2; + break; + case Constants.TABLESWITCH: + case Constants.LOOKUPSWITCH: + max_additional_bytes += 3; + break; + } + index += i.getLength(); + } + /* Pass 2: Expand the variable-length (Branch)Instructions depending on + * the target offset (short or int) and ensure that branch targets are + * within this list. + */ + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes); + } + /* Pass 3: Update position numbers (which may have changed due to the + * preceding expansions), like pass 1. + */ + index = count = 0; + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + ih.setPosition(index); + pos[count++] = index; + index += i.getLength(); + } + byte_positions = new int[count]; // Trim to proper size + System.arraycopy(pos, 0, byte_positions, 0, count); + } + + + /** + * When everything is finished, use this method to convert the instruction + * list into an array of bytes. + * + * @return the byte code ready to be dumped + */ + public byte[] getByteCode() { + // Update position indices of instructions + setPositions(); + ByteArrayOutputStream b = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(b); + try { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + i.dump(out); // Traverse list + } + } catch (IOException e) { + System.err.println(e); + return new byte[0]; + } + return b.toByteArray(); + } + + + /** + * @return an array of instructions without target information for branch instructions. + */ + public Instruction[] getInstructions() { + ByteSequence bytes = new ByteSequence(getByteCode()); + List instructions = new ArrayList(); + try { + while (bytes.available() > 0) { + instructions.add(Instruction.readInstruction(bytes)); + } + } catch (IOException e) { + throw new ClassGenException(e.toString(), e); + } + return (Instruction[]) instructions.toArray(new Instruction[instructions.size()]); + } + + + public String toString() { + return toString(true); + } + + + /** + * @param verbose toggle output format + * @return String containing all instructions in this list. + */ + public String toString( boolean verbose ) { + StringBuffer buf = new StringBuffer(); + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + buf.append(ih.toString(verbose)).append("\n"); + } + return buf.toString(); + } + + + /** + * @return Enumeration that lists all instructions (handles) + */ + public Iterator iterator() { + return new Iterator() { + + private InstructionHandle ih = start; + + + public Object next() throws NoSuchElementException { + if (ih == null) + throw new NoSuchElementException(); + InstructionHandle i = ih; + ih = ih.next; + return i; + } + + + public void remove() { + throw new UnsupportedOperationException(); + } + + + public boolean hasNext() { + return ih != null; + } + }; + } + + + /** + * @return array containing all instructions (handles) + */ + public InstructionHandle[] getInstructionHandles() { + InstructionHandle[] ihs = new InstructionHandle[length]; + InstructionHandle ih = start; + for (int i = 0; i < length; i++) { + ihs[i] = ih; + ih = ih.next; + } + return ihs; + } + + + /** + * Get positions (offsets) of all instructions in the list. This relies on that + * the list has been freshly created from an byte code array, or that setPositions() + * has been called. Otherwise this may be inaccurate. + * + * @return array containing all instruction's offset in byte code + */ + public int[] getInstructionPositions() { + return byte_positions; + } + + + /** + * @return complete, i.e., deep copy of this list + */ + public InstructionList copy() { + Map map = new HashMap(); + InstructionList il = new InstructionList(); + /* Pass 1: Make copies of all instructions, append them to the new list + * and associate old instruction references with the new ones, i.e., + * a 1:1 mapping. + */ + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + Instruction c = i.copy(); // Use clone for shallow copy + if (c instanceof BranchInstruction) { + map.put(ih, il.append((BranchInstruction) c)); + } else { + map.put(ih, il.append(c)); + } + } + /* Pass 2: Update branch targets. + */ + InstructionHandle ih = start; + InstructionHandle ch = il.start; + while (ih != null) { + Instruction i = ih.instruction; + Instruction c = ch.instruction; + if (i instanceof BranchInstruction) { + BranchInstruction bi = (BranchInstruction) i; + BranchInstruction bc = (BranchInstruction) c; + InstructionHandle itarget = bi.getTarget(); // old target + // New target is in hash map + bc.setTarget((InstructionHandle) map.get(itarget)); + if (bi instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH + InstructionHandle[] itargets = ((Select) bi).getTargets(); + InstructionHandle[] ctargets = ((Select) bc).getTargets(); + for (int j = 0; j < itargets.length; j++) { // Update all targets + ctargets[j] = (InstructionHandle) map.get(itargets[j]); + } + } + } + ih = ih.next; + ch = ch.next; + } + return il; + } + + + /** Replace all references to the old constant pool with references to the new + * constant pool + */ + public void replaceConstantPool( ConstantPoolGen old_cp, ConstantPoolGen new_cp ) { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.instruction; + if (i instanceof CPInstruction) { + CPInstruction ci = (CPInstruction) i; + Constant c = old_cp.getConstant(ci.getIndex()); + ci.setIndex(new_cp.addConstant(c, old_cp)); + } + } + } + + + private void clear() { + start = end = null; + length = 0; + } + + + /** + * Delete contents of list. Provides besser memory utilization, + * because the system then may reuse the instruction handles. This + * method is typically called right after + * MethodGen.getMethod(). + */ + public void dispose() { + // Traverse in reverse order, because ih.next is overwritten + for (InstructionHandle ih = end; ih != null; ih = ih.prev) { + /* Causes BranchInstructions to release target and targeters, because it + * calls dispose() on the contained instruction. + */ + ih.dispose(); + } + clear(); + } + + + /** + * @return start of list + */ + public InstructionHandle getStart() { + return start; + } + + + /** + * @return end of list + */ + public InstructionHandle getEnd() { + return end; + } + + + /** + * @return length of list (Number of instructions, not bytes) + */ + public int getLength() { + return length; + } + + + /** + * @return length of list (Number of instructions, not bytes) + */ + public int size() { + return length; + } + + + /** + * Redirect all references from old_target to new_target, i.e., update targets + * of branch instructions. + * + * @param old_target the old target instruction handle + * @param new_target the new target instruction handle + */ + public void redirectBranches( InstructionHandle old_target, InstructionHandle new_target ) { + for (InstructionHandle ih = start; ih != null; ih = ih.next) { + Instruction i = ih.getInstruction(); + if (i instanceof BranchInstruction) { + BranchInstruction b = (BranchInstruction) i; + InstructionHandle target = b.getTarget(); + if (target == old_target) { + b.setTarget(new_target); + } + if (b instanceof Select) { // Either LOOKUPSWITCH or TABLESWITCH + InstructionHandle[] targets = ((Select) b).getTargets(); + for (int j = 0; j < targets.length; j++) { + if (targets[j] == old_target) { + ((Select) b).setTarget(j, new_target); + } + } + } + } + } + } + + + /** + * Redirect all references of local variables from old_target to new_target. + * + * @param lg array of local variables + * @param old_target the old target instruction handle + * @param new_target the new target instruction handle + * @see MethodGen + */ + public void redirectLocalVariables( LocalVariableGen[] lg, InstructionHandle old_target, + InstructionHandle new_target ) { + for (int i = 0; i < lg.length; i++) { + InstructionHandle start = lg[i].getStart(); + InstructionHandle end = lg[i].getEnd(); + if (start == old_target) { + lg[i].setStart(new_target); + } + if (end == old_target) { + lg[i].setEnd(new_target); + } + } + } + + + /** + * Redirect all references of exception handlers from old_target to new_target. + * + * @param exceptions array of exception handlers + * @param old_target the old target instruction handle + * @param new_target the new target instruction handle + * @see MethodGen + */ + public void redirectExceptionHandlers( CodeExceptionGen[] exceptions, + InstructionHandle old_target, InstructionHandle new_target ) { + for (int i = 0; i < exceptions.length; i++) { + if (exceptions[i].getStartPC() == old_target) { + exceptions[i].setStartPC(new_target); + } + if (exceptions[i].getEndPC() == old_target) { + exceptions[i].setEndPC(new_target); + } + if (exceptions[i].getHandlerPC() == old_target) { + exceptions[i].setHandlerPC(new_target); + } + } + } + + private List observers; + + + /** Add observer for this object. + */ + public void addObserver( InstructionListObserver o ) { + if (observers == null) { + observers = new ArrayList(); + } + observers.add(o); + } + + + /** Remove observer for this object. + */ + public void removeObserver( InstructionListObserver o ) { + if (observers != null) { + observers.remove(o); + } + } + + + /** Call notify() method on all observers. This method is not called + * automatically whenever the state has changed, but has to be + * called by the user after he has finished editing the object. + */ + public void update() { + if (observers != null) { + for (Iterator e = observers.iterator(); e.hasNext();) { + ((InstructionListObserver) e.next()).notify(this); + } + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionListObserver.java b/java/org/apache/tomcat/util/bcel/generic/InstructionListObserver.java new file mode 100644 index 000000000..a2b1b94b5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionListObserver.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Implement this interface if you're interested in changes to an InstructionList object + * and register yourself with addObserver(). + * + * @version $Id$ + * @author M. Dahm + */ +public interface InstructionListObserver { + + public void notify( InstructionList list ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InstructionTargeter.java b/java/org/apache/tomcat/util/bcel/generic/InstructionTargeter.java new file mode 100644 index 000000000..bb29cd124 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InstructionTargeter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote that a class targets InstructionHandles within an InstructionList. Namely + * the following implementers: + * + * @see BranchHandle + * @see LocalVariableGen + * @see CodeExceptionGen + * @version $Id$ + * @author M. Dahm + */ +public interface InstructionTargeter { + + public boolean containsTarget( InstructionHandle ih ); + + + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/InvokeInstruction.java b/java/org/apache/tomcat/util/bcel/generic/InvokeInstruction.java new file mode 100644 index 000000000..6e48c8f63 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/InvokeInstruction.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.StringTokenizer; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; + +/** + * Super class for the INVOKExxx family of instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, + TypedInstruction, StackConsumer, StackProducer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + InvokeInstruction() { + } + + + /** + * @param index to constant pool + */ + protected InvokeInstruction(short opcode, int index) { + super(opcode, index); + } + + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString( ConstantPool cp ) { + Constant c = cp.getConstant(index); + StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); + return Constants.OPCODE_NAMES[opcode] + " " + tok.nextToken().replace('.', '/') + + tok.nextToken(); + } + + + /** + * Also works for instructions whose stack effect depends on the + * constant pool entry they reference. + * @return Number of words consumed from stack by this instruction + */ + public int consumeStack( ConstantPoolGen cpg ) { + int sum; + if (opcode == Constants.INVOKESTATIC) { + sum = 0; + } else { + sum = 1; // this reference + } + + String signature = getSignature(cpg); + sum += Type.getArgumentTypesSize(signature); + return sum; + } + + + /** + * Also works for instructions whose stack effect depends on the + * constant pool entry they reference. + * @return Number of words produced onto stack by this instruction + */ + public int produceStack( ConstantPoolGen cpg ) { + String signature = getSignature(cpg); + return Type.getReturnTypeSize(signature); + } + + + /** @return return type of referenced method. + */ + public Type getType( ConstantPoolGen cpg ) { + return getReturnType(cpg); + } + + + /** @return name of referenced method. + */ + public String getMethodName( ConstantPoolGen cpg ) { + return getName(cpg); + } + + + /** @return return type of referenced method. + */ + public Type getReturnType( ConstantPoolGen cpg ) { + return Type.getReturnType(getSignature(cpg)); + } + + + /** @return argument types of referenced method. + */ + public Type[] getArgumentTypes( ConstantPoolGen cpg ) { + return Type.getArgumentTypes(getSignature(cpg)); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/JSR.java b/java/org/apache/tomcat/util/bcel/generic/JSR.java new file mode 100644 index 000000000..278d5588e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/JSR.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * JSR - Jump to subroutine + * + * @version $Id$ + * @author M. Dahm + */ +public class JSR extends JsrInstruction implements VariableLengthInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + JSR() { + } + + + public JSR(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.JSR, target); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + index = getTargetOffset(); + if (opcode == org.apache.tomcat.util.bcel.Constants.JSR) { + super.dump(out); + } else { // JSR_W + index = getTargetOffset(); + out.writeByte(opcode); + out.writeInt(index); + } + } + + + protected int updatePosition( int offset, int max_offset ) { + int i = getTargetOffset(); // Depending on old position value + position += offset; // Position may be shifted by preceding expansions + if (Math.abs(i) >= (32767 - max_offset)) { // to large for short (estimate) + opcode = org.apache.tomcat.util.bcel.Constants.JSR_W; + length = 5; + return 2; // 5 - 3 + } + return 0; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitVariableLengthInstruction(this); + v.visitBranchInstruction(this); + v.visitJsrInstruction(this); + v.visitJSR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/JSR_W.java b/java/org/apache/tomcat/util/bcel/generic/JSR_W.java new file mode 100644 index 000000000..be0681f84 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/JSR_W.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * JSR_W - Jump to subroutine + * + * @version $Id$ + * @author M. Dahm + */ +public class JSR_W extends JsrInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + JSR_W() { + } + + + public JSR_W(InstructionHandle target) { + super(org.apache.tomcat.util.bcel.Constants.JSR_W, target); + length = 5; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + index = getTargetOffset(); + out.writeByte(opcode); + out.writeInt(index); + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + index = bytes.readInt(); + length = 5; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitBranchInstruction(this); + v.visitJsrInstruction(this); + v.visitJSR_W(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/JsrInstruction.java b/java/org/apache/tomcat/util/bcel/generic/JsrInstruction.java new file mode 100644 index 000000000..b0ebb6b47 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/JsrInstruction.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Super class for JSR - Jump to subroutine + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class JsrInstruction extends BranchInstruction implements UnconditionalBranch, + TypedInstruction, StackProducer { + + JsrInstruction(short opcode, InstructionHandle target) { + super(opcode, target); + } + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + JsrInstruction() { + } + + + /** @return return address type + */ + public Type getType( ConstantPoolGen cp ) { + return new ReturnaddressType(physicalSuccessor()); + } + + + /** + * Returns an InstructionHandle to the physical successor + * of this JsrInstruction. For this method to work, + * this JsrInstruction object must not be shared between + * multiple InstructionHandle objects! + * Formally, there must not be InstructionHandle objects + * i, j where i != j and i.getInstruction() == this == + * j.getInstruction(). + * @return an InstructionHandle to the "next" instruction that + * will be executed when RETurned from a subroutine. + */ + public InstructionHandle physicalSuccessor() { + InstructionHandle ih = this.target; + // Rewind! + while (ih.getPrev() != null) { + ih = ih.getPrev(); + } + // Find the handle for "this" JsrInstruction object. + while (ih.getInstruction() != this) { + ih = ih.getNext(); + } + InstructionHandle toThis = ih; + while (ih != null) { + ih = ih.getNext(); + if ((ih != null) && (ih.getInstruction() == this)) { + throw new RuntimeException("physicalSuccessor() called on a shared JsrInstruction."); + } + } + // Return the physical successor + return toThis.getNext(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/L2D.java b/java/org/apache/tomcat/util/bcel/generic/L2D.java new file mode 100644 index 000000000..4fb62eb80 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/L2D.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * L2D - Convert long to double + *
      Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class L2D extends ConversionInstruction { + + public L2D() { + super(org.apache.tomcat.util.bcel.Constants.L2D); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitL2D(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/L2F.java b/java/org/apache/tomcat/util/bcel/generic/L2F.java new file mode 100644 index 000000000..8c8f98272 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/L2F.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * L2F - Convert long to float + *
      Stack: ..., value.word1, value.word2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class L2F extends ConversionInstruction { + + public L2F() { + super(org.apache.tomcat.util.bcel.Constants.L2F); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitL2F(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/L2I.java b/java/org/apache/tomcat/util/bcel/generic/L2I.java new file mode 100644 index 000000000..90d256c50 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/L2I.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * L2I - Convert long to int + *
      Stack: ..., value.word1, value.word2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class L2I extends ConversionInstruction { + + public L2I() { + super(org.apache.tomcat.util.bcel.Constants.L2I); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitConversionInstruction(this); + v.visitL2I(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LADD.java b/java/org/apache/tomcat/util/bcel/generic/LADD.java new file mode 100644 index 000000000..a08481f6c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LADD.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LADD - Add longs + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class LADD extends ArithmeticInstruction { + + public LADD() { + super(org.apache.tomcat.util.bcel.Constants.LADD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLADD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LALOAD.java b/java/org/apache/tomcat/util/bcel/generic/LALOAD.java new file mode 100644 index 000000000..64f296a20 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LALOAD.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LALOAD - Load long from array + *
      Stack: ..., arrayref, index -> ..., value1, value2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LALOAD extends ArrayInstruction implements StackProducer { + + /** Load long from array + */ + public LALOAD() { + super(org.apache.tomcat.util.bcel.Constants.LALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitLALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LAND.java b/java/org/apache/tomcat/util/bcel/generic/LAND.java new file mode 100644 index 000000000..7ed48eb51 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LAND.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LAND - Bitwise AND longs + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class LAND extends ArithmeticInstruction { + + public LAND() { + super(org.apache.tomcat.util.bcel.Constants.LAND); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLAND(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LASTORE.java b/java/org/apache/tomcat/util/bcel/generic/LASTORE.java new file mode 100644 index 000000000..32de31b0f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LASTORE.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LASTORE - Store into long array + *
      Stack: ..., arrayref, index, value.word1, value.word2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LASTORE extends ArrayInstruction implements StackConsumer { + + /** Store long into array + */ + public LASTORE() { + super(org.apache.tomcat.util.bcel.Constants.LASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitLASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LCMP.java b/java/org/apache/tomcat/util/bcel/generic/LCMP.java new file mode 100644 index 000000000..3f481e713 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LCMP.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LCMP - Compare longs: + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result <= -1, 0, 1> + * + * @version $Id$ + * @author M. Dahm + */ +public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer { + + public LCMP() { + super(org.apache.tomcat.util.bcel.Constants.LCMP, (short) 1); + } + + + /** @return Type.LONG + */ + public Type getType( ConstantPoolGen cp ) { + return Type.LONG; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitLCMP(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LCONST.java b/java/org/apache/tomcat/util/bcel/generic/LCONST.java new file mode 100644 index 000000000..99a3138c3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LCONST.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LCONST - Push 0 or 1, other values cause an exception + * + *
      Stack: ... -> ..., 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LCONST extends Instruction implements ConstantPushInstruction, TypedInstruction { + + private long value; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LCONST() { + } + + + public LCONST(long l) { + super(org.apache.tomcat.util.bcel.Constants.LCONST_0, (short) 1); + if (l == 0) { + opcode = org.apache.tomcat.util.bcel.Constants.LCONST_0; + } else if (l == 1) { + opcode = org.apache.tomcat.util.bcel.Constants.LCONST_1; + } else { + throw new ClassGenException("LCONST can be used only for 0 and 1: " + l); + } + value = l; + } + + + public Number getValue() { + return new Long(value); + } + + + /** @return Type.LONG + */ + public Type getType( ConstantPoolGen cp ) { + return Type.LONG; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitLCONST(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LDC.java b/java/org/apache/tomcat/util/bcel/generic/LDC.java new file mode 100644 index 000000000..9fae0af4f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LDC.java @@ -0,0 +1,148 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * LDC - Push item from constant pool. + * + *
      Stack: ... -> ..., item
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LDC extends CPInstruction implements PushInstruction, ExceptionThrower, + TypedInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LDC() { + } + + + public LDC(int index) { + super(org.apache.tomcat.util.bcel.Constants.LDC_W, index); + setSize(); + } + + + // Adjust to proper size + protected final void setSize() { + if (index <= org.apache.tomcat.util.bcel.Constants.MAX_BYTE) { // Fits in one byte? + opcode = org.apache.tomcat.util.bcel.Constants.LDC; + length = 2; + } else { + opcode = org.apache.tomcat.util.bcel.Constants.LDC_W; + length = 3; + } + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + if (length == 2) { + out.writeByte(index); + } else { + out.writeShort(index); + } + } + + + /** + * Set the index to constant pool and adjust size. + */ + public final void setIndex( int index ) { + super.setIndex(index); + setSize(); + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + length = 2; + index = bytes.readUnsignedByte(); + } + + + public Object getValue( ConstantPoolGen cpg ) { + org.apache.tomcat.util.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(index); + switch (c.getTag()) { + case org.apache.tomcat.util.bcel.Constants.CONSTANT_String: + int i = ((org.apache.tomcat.util.bcel.classfile.ConstantString) c).getStringIndex(); + c = cpg.getConstantPool().getConstant(i); + return ((org.apache.tomcat.util.bcel.classfile.ConstantUtf8) c).getBytes(); + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Float: + return new Float(((org.apache.tomcat.util.bcel.classfile.ConstantFloat) c).getBytes()); + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Integer: + return new Integer(((org.apache.tomcat.util.bcel.classfile.ConstantInteger) c).getBytes()); + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Class: + return c; + default: // Never reached + throw new RuntimeException("Unknown or invalid constant type at " + index); + } + } + + + public Type getType( ConstantPoolGen cpg ) { + switch (cpg.getConstantPool().getConstant(index).getTag()) { + case org.apache.tomcat.util.bcel.Constants.CONSTANT_String: + return Type.STRING; + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Float: + return Type.FLOAT; + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Integer: + return Type.INT; + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Class: + return Type.CLASS; + default: // Never reached + throw new RuntimeException("Unknown or invalid constant type at " + index); + } + } + + + public Class[] getExceptions() { + return org.apache.tomcat.util.bcel.ExceptionConstants.EXCS_STRING_RESOLUTION; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitLDC(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LDC2_W.java b/java/org/apache/tomcat/util/bcel/generic/LDC2_W.java new file mode 100644 index 000000000..8cb58118d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LDC2_W.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LDC2_W - Push long or double from constant pool + * + *
      Stack: ... -> ..., item.word1, item.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LDC2_W extends CPInstruction implements PushInstruction, TypedInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LDC2_W() { + } + + + public LDC2_W(int index) { + super(org.apache.tomcat.util.bcel.Constants.LDC2_W, index); + } + + + public Type getType( ConstantPoolGen cpg ) { + switch (cpg.getConstantPool().getConstant(index).getTag()) { + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Long: + return Type.LONG; + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Double: + return Type.DOUBLE; + default: // Never reached + throw new RuntimeException("Unknown constant type " + opcode); + } + } + + + public Number getValue( ConstantPoolGen cpg ) { + org.apache.tomcat.util.bcel.classfile.Constant c = cpg.getConstantPool().getConstant(index); + switch (c.getTag()) { + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Long: + return new Long(((org.apache.tomcat.util.bcel.classfile.ConstantLong) c).getBytes()); + case org.apache.tomcat.util.bcel.Constants.CONSTANT_Double: + return new Double(((org.apache.tomcat.util.bcel.classfile.ConstantDouble) c).getBytes()); + default: // Never reached + throw new RuntimeException("Unknown or invalid constant type at " + index); + } + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitLDC2_W(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LDC_W.java b/java/org/apache/tomcat/util/bcel/generic/LDC_W.java new file mode 100644 index 000000000..6defb6347 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LDC_W.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * LDC_W - Push item from constant pool (wide index) + * + *
      Stack: ... -> ..., item.word1, item.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LDC_W extends LDC { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LDC_W() { + } + + + public LDC_W(int index) { + super(index); + } + + + /** + * Read needed data (i.e., index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + setIndex(bytes.readUnsignedShort()); + // Override just in case it has been changed + opcode = org.apache.tomcat.util.bcel.Constants.LDC_W; + length = 3; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LDIV.java b/java/org/apache/tomcat/util/bcel/generic/LDIV.java new file mode 100644 index 000000000..628a11a6c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LDIV.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LDIV - Divide longs + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class LDIV extends ArithmeticInstruction implements ExceptionThrower { + + public LDIV() { + super(org.apache.tomcat.util.bcel.Constants.LDIV); + } + + + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLDIV(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LLOAD.java b/java/org/apache/tomcat/util/bcel/generic/LLOAD.java new file mode 100644 index 000000000..f402223bb --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LLOAD.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LLOAD - Load long from local variable + *
      Stack ... -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LLOAD extends LoadInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LLOAD() { + super(org.apache.tomcat.util.bcel.Constants.LLOAD, org.apache.tomcat.util.bcel.Constants.LLOAD_0); + } + + + public LLOAD(int n) { + super(org.apache.tomcat.util.bcel.Constants.LLOAD, org.apache.tomcat.util.bcel.Constants.LLOAD_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitLLOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LMUL.java b/java/org/apache/tomcat/util/bcel/generic/LMUL.java new file mode 100644 index 000000000..efa1b160b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LMUL.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LMUL - Multiply longs + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class LMUL extends ArithmeticInstruction { + + public LMUL() { + super(org.apache.tomcat.util.bcel.Constants.LMUL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLMUL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LNEG.java b/java/org/apache/tomcat/util/bcel/generic/LNEG.java new file mode 100644 index 000000000..5b914bb9c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LNEG.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LNEG - Negate long + *
      Stack: ..., value.word1, value.word2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LNEG extends ArithmeticInstruction { + + public LNEG() { + super(org.apache.tomcat.util.bcel.Constants.LNEG); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLNEG(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LOOKUPSWITCH.java b/java/org/apache/tomcat/util/bcel/generic/LOOKUPSWITCH.java new file mode 100644 index 000000000..e278c9e75 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LOOKUPSWITCH.java @@ -0,0 +1,95 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * LOOKUPSWITCH - Switch with unordered set of values + * + * @version $Id$ + * @author M. Dahm + * @see SWITCH + */ +public class LOOKUPSWITCH extends Select { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LOOKUPSWITCH() { + } + + + public LOOKUPSWITCH(int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) { + super(org.apache.tomcat.util.bcel.Constants.LOOKUPSWITCH, match, targets, defaultTarget); + length = (short) (9 + match_length * 8); /* alignment remainder assumed + * 0 here, until dump time. */ + fixed_length = length; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + super.dump(out); + out.writeInt(match_length); // npairs + for (int i = 0; i < match_length; i++) { + out.writeInt(match[i]); // match-offset pairs + out.writeInt(indices[i] = getTargetOffset(targets[i])); + } + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + super.initFromFile(bytes, wide); // reads padding + match_length = bytes.readInt(); + fixed_length = (short) (9 + match_length * 8); + length = (short) (fixed_length + padding); + match = new int[match_length]; + indices = new int[match_length]; + targets = new InstructionHandle[match_length]; + for (int i = 0; i < match_length; i++) { + match[i] = bytes.readInt(); + indices[i] = bytes.readInt(); + } + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitVariableLengthInstruction(this); + v.visitStackProducer(this); + v.visitBranchInstruction(this); + v.visitSelect(this); + v.visitLOOKUPSWITCH(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LOR.java b/java/org/apache/tomcat/util/bcel/generic/LOR.java new file mode 100644 index 000000000..1e4e31fd1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LOR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LOR - Bitwise OR long + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LOR extends ArithmeticInstruction { + + public LOR() { + super(org.apache.tomcat.util.bcel.Constants.LOR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLOR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LREM.java b/java/org/apache/tomcat/util/bcel/generic/LREM.java new file mode 100644 index 000000000..20b17c5cb --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LREM.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LREM - Remainder of long + *
      Stack: ..., value1, value2 -> result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LREM extends ArithmeticInstruction implements ExceptionThrower { + + public LREM() { + super(org.apache.tomcat.util.bcel.Constants.LREM); + } + + + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.ARITHMETIC_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLREM(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LRETURN.java b/java/org/apache/tomcat/util/bcel/generic/LRETURN.java new file mode 100644 index 000000000..cd7f8a630 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LRETURN.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LRETURN - Return long from method + *
      Stack: ..., value.word1, value.word2 -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LRETURN extends ReturnInstruction { + + public LRETURN() { + super(org.apache.tomcat.util.bcel.Constants.LRETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitLRETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LSHL.java b/java/org/apache/tomcat/util/bcel/generic/LSHL.java new file mode 100644 index 000000000..d12463aa5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LSHL.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LSHL - Arithmetic shift left long + *
      Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LSHL extends ArithmeticInstruction { + + public LSHL() { + super(org.apache.tomcat.util.bcel.Constants.LSHL); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLSHL(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LSHR.java b/java/org/apache/tomcat/util/bcel/generic/LSHR.java new file mode 100644 index 000000000..81af6481c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LSHR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LSHR - Arithmetic shift right long + *
      Stack: ..., value1.word1, value1.word2, value2 -> ..., result.word1, result.word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LSHR extends ArithmeticInstruction { + + public LSHR() { + super(org.apache.tomcat.util.bcel.Constants.LSHR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLSHR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LSTORE.java b/java/org/apache/tomcat/util/bcel/generic/LSTORE.java new file mode 100644 index 000000000..2490af1b0 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LSTORE.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LSTORE - Store long into local variable + *
      Stack: ..., value.word1, value.word2 -> ... 
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LSTORE extends StoreInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + LSTORE() { + super(org.apache.tomcat.util.bcel.Constants.LSTORE, org.apache.tomcat.util.bcel.Constants.LSTORE_0); + } + + + public LSTORE(int n) { + super(org.apache.tomcat.util.bcel.Constants.LSTORE, org.apache.tomcat.util.bcel.Constants.LSTORE_0, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + super.accept(v); + v.visitLSTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LSUB.java b/java/org/apache/tomcat/util/bcel/generic/LSUB.java new file mode 100644 index 000000000..5961a5bdc --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LSUB.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LSUB - Substract longs + *
      Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
      + * ..., result.word1, result.word2 + * + * @version $Id$ + * @author M. Dahm + */ +public class LSUB extends ArithmeticInstruction { + + public LSUB() { + super(org.apache.tomcat.util.bcel.Constants.LSUB); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLSUB(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LUSHR.java b/java/org/apache/tomcat/util/bcel/generic/LUSHR.java new file mode 100644 index 000000000..862e498ce --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LUSHR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LUSHR - Logical shift right long + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LUSHR extends ArithmeticInstruction { + + public LUSHR() { + super(org.apache.tomcat.util.bcel.Constants.LUSHR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLUSHR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LXOR.java b/java/org/apache/tomcat/util/bcel/generic/LXOR.java new file mode 100644 index 000000000..93f0a9952 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LXOR.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * LXOR - Bitwise XOR long + *
      Stack: ..., value1, value2 -> ..., result
      + * + * @version $Id$ + * @author M. Dahm + */ +public class LXOR extends ArithmeticInstruction { + + public LXOR() { + super(org.apache.tomcat.util.bcel.Constants.LXOR); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitTypedInstruction(this); + v.visitStackProducer(this); + v.visitStackConsumer(this); + v.visitArithmeticInstruction(this); + v.visitLXOR(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LineNumberGen.java b/java/org/apache/tomcat/util/bcel/generic/LineNumberGen.java new file mode 100644 index 000000000..da624e518 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LineNumberGen.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.classfile.LineNumber; + +/** + * This class represents a line number within a method, i.e., give an instruction + * a line number corresponding to the source code line. + * + * @version $Id$ + * @author M. Dahm + * @see LineNumber + * @see MethodGen + */ +public class LineNumberGen implements InstructionTargeter, Cloneable, java.io.Serializable { + + private InstructionHandle ih; + private int src_line; + + + /** + * Create a line number. + * + * @param ih instruction handle to reference + */ + public LineNumberGen(InstructionHandle ih, int src_line) { + setInstruction(ih); + setSourceLine(src_line); + } + + + /** + * @return true, if ih is target of this line number + */ + public boolean containsTarget( InstructionHandle ih ) { + return this.ih == ih; + } + + + /** + * @param old_ih old target + * @param new_ih new target + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + if (old_ih != ih) { + throw new ClassGenException("Not targeting " + old_ih + ", but " + ih + "}"); + } else { + setInstruction(new_ih); + } + } + + + /** + * Get LineNumber attribute . + * + * This relies on that the instruction list has already been dumped to byte code or + * or that the `setPositions' methods has been called for the instruction list. + */ + public LineNumber getLineNumber() { + return new LineNumber(ih.getPosition(), src_line); + } + + + public void setInstruction( InstructionHandle ih ) { + BranchInstruction.notifyTarget(this.ih, ih, this); + this.ih = ih; + } + + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } + + + public InstructionHandle getInstruction() { + return ih; + } + + + public void setSourceLine( int src_line ) { + this.src_line = src_line; + } + + + public int getSourceLine() { + return src_line; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LoadClass.java b/java/org/apache/tomcat/util/bcel/generic/LoadClass.java new file mode 100644 index 000000000..ffbbfe74b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LoadClass.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes that an instruction may start the process of loading and resolving + * the referenced class in the Virtual Machine. + * + * @version $Id$ + * @author M. Dahm + */ +public interface LoadClass { + + /** + * Returns the ObjectType of the referenced class or interface + * that may be loaded and resolved. + * @return object type that may be loaded or null if a primitive is + * referenced + */ + public ObjectType getLoadClassType( ConstantPoolGen cpg ); + + + /** + * Returns the type associated with this instruction. + * LoadClass instances are always typed, but this type + * does not always refer to the type of the class or interface + * that it possibly forces to load. For example, GETFIELD would + * return the type of the field and not the type of the class + * where the field is defined. + * If no class is forced to be loaded, null is returned. + * An example for this is an ANEWARRAY instruction that creates + * an int[][]. + * @see #getLoadClassType(ConstantPoolGen) + */ + public Type getType( ConstantPoolGen cpg ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LoadInstruction.java b/java/org/apache/tomcat/util/bcel/generic/LoadInstruction.java new file mode 100644 index 000000000..6a7c513b6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LoadInstruction.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an unparameterized instruction to load a value from a local + * variable, e.g. ILOAD. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class LoadInstruction extends LocalVariableInstruction implements PushInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + * tag and length are defined in readInstruction and initFromFile, respectively. + */ + LoadInstruction(short canon_tag, short c_tag) { + super(canon_tag, c_tag); + } + + + /** + * @param opcode Instruction opcode + * @param c_tag Instruction number for compact version, ALOAD_0, e.g. + * @param n local variable index (unsigned short) + */ + protected LoadInstruction(short opcode, short c_tag, int n) { + super(opcode, c_tag, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitPushInstruction(this); + v.visitTypedInstruction(this); + v.visitLocalVariableInstruction(this); + v.visitLoadInstruction(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LocalVariableGen.java b/java/org/apache/tomcat/util/bcel/generic/LocalVariableGen.java new file mode 100644 index 000000000..1d7b83167 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LocalVariableGen.java @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.LocalVariable; + +/** + * This class represents a local variable within a method. It contains its + * scope, name and type. The generated LocalVariable object can be obtained + * with getLocalVariable which needs the instruction list and the constant + * pool as parameters. + * + * @version $Id$ + * @author M. Dahm + * @see LocalVariable + * @see MethodGen + */ +public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable, + java.io.Serializable { + + private int index; + private String name; + private Type type; + private InstructionHandle start, end; + + + /** + * Generate a local variable that with index `index'. Note that double and long + * variables need two indexs. Index indices have to be provided by the user. + * + * @param index index of local variable + * @param name its name + * @param type its type + * @param start from where the instruction is valid (null means from the start) + * @param end until where the instruction is valid (null means to the end) + */ + public LocalVariableGen(int index, String name, Type type, InstructionHandle start, + InstructionHandle end) { + if ((index < 0) || (index > Constants.MAX_SHORT)) { + throw new ClassGenException("Invalid index index: " + index); + } + this.name = name; + this.type = type; + this.index = index; + setStart(start); + setEnd(end); + } + + + /** + * Get LocalVariable object. + * + * This relies on that the instruction list has already been dumped to byte code or + * or that the `setPositions' methods has been called for the instruction list. + * + * Note that for local variables whose scope end at the last + * instruction of the method's code, the JVM specification is ambiguous: + * both a start_pc+length ending at the last instruction and + * start_pc+length ending at first index beyond the end of the code are + * valid. + * + * @param cp constant pool + */ + public LocalVariable getLocalVariable( ConstantPoolGen cp ) { + int start_pc = start.getPosition(); + int length = end.getPosition() - start_pc; + if (length > 0) { + length += end.getInstruction().getLength(); + } + int name_index = cp.addUtf8(name); + int signature_index = cp.addUtf8(type.getSignature()); + return new LocalVariable(start_pc, length, name_index, signature_index, index, cp + .getConstantPool()); + } + + + public void setIndex( int index ) { + this.index = index; + } + + + public int getIndex() { + return index; + } + + + public void setName( String name ) { + this.name = name; + } + + + public String getName() { + return name; + } + + + public void setType( Type type ) { + this.type = type; + } + + + public Type getType() { + return type; + } + + + public InstructionHandle getStart() { + return start; + } + + + public InstructionHandle getEnd() { + return end; + } + + + public void setStart( InstructionHandle start ) { + BranchInstruction.notifyTarget(this.start, start, this); + this.start = start; + } + + + public void setEnd( InstructionHandle end ) { + BranchInstruction.notifyTarget(this.end, end, this); + this.end = end; + } + + + /** + * @param old_ih old target, either start or end + * @param new_ih new target + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + boolean targeted = false; + if (start == old_ih) { + targeted = true; + setStart(new_ih); + } + if (end == old_ih) { + targeted = true; + setEnd(new_ih); + } + if (!targeted) { + throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end + + "}"); + } + } + + + /** + * @return true, if ih is target of this variable + */ + public boolean containsTarget( InstructionHandle ih ) { + return (start == ih) || (end == ih); + } + + + /** @return a hash code value for the object. + */ + public int hashCode() { + //If the user changes the name or type, problems with the targeter hashmap will occur + int hc = index ^ name.hashCode() ^ type.hashCode(); + return hc; + } + + + /** + * We consider to local variables to be equal, if the use the same index and + * are valid in the same range. + */ + public boolean equals( Object o ) { + if (!(o instanceof LocalVariableGen)) { + return false; + } + LocalVariableGen l = (LocalVariableGen) o; + return (l.index == index) && (l.start == start) && (l.end == end); + } + + + public String toString() { + return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")"; + } + + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + System.err.println(e); + return null; + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/LocalVariableInstruction.java b/java/org/apache/tomcat/util/bcel/generic/LocalVariableInstruction.java new file mode 100644 index 000000000..c93733712 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/LocalVariableInstruction.java @@ -0,0 +1,202 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Abstract super class for instructions dealing with local variables. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, + IndexedInstruction { + + protected int n = -1; // index of referenced variable + private short c_tag = -1; // compact version, such as ILOAD_0 + private short canon_tag = -1; // canonical tag such as ILOAD + + + private final boolean wide() { + return n > Constants.MAX_BYTE; + } + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + * tag and length are defined in readInstruction and initFromFile, respectively. + */ + LocalVariableInstruction(short canon_tag, short c_tag) { + super(); + this.canon_tag = canon_tag; + this.c_tag = c_tag; + } + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Also used by IINC()! + */ + LocalVariableInstruction() { + } + + + /** + * @param opcode Instruction opcode + * @param c_tag Instruction number for compact version, ALOAD_0, e.g. + * @param n local variable index (unsigned short) + */ + protected LocalVariableInstruction(short opcode, short c_tag, int n) { + super(opcode, (short) 2); + this.c_tag = c_tag; + canon_tag = opcode; + setIndex(n); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + if (wide()) { + out.writeByte(Constants.WIDE); + } + out.writeByte(opcode); + if (length > 1) { // Otherwise ILOAD_n, instruction, e.g. + if (wide()) { + out.writeShort(n); + } else { + out.writeByte(n); + } + } + } + + + /** + * Long output format: + * + * <name of opcode> "["<opcode number>"]" + * "("<length of instruction>")" "<"< local variable index>">" + * + * @param verbose long/short format switch + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + if (((opcode >= Constants.ILOAD_0) && (opcode <= Constants.ALOAD_3)) + || ((opcode >= Constants.ISTORE_0) && (opcode <= Constants.ASTORE_3))) { + return super.toString(verbose); + } else { + return super.toString(verbose) + " " + n; + } + } + + + /** + * Read needed data (e.g. index) from file. + * PRE: (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3) + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + if (wide) { + n = bytes.readUnsignedShort(); + length = 4; + } else if (((opcode >= Constants.ILOAD) && (opcode <= Constants.ALOAD)) + || ((opcode >= Constants.ISTORE) && (opcode <= Constants.ASTORE))) { + n = bytes.readUnsignedByte(); + length = 2; + } else if (opcode <= Constants.ALOAD_3) { // compact load instruction such as ILOAD_2 + n = (opcode - Constants.ILOAD_0) % 4; + length = 1; + } else { // Assert ISTORE_0 <= tag <= ASTORE_3 + n = (opcode - Constants.ISTORE_0) % 4; + length = 1; + } + } + + + /** + * @return local variable index referred by this instruction. + */ + public final int getIndex() { + return n; + } + + + /** + * Set the local variable index + */ + public void setIndex( int n ) { + if ((n < 0) || (n > Constants.MAX_SHORT)) { + throw new ClassGenException("Illegal value: " + n); + } + this.n = n; + if (n >= 0 && n <= 3) { // Use more compact instruction xLOAD_n + opcode = (short) (c_tag + n); + length = 1; + } else { + opcode = canon_tag; + if (wide()) { + length = 4; + } else { + length = 2; + } + } + } + + + /** @return canonical tag for instruction, e.g., ALOAD for ALOAD_0 + */ + public short getCanonicalTag() { + return canon_tag; + } + + + /** + * Returns the type associated with the instruction - + * in case of ALOAD or ASTORE Type.OBJECT is returned. + * This is just a bit incorrect, because ALOAD and ASTORE + * may work on every ReferenceType (including Type.NULL) and + * ASTORE may even work on a ReturnaddressType . + * @return type associated with the instruction + */ + public Type getType( ConstantPoolGen cp ) { + switch (canon_tag) { + case Constants.ILOAD: + case Constants.ISTORE: + return Type.INT; + case Constants.LLOAD: + case Constants.LSTORE: + return Type.LONG; + case Constants.DLOAD: + case Constants.DSTORE: + return Type.DOUBLE; + case Constants.FLOAD: + case Constants.FSTORE: + return Type.FLOAT; + case Constants.ALOAD: + case Constants.ASTORE: + return Type.OBJECT; + default: + throw new ClassGenException("Oops: unknown case in switch" + canon_tag); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/MONITORENTER.java b/java/org/apache/tomcat/util/bcel/generic/MONITORENTER.java new file mode 100644 index 000000000..c99fd5647 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/MONITORENTER.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * MONITORENTER - Enter monitor for object + *
      Stack: ..., objectref -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class MONITORENTER extends Instruction implements ExceptionThrower, StackConsumer { + + public MONITORENTER() { + super(org.apache.tomcat.util.bcel.Constants.MONITORENTER, (short) 1); + } + + + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackConsumer(this); + v.visitMONITORENTER(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/MONITOREXIT.java b/java/org/apache/tomcat/util/bcel/generic/MONITOREXIT.java new file mode 100644 index 000000000..38d27b73f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/MONITOREXIT.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * MONITOREXIT - Exit monitor for object + *
      Stack: ..., objectref -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class MONITOREXIT extends Instruction implements ExceptionThrower, StackConsumer { + + public MONITOREXIT() { + super(org.apache.tomcat.util.bcel.Constants.MONITOREXIT, (short) 1); + } + + + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.NULL_POINTER_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackConsumer(this); + v.visitMONITOREXIT(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/MULTIANEWARRAY.java b/java/org/apache/tomcat/util/bcel/generic/MULTIANEWARRAY.java new file mode 100644 index 000000000..f86b03e14 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/MULTIANEWARRAY.java @@ -0,0 +1,146 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.ExceptionConstants; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * MULTIANEWARRAY - Create new mutidimensional array of references + *
      Stack: ..., count1, [count2, ...] -> ..., arrayref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class MULTIANEWARRAY extends CPInstruction implements LoadClass, AllocationInstruction, + ExceptionThrower { + + private short dimensions; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + MULTIANEWARRAY() { + } + + + public MULTIANEWARRAY(int index, short dimensions) { + super(org.apache.tomcat.util.bcel.Constants.MULTIANEWARRAY, index); + if (dimensions < 1) { + throw new ClassGenException("Invalid dimensions value: " + dimensions); + } + this.dimensions = dimensions; + length = 4; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + out.writeShort(index); + out.writeByte(dimensions); + } + + + /** + * Read needed data (i.e., no. dimension) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + super.initFromFile(bytes, wide); + dimensions = bytes.readByte(); + length = 4; + } + + + /** + * @return number of dimensions to be created + */ + public final short getDimensions() { + return dimensions; + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + index + " " + dimensions; + } + + + /** + * @return mnemonic for instruction with symbolic references resolved + */ + public String toString( ConstantPool cp ) { + return super.toString(cp) + " " + dimensions; + } + + + /** + * Also works for instructions whose stack effect depends on the + * constant pool entry they reference. + * @return Number of words consumed from stack by this instruction + */ + public int consumeStack( ConstantPoolGen cpg ) { + return dimensions; + } + + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION; + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR; + return cs; + } + + + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + Type t = getType(cpg); + if (t instanceof ArrayType) { + t = ((ArrayType) t).getBasicType(); + } + return (t instanceof ObjectType) ? (ObjectType) t : null; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLoadClass(this); + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitMULTIANEWARRAY(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/MethodGen.java b/java/org/apache/tomcat/util/bcel/generic/MethodGen.java new file mode 100644 index 000000000..17846d984 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/MethodGen.java @@ -0,0 +1,1246 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.AnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.Annotations; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Code; +import org.apache.tomcat.util.bcel.classfile.CodeException; +import org.apache.tomcat.util.bcel.classfile.ExceptionTable; +import org.apache.tomcat.util.bcel.classfile.LineNumber; +import org.apache.tomcat.util.bcel.classfile.LineNumberTable; +import org.apache.tomcat.util.bcel.classfile.LocalVariable; +import org.apache.tomcat.util.bcel.classfile.LocalVariableTable; +import org.apache.tomcat.util.bcel.classfile.LocalVariableTypeTable; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.ParameterAnnotationEntry; +import org.apache.tomcat.util.bcel.classfile.ParameterAnnotations; +import org.apache.tomcat.util.bcel.classfile.RuntimeVisibleParameterAnnotations; +import org.apache.tomcat.util.bcel.classfile.Utility; +import org.apache.tomcat.util.bcel.util.BCELComparator; + +/** + * Template class for building up a method. This is done by defining exception + * handlers, adding thrown exceptions, local variables and attributes, whereas + * the `LocalVariableTable' and `LineNumberTable' attributes will be set + * automatically for the code. Use stripAttributes() if you don't like this. + * + * While generating code it may be necessary to insert NOP operations. You can + * use the `removeNOPs' method to get rid off them. + * The resulting method object can be obtained via the `getMethod()' method. + * + * @version $Id$ + * @author M. Dahm + * @author Patrick C. Beard [setMaxStack()] + * @see InstructionList + * @see Method + */ +public class MethodGen extends FieldGenOrMethodGen { + + private String class_name; + private Type[] arg_types; + private String[] arg_names; + private int max_locals; + private int max_stack; + private InstructionList il; + private boolean strip_attributes; + private List variable_vec = new ArrayList(); + private List line_number_vec = new ArrayList(); + private List exception_vec = new ArrayList(); + private List throws_vec = new ArrayList(); + private List code_attrs_vec = new ArrayList(); + + private List[] param_annotations; // Array of lists containing AnnotationGen objects + private boolean hasParameterAnnotations = false; + private boolean haveUnpackedParameterAnnotations = false; + + private static BCELComparator _cmp = new BCELComparator() { + + public boolean equals( Object o1, Object o2 ) { + MethodGen THIS = (MethodGen) o1; + MethodGen THAT = (MethodGen) o2; + return THIS.getName().equals(THAT.getName()) + && THIS.getSignature().equals(THAT.getSignature()); + } + + + public int hashCode( Object o ) { + MethodGen THIS = (MethodGen) o; + return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + } + }; + + + /** + * Declare method. If the method is non-static the constructor + * automatically declares a local variable `$this' in slot 0. The + * actual code is contained in the `il' parameter, which may further + * manipulated by the user. But he must take care not to remove any + * instruction (handles) that are still referenced from this object. + * + * For example one may not add a local variable and later remove the + * instructions it refers to without causing havoc. It is safe + * however if you remove that local variable, too. + * + * @param access_flags access qualifiers + * @param return_type method type + * @param arg_types argument types + * @param arg_names argument names (if this is null, default names will be provided + * for them) + * @param method_name name of method + * @param class_name class name containing this method (may be null, if you don't care) + * @param il instruction list associated with this method, may be null only for + * abstract or native methods + * @param cp constant pool + */ + public MethodGen(int access_flags, Type return_type, Type[] arg_types, String[] arg_names, + String method_name, String class_name, InstructionList il, ConstantPoolGen cp) { + setAccessFlags(access_flags); + setType(return_type); + setArgumentTypes(arg_types); + setArgumentNames(arg_names); + setName(method_name); + setClassName(class_name); + setInstructionList(il); + setConstantPool(cp); + boolean abstract_ = isAbstract() || isNative(); + InstructionHandle start = null; + InstructionHandle end = null; + if (!abstract_) { + start = il.getStart(); + end = il.getEnd(); + /* Add local variables, namely the implicit `this' and the arguments + */ + if (!isStatic() && (class_name != null)) { // Instance method -> `this' is local var 0 + addLocalVariable("this", new ObjectType(class_name), start, end); + } + } + if (arg_types != null) { + int size = arg_types.length; + for (int i = 0; i < size; i++) { + if (Type.VOID == arg_types[i]) { + throw new ClassGenException("'void' is an illegal argument type for a method"); + } + } + if (arg_names != null) { // Names for variables provided? + if (size != arg_names.length) { + throw new ClassGenException("Mismatch in argument array lengths: " + size + + " vs. " + arg_names.length); + } + } else { // Give them dummy names + arg_names = new String[size]; + for (int i = 0; i < size; i++) { + arg_names[i] = "arg" + i; + } + setArgumentNames(arg_names); + } + if (!abstract_) { + for (int i = 0; i < size; i++) { + addLocalVariable(arg_names[i], arg_types[i], start, end); + } + } + } + } + + + /** + * Instantiate from existing method. + * + * @param m method + * @param class_name class name containing this method + * @param cp constant pool + */ + public MethodGen(Method m, String class_name, ConstantPoolGen cp) { + this(m.getAccessFlags(), Type.getReturnType(m.getSignature()), Type.getArgumentTypes(m + .getSignature()), null /* may be overridden anyway */ + , m.getName(), class_name, + ((m.getAccessFlags() & (Constants.ACC_ABSTRACT | Constants.ACC_NATIVE)) == 0) + ? new InstructionList(m.getCode().getCode()) + : null, cp); + Attribute[] attributes = m.getAttributes(); + for (int i = 0; i < attributes.length; i++) { + Attribute a = attributes[i]; + if (a instanceof Code) { + Code c = (Code) a; + setMaxStack(c.getMaxStack()); + setMaxLocals(c.getMaxLocals()); + CodeException[] ces = c.getExceptionTable(); + if (ces != null) { + for (int j = 0; j < ces.length; j++) { + CodeException ce = ces[j]; + int type = ce.getCatchType(); + ObjectType c_type = null; + if (type > 0) { + String cen = m.getConstantPool().getConstantString(type, + Constants.CONSTANT_Class); + c_type = new ObjectType(cen); + } + int end_pc = ce.getEndPC(); + int length = m.getCode().getCode().length; + InstructionHandle end; + if (length == end_pc) { // May happen, because end_pc is exclusive + end = il.getEnd(); + } else { + end = il.findHandle(end_pc); + end = end.getPrev(); // Make it inclusive + } + addExceptionHandler(il.findHandle(ce.getStartPC()), end, il.findHandle(ce + .getHandlerPC()), c_type); + } + } + Attribute[] c_attributes = c.getAttributes(); + for (int j = 0; j < c_attributes.length; j++) { + a = c_attributes[j]; + if (a instanceof LineNumberTable) { + LineNumber[] ln = ((LineNumberTable) a).getLineNumberTable(); + for (int k = 0; k < ln.length; k++) { + LineNumber l = ln[k]; + InstructionHandle ih = il.findHandle(l.getStartPC()); + if (ih != null) { + addLineNumber(ih, l.getLineNumber()); + } + } + } else if (a instanceof LocalVariableTable) { + LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable(); + removeLocalVariables(); + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + InstructionHandle start = il.findHandle(l.getStartPC()); + InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); + // Repair malformed handles + if (null == start) { + start = il.getStart(); + } + if (null == end) { + end = il.getEnd(); + } + addLocalVariable(l.getName(), Type.getType(l.getSignature()), l + .getIndex(), start, end); + } + } else if (a instanceof LocalVariableTypeTable) { + LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable(); + removeLocalVariables(); + for (int k = 0; k < lv.length; k++) { + LocalVariable l = lv[k]; + InstructionHandle start = il.findHandle(l.getStartPC()); + InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength()); + // Repair malformed handles + if (null == start) { + start = il.getStart(); + } + if (null == end) { + end = il.getEnd(); + } + addLocalVariable(l.getName(), Type.getType(l.getSignature()), l + .getIndex(), start, end); + } + } else { + addCodeAttribute(a); + } + } + } else if (a instanceof ExceptionTable) { + String[] names = ((ExceptionTable) a).getExceptionNames(); + for (int j = 0; j < names.length; j++) { + addException(names[j]); + } + } else if (a instanceof Annotations) { + Annotations runtimeAnnotations = (Annotations) a; + AnnotationEntry[] aes = runtimeAnnotations.getAnnotationEntries(); + for (int k = 0; k < aes.length; k++) { + AnnotationEntry element = aes[k]; + addAnnotationEntry(new AnnotationEntryGen(element, cp, false)); + } + } else { + addAttribute(a); + } + } + } + + + /** + * Adds a local variable to this method. + * + * @param name variable name + * @param type variable type + * @param slot the index of the local variable, if type is long or double, the next available + * index is slot+2 + * @param start from where the variable is valid + * @param end until where the variable is valid + * @return new local variable object + * @see LocalVariable + */ + public LocalVariableGen addLocalVariable( String name, Type type, int slot, + InstructionHandle start, InstructionHandle end ) { + byte t = type.getType(); + if (t != Constants.T_ADDRESS) { + int add = type.getSize(); + if (slot + add > max_locals) { + max_locals = slot + add; + } + LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end); + int i; + if ((i = variable_vec.indexOf(l)) >= 0) { + variable_vec.set(i, l); + } else { + variable_vec.add(l); + } + return l; + } else { + throw new IllegalArgumentException("Can not use " + type + + " as type for local variable"); + } + } + + + /** + * Adds a local variable to this method and assigns an index automatically. + * + * @param name variable name + * @param type variable type + * @param start from where the variable is valid, if this is null, + * it is valid from the start + * @param end until where the variable is valid, if this is null, + * it is valid to the end + * @return new local variable object + * @see LocalVariable + */ + public LocalVariableGen addLocalVariable( String name, Type type, InstructionHandle start, + InstructionHandle end ) { + return addLocalVariable(name, type, max_locals, start, end); + } + + + /** + * Remove a local variable, its slot will not be reused, if you do not use addLocalVariable + * with an explicit index argument. + */ + public void removeLocalVariable( LocalVariableGen l ) { + variable_vec.remove(l); + } + + + /** + * Remove all local variables. + */ + public void removeLocalVariables() { + variable_vec.clear(); + } + + + /** + * Sort local variables by index + */ + private static final void sort( LocalVariableGen[] vars, int l, int r ) { + int i = l, j = r; + int m = vars[(l + r) / 2].getIndex(); + LocalVariableGen h; + do { + while (vars[i].getIndex() < m) { + i++; + } + while (m < vars[j].getIndex()) { + j--; + } + if (i <= j) { + h = vars[i]; + vars[i] = vars[j]; + vars[j] = h; // Swap elements + i++; + j--; + } + } while (i <= j); + if (l < j) { + sort(vars, l, j); + } + if (i < r) { + sort(vars, i, r); + } + } + + + /* + * If the range of the variable has not been set yet, it will be set to be valid from + * the start to the end of the instruction list. + * + * @return array of declared local variables sorted by index + */ + public LocalVariableGen[] getLocalVariables() { + int size = variable_vec.size(); + LocalVariableGen[] lg = new LocalVariableGen[size]; + variable_vec.toArray(lg); + for (int i = 0; i < size; i++) { + if (lg[i].getStart() == null) { + lg[i].setStart(il.getStart()); + } + if (lg[i].getEnd() == null) { + lg[i].setEnd(il.getEnd()); + } + } + if (size > 1) { + sort(lg, 0, size - 1); + } + return lg; + } + + + /** + * @return `LocalVariableTable' attribute of all the local variables of this method. + */ + public LocalVariableTable getLocalVariableTable( ConstantPoolGen cp ) { + LocalVariableGen[] lg = getLocalVariables(); + int size = lg.length; + LocalVariable[] lv = new LocalVariable[size]; + for (int i = 0; i < size; i++) { + lv[i] = lg[i].getLocalVariable(cp); + } + return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp + .getConstantPool()); + } + + + /** + * Give an instruction a line number corresponding to the source code line. + * + * @param ih instruction to tag + * @return new line number object + * @see LineNumber + */ + public LineNumberGen addLineNumber( InstructionHandle ih, int src_line ) { + LineNumberGen l = new LineNumberGen(ih, src_line); + line_number_vec.add(l); + return l; + } + + + /** + * Remove a line number. + */ + public void removeLineNumber( LineNumberGen l ) { + line_number_vec.remove(l); + } + + + /** + * Remove all line numbers. + */ + public void removeLineNumbers() { + line_number_vec.clear(); + } + + + /* + * @return array of line numbers + */ + public LineNumberGen[] getLineNumbers() { + LineNumberGen[] lg = new LineNumberGen[line_number_vec.size()]; + line_number_vec.toArray(lg); + return lg; + } + + + /** + * @return `LineNumberTable' attribute of all the local variables of this method. + */ + public LineNumberTable getLineNumberTable( ConstantPoolGen cp ) { + int size = line_number_vec.size(); + LineNumber[] ln = new LineNumber[size]; + try { + for (int i = 0; i < size; i++) { + ln[i] = ((LineNumberGen) line_number_vec.get(i)).getLineNumber(); + } + } catch (ArrayIndexOutOfBoundsException e) { + } // Never occurs + return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp + .getConstantPool()); + } + + + /** + * Add an exception handler, i.e., specify region where a handler is active and an + * instruction where the actual handling is done. + * + * @param start_pc Start of region (inclusive) + * @param end_pc End of region (inclusive) + * @param handler_pc Where handling is done + * @param catch_type class type of handled exception or null if any + * exception is handled + * @return new exception handler object + */ + public CodeExceptionGen addExceptionHandler( InstructionHandle start_pc, + InstructionHandle end_pc, InstructionHandle handler_pc, ObjectType catch_type ) { + if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) { + throw new ClassGenException("Exception handler target is null instruction"); + } + CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc, catch_type); + exception_vec.add(c); + return c; + } + + + /** + * Remove an exception handler. + */ + public void removeExceptionHandler( CodeExceptionGen c ) { + exception_vec.remove(c); + } + + + /** + * Remove all line numbers. + */ + public void removeExceptionHandlers() { + exception_vec.clear(); + } + + + /* + * @return array of declared exception handlers + */ + public CodeExceptionGen[] getExceptionHandlers() { + CodeExceptionGen[] cg = new CodeExceptionGen[exception_vec.size()]; + exception_vec.toArray(cg); + return cg; + } + + + /** + * @return code exceptions for `Code' attribute + */ + private CodeException[] getCodeExceptions() { + int size = exception_vec.size(); + CodeException[] c_exc = new CodeException[size]; + try { + for (int i = 0; i < size; i++) { + CodeExceptionGen c = (CodeExceptionGen) exception_vec.get(i); + c_exc[i] = c.getCodeException(cp); + } + } catch (ArrayIndexOutOfBoundsException e) { + } + return c_exc; + } + + + /** + * Add an exception possibly thrown by this method. + * + * @param class_name (fully qualified) name of exception + */ + public void addException( String class_name ) { + throws_vec.add(class_name); + } + + + /** + * Remove an exception. + */ + public void removeException( String c ) { + throws_vec.remove(c); + } + + + /** + * Remove all exceptions. + */ + public void removeExceptions() { + throws_vec.clear(); + } + + + /* + * @return array of thrown exceptions + */ + public String[] getExceptions() { + String[] e = new String[throws_vec.size()]; + throws_vec.toArray(e); + return e; + } + + + /** + * @return `Exceptions' attribute of all the exceptions thrown by this method. + */ + private ExceptionTable getExceptionTable( ConstantPoolGen cp ) { + int size = throws_vec.size(); + int[] ex = new int[size]; + try { + for (int i = 0; i < size; i++) { + ex[i] = cp.addClass((String) throws_vec.get(i)); + } + } catch (ArrayIndexOutOfBoundsException e) { + } + return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex, cp.getConstantPool()); + } + + + /** + * Add an attribute to the code. Currently, the JVM knows about the + * LineNumberTable, LocalVariableTable and StackMap attributes, + * where the former two will be generated automatically and the + * latter is used for the MIDP only. Other attributes will be + * ignored by the JVM but do no harm. + * + * @param a attribute to be added + */ + public void addCodeAttribute( Attribute a ) { + code_attrs_vec.add(a); + } + + + /** + * Remove a code attribute. + */ + public void removeCodeAttribute( Attribute a ) { + code_attrs_vec.remove(a); + } + + + /** + * Remove all code attributes. + */ + public void removeCodeAttributes() { + code_attrs_vec.clear(); + } + + + /** + * @return all attributes of this method. + */ + public Attribute[] getCodeAttributes() { + Attribute[] attributes = new Attribute[code_attrs_vec.size()]; + code_attrs_vec.toArray(attributes); + return attributes; + } + + public void addAnnotationsAsAttribute(ConstantPoolGen cp) { + Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotation_vec); + for (int i = 0; i < attrs.length; i++) { + addAttribute(attrs[i]); + } + } + + public void addParameterAnnotationsAsAttribute(ConstantPoolGen cp) { + if (!hasParameterAnnotations) return; + Attribute[] attrs = Utility.getParameterAnnotationAttributes(cp,param_annotations); + if (attrs!=null) { + for (int i = 0; i < attrs.length; i++) { + addAttribute(attrs[i]); + } + } + } + + + /** + * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, + * before calling this method (the same applies for max locals). + * + * @return method object + */ + public Method getMethod() { + String signature = getSignature(); + int name_index = cp.addUtf8(name); + int signature_index = cp.addUtf8(signature); + /* Also updates positions of instructions, i.e., their indices + */ + byte[] byte_code = null; + if (il != null) { + byte_code = il.getByteCode(); + } + LineNumberTable lnt = null; + LocalVariableTable lvt = null; + /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) + */ + if ((variable_vec.size() > 0) && !strip_attributes) { + addCodeAttribute(lvt = getLocalVariableTable(cp)); + } + if ((line_number_vec.size() > 0) && !strip_attributes) { + addCodeAttribute(lnt = getLineNumberTable(cp)); + } + Attribute[] code_attrs = getCodeAttributes(); + /* Each attribute causes 6 additional header bytes + */ + int attrs_len = 0; + for (int i = 0; i < code_attrs.length; i++) { + attrs_len += (code_attrs[i].getLength() + 6); + } + CodeException[] c_exc = getCodeExceptions(); + int exc_len = c_exc.length * 8; // Every entry takes 8 bytes + Code code = null; + if ((il != null) && !isAbstract() && !isNative()) { + // Remove any stale code attribute + Attribute[] attributes = getAttributes(); + for (int i = 0; i < attributes.length; i++) { + Attribute a = attributes[i]; + if (a instanceof Code) { + removeAttribute(a); + } + } + code = new Code(cp.addUtf8("Code"), 8 + byte_code.length + // prologue byte code + 2 + exc_len + // exceptions + 2 + attrs_len, // attributes + max_stack, max_locals, byte_code, c_exc, code_attrs, cp.getConstantPool()); + addAttribute(code); + } + addAnnotationsAsAttribute(cp); + addParameterAnnotationsAsAttribute(cp); + ExceptionTable et = null; + if (throws_vec.size() > 0) { + addAttribute(et = getExceptionTable(cp)); + // Add `Exceptions' if there are "throws" clauses + } + Method m = new Method(access_flags, name_index, signature_index, getAttributes(), cp + .getConstantPool()); + // Undo effects of adding attributes + if (lvt != null) { + removeCodeAttribute(lvt); + } + if (lnt != null) { + removeCodeAttribute(lnt); + } + if (code != null) { + removeAttribute(code); + } + if (et != null) { + removeAttribute(et); + } + return m; + } + + + /** + * Remove all NOPs from the instruction list (if possible) and update every + * object refering to them, i.e., branch instructions, local variables and + * exception handlers. + */ + public void removeNOPs() { + if (il != null) { + InstructionHandle next; + /* Check branch instructions. + */ + for (InstructionHandle ih = il.getStart(); ih != null; ih = next) { + next = ih.next; + if ((next != null) && (ih.getInstruction() instanceof NOP)) { + try { + il.delete(ih); + } catch (TargetLostException e) { + InstructionHandle[] targets = e.getTargets(); + for (int i = 0; i < targets.length; i++) { + InstructionTargeter[] targeters = targets[i].getTargeters(); + for (int j = 0; j < targeters.length; j++) { + targeters[j].updateTarget(targets[i], next); + } + } + } + } + } + } + } + + + /** + * Set maximum number of local variables. + */ + public void setMaxLocals( int m ) { + max_locals = m; + } + + + public int getMaxLocals() { + return max_locals; + } + + + /** + * Set maximum stack size for this method. + */ + public void setMaxStack( int m ) { + max_stack = m; + } + + + public int getMaxStack() { + return max_stack; + } + + + /** @return class that contains this method + */ + public String getClassName() { + return class_name; + } + + + public void setClassName( String class_name ) { + this.class_name = class_name; + } + + + public void setReturnType( Type return_type ) { + setType(return_type); + } + + + public Type getReturnType() { + return getType(); + } + + + public void setArgumentTypes( Type[] arg_types ) { + this.arg_types = arg_types; + } + + + public Type[] getArgumentTypes() { + return (Type[]) arg_types.clone(); + } + + + public void setArgumentType( int i, Type type ) { + arg_types[i] = type; + } + + + public Type getArgumentType( int i ) { + return arg_types[i]; + } + + + public void setArgumentNames( String[] arg_names ) { + this.arg_names = arg_names; + } + + + public String[] getArgumentNames() { + return (String[]) arg_names.clone(); + } + + + public void setArgumentName( int i, String name ) { + arg_names[i] = name; + } + + + public String getArgumentName( int i ) { + return arg_names[i]; + } + + + public InstructionList getInstructionList() { + return il; + } + + + public void setInstructionList( InstructionList il ) { + this.il = il; + } + + + public String getSignature() { + return Type.getMethodSignature(type, arg_types); + } + + + /** + * Computes max. stack size by performing control flow analysis. + */ + public void setMaxStack() { + if (il != null) { + max_stack = getMaxStack(cp, il, getExceptionHandlers()); + } else { + max_stack = 0; + } + } + + + /** + * Compute maximum number of local variables. + */ + public void setMaxLocals() { + if (il != null) { + int max = isStatic() ? 0 : 1; + if (arg_types != null) { + for (int i = 0; i < arg_types.length; i++) { + max += arg_types[i].getSize(); + } + } + for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) { + Instruction ins = ih.getInstruction(); + if ((ins instanceof LocalVariableInstruction) || (ins instanceof RET) + || (ins instanceof IINC)) { + int index = ((IndexedInstruction) ins).getIndex() + + ((TypedInstruction) ins).getType(cp).getSize(); + if (index > max) { + max = index; + } + } + } + max_locals = max; + } else { + max_locals = 0; + } + } + + + /** Do not/Do produce attributes code attributesLineNumberTable and + * LocalVariableTable, like javac -O + */ + public void stripAttributes( boolean flag ) { + strip_attributes = flag; + } + + static final class BranchTarget { + + InstructionHandle target; + int stackDepth; + + + BranchTarget(InstructionHandle target, int stackDepth) { + this.target = target; + this.stackDepth = stackDepth; + } + } + + static final class BranchStack { + + Stack branchTargets = new Stack(); + Hashtable visitedTargets = new Hashtable(); + + + public void push( InstructionHandle target, int stackDepth ) { + if (visited(target)) { + return; + } + branchTargets.push(visit(target, stackDepth)); + } + + + public BranchTarget pop() { + if (!branchTargets.empty()) { + BranchTarget bt = (BranchTarget) branchTargets.pop(); + return bt; + } + return null; + } + + + private final BranchTarget visit( InstructionHandle target, int stackDepth ) { + BranchTarget bt = new BranchTarget(target, stackDepth); + visitedTargets.put(target, bt); + return bt; + } + + + private final boolean visited( InstructionHandle target ) { + return (visitedTargets.get(target) != null); + } + } + + + /** + * Computes stack usage of an instruction list by performing control flow analysis. + * + * @return maximum stack depth used by method + */ + public static int getMaxStack( ConstantPoolGen cp, InstructionList il, CodeExceptionGen[] et ) { + BranchStack branchTargets = new BranchStack(); + /* Initially, populate the branch stack with the exception + * handlers, because these aren't (necessarily) branched to + * explicitly. in each case, the stack will have depth 1, + * containing the exception object. + */ + for (int i = 0; i < et.length; i++) { + InstructionHandle handler_pc = et[i].getHandlerPC(); + if (handler_pc != null) { + branchTargets.push(handler_pc, 1); + } + } + int stackDepth = 0, maxStackDepth = 0; + InstructionHandle ih = il.getStart(); + while (ih != null) { + Instruction instruction = ih.getInstruction(); + short opcode = instruction.getOpcode(); + int delta = instruction.produceStack(cp) - instruction.consumeStack(cp); + stackDepth += delta; + if (stackDepth > maxStackDepth) { + maxStackDepth = stackDepth; + } + // choose the next instruction based on whether current is a branch. + if (instruction instanceof BranchInstruction) { + BranchInstruction branch = (BranchInstruction) instruction; + if (instruction instanceof Select) { + // explore all of the select's targets. the default target is handled below. + Select select = (Select) branch; + InstructionHandle[] targets = select.getTargets(); + for (int i = 0; i < targets.length; i++) { + branchTargets.push(targets[i], stackDepth); + } + // nothing to fall through to. + ih = null; + } else if (!(branch instanceof IfInstruction)) { + // if an instruction that comes back to following PC, + // push next instruction, with stack depth reduced by 1. + if (opcode == Constants.JSR || opcode == Constants.JSR_W) { + branchTargets.push(ih.getNext(), stackDepth - 1); + } + ih = null; + } + // for all branches, the target of the branch is pushed on the branch stack. + // conditional branches have a fall through case, selects don't, and + // jsr/jsr_w return to the next instruction. + branchTargets.push(branch.getTarget(), stackDepth); + } else { + // check for instructions that terminate the method. + if (opcode == Constants.ATHROW || opcode == Constants.RET + || (opcode >= Constants.IRETURN && opcode <= Constants.RETURN)) { + ih = null; + } + } + // normal case, go to the next instruction. + if (ih != null) { + ih = ih.getNext(); + } + // if we have no more instructions, see if there are any deferred branches to explore. + if (ih == null) { + BranchTarget bt = branchTargets.pop(); + if (bt != null) { + ih = bt.target; + stackDepth = bt.stackDepth; + } + } + } + return maxStackDepth; + } + + private List observers; + + + /** Add observer for this object. + */ + public void addObserver( MethodObserver o ) { + if (observers == null) { + observers = new ArrayList(); + } + observers.add(o); + } + + + /** Remove observer for this object. + */ + public void removeObserver( MethodObserver o ) { + if (observers != null) { + observers.remove(o); + } + } + + + /** Call notify() method on all observers. This method is not called + * automatically whenever the state has changed, but has to be + * called by the user after he has finished editing the object. + */ + public void update() { + if (observers != null) { + for (Iterator e = observers.iterator(); e.hasNext();) { + ((MethodObserver) e.next()).notify(this); + } + } + } + + + /** + * Return string representation close to declaration format, + * `public static void main(String[]) throws IOException', e.g. + * + * @return String representation of the method. + */ + public final String toString() { + String access = Utility.accessToString(access_flags); + String signature = Type.getMethodSignature(type, arg_types); + signature = Utility.methodSignatureToString(signature, name, access, true, + getLocalVariableTable(cp)); + StringBuffer buf = new StringBuffer(signature); + for (int i = 0; i < getAttributes().length; i++) { + Attribute a = getAttributes()[i]; + if (!((a instanceof Code) || (a instanceof ExceptionTable))) { + buf.append(" [").append(a.toString()).append("]"); + } + } + + if (throws_vec.size() > 0) { + for (Iterator e = throws_vec.iterator(); e.hasNext();) { + buf.append("\n\t\tthrows ").append(e.next()); + } + } + return buf.toString(); + } + + + /** @return deep copy of this method + */ + public MethodGen copy( String class_name, ConstantPoolGen cp ) { + Method m = ((MethodGen) clone()).getMethod(); + MethodGen mg = new MethodGen(m, class_name, this.cp); + if (this.cp != cp) { + mg.setConstantPool(cp); + mg.getInstructionList().replaceConstantPool(this.cp, cp); + } + return mg; + } + + //J5TODO: Should param_annotations be an array of arrays? Rather than an array of lists, this + // is more likely to suggest to the caller it is readonly (which a List does not). + /** + * Return a list of AnnotationGen objects representing parameter annotations + */ + public List getAnnotationsOnParameter(int i) { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations || i>arg_types.length) return null; + return param_annotations[i]; + } + + /** + * Goes through the attributes on the method and identifies any that are + * RuntimeParameterAnnotations, extracting their contents and storing them + * as parameter annotations. There are two kinds of parameter annotation - + * visible and invisible. Once they have been unpacked, these attributes are + * deleted. (The annotations will be rebuilt as attributes when someone + * builds a Method object out of this MethodGen object). + */ + private void ensureExistingParameterAnnotationsUnpacked() + { + if (haveUnpackedParameterAnnotations) + return; + // Find attributes that contain parameter annotation data + Attribute[] attrs = getAttributes(); + ParameterAnnotations paramAnnVisAttr = null; + ParameterAnnotations paramAnnInvisAttr = null; + for (int i = 0; i < attrs.length; i++) + { + Attribute attribute = attrs[i]; + if (attribute instanceof ParameterAnnotations) + { + // Initialize param_annotations + if (!hasParameterAnnotations) + { + param_annotations = new List[arg_types.length]; + for (int j = 0; j < arg_types.length; j++) + param_annotations[j] = new ArrayList(); + } + hasParameterAnnotations = true; + ParameterAnnotations rpa = (ParameterAnnotations) attribute; + if (rpa instanceof RuntimeVisibleParameterAnnotations) + paramAnnVisAttr = rpa; + else + paramAnnInvisAttr = rpa; + for (int j = 0; j < arg_types.length; j++) + { + // This returns Annotation[] ... + ParameterAnnotationEntry immutableArray = rpa + .getParameterAnnotationEntries()[j]; + // ... which needs transforming into an AnnotationGen[] ... + List mutable = makeMutableVersion(immutableArray.getAnnotationEntries()); + // ... then add these to any we already know about + param_annotations[j].addAll(mutable); + } + } + } + if (paramAnnVisAttr != null) + removeAttribute(paramAnnVisAttr); + if (paramAnnInvisAttr != null) + removeAttribute(paramAnnInvisAttr); + haveUnpackedParameterAnnotations = true; + } + + private List /* AnnotationGen */makeMutableVersion(AnnotationEntry[] mutableArray) + { + List result = new ArrayList(); + for (int i = 0; i < mutableArray.length; i++) + { + result.add(new AnnotationEntryGen(mutableArray[i], getConstantPool(), + false)); + } + return result; + } + + public void addParameterAnnotation(int parameterIndex, + AnnotationEntryGen annotation) + { + ensureExistingParameterAnnotationsUnpacked(); + if (!hasParameterAnnotations) + { + param_annotations = new List[arg_types.length]; + hasParameterAnnotations = true; + } + List existingAnnotations = param_annotations[parameterIndex]; + if (existingAnnotations != null) + { + existingAnnotations.add(annotation); + } + else + { + List l = new ArrayList(); + l.add(annotation); + param_annotations[parameterIndex] = l; + } + } + + + + + /** + * @return Comparison strategy object + */ + public static BCELComparator getComparator() { + return _cmp; + } + + + /** + * @param comparator Comparison strategy object + */ + public static void setComparator( BCELComparator comparator ) { + _cmp = comparator; + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default two MethodGen objects are said to be equal when + * their names and signatures are equal. + * + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals( Object obj ) { + return _cmp.equals(this, obj); + } + + + /** + * Return value as defined by given BCELComparator strategy. + * By default return the hashcode of the method's name XOR signature. + * + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return _cmp.hashCode(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/MethodObserver.java b/java/org/apache/tomcat/util/bcel/generic/MethodObserver.java new file mode 100644 index 000000000..15618f383 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/MethodObserver.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Implement this interface if you're interested in changes to a MethodGen object + * and register yourself with addObserver(). + * + * @version $Id$ + * @author M. Dahm + */ +public interface MethodObserver { + + public void notify( MethodGen method ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/NEW.java b/java/org/apache/tomcat/util/bcel/generic/NEW.java new file mode 100644 index 000000000..9d2aeb593 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/NEW.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * NEW - Create new object + *
      Stack: ... -> ..., objectref
      + * + * @version $Id$ + * @author M. Dahm + */ +public class NEW extends CPInstruction implements LoadClass, AllocationInstruction, + ExceptionThrower, StackProducer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + NEW() { + } + + + public NEW(int index) { + super(org.apache.tomcat.util.bcel.Constants.NEW, index); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length); + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length + 1] = ExceptionConstants.INSTANTIATION_ERROR; + cs[ExceptionConstants.EXCS_CLASS_AND_INTERFACE_RESOLUTION.length] = ExceptionConstants.ILLEGAL_ACCESS_ERROR; + return cs; + } + + + public ObjectType getLoadClassType( ConstantPoolGen cpg ) { + return (ObjectType) getType(cpg); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitLoadClass(this); + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitCPInstruction(this); + v.visitNEW(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/NEWARRAY.java b/java/org/apache/tomcat/util/bcel/generic/NEWARRAY.java new file mode 100644 index 000000000..22af18de1 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/NEWARRAY.java @@ -0,0 +1,120 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * NEWARRAY - Create new array of basic type (int, short, ...) + *
      Stack: ..., count -> ..., arrayref
      + * type must be one of T_INT, T_SHORT, ... + * + * @version $Id$ + * @author M. Dahm + */ +public class NEWARRAY extends Instruction implements AllocationInstruction, ExceptionThrower, + StackProducer { + + private byte type; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + NEWARRAY() { + } + + + public NEWARRAY(byte type) { + super(org.apache.tomcat.util.bcel.Constants.NEWARRAY, (short) 2); + this.type = type; + } + + + public NEWARRAY(BasicType type) { + this(type.getType()); + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + out.writeByte(type); + } + + + /** + * @return numeric code for basic element type + */ + public final byte getTypecode() { + return type; + } + + + /** + * @return type of constructed array + */ + public final Type getType() { + return new ArrayType(BasicType.getType(type), 1); + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + org.apache.tomcat.util.bcel.Constants.TYPE_NAMES[type]; + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + type = bytes.readByte(); + length = 2; + } + + + public Class[] getExceptions() { + return new Class[] { + org.apache.tomcat.util.bcel.ExceptionConstants.NEGATIVE_ARRAY_SIZE_EXCEPTION + }; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitAllocationInstruction(this); + v.visitExceptionThrower(this); + v.visitStackProducer(this); + v.visitNEWARRAY(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/NOP.java b/java/org/apache/tomcat/util/bcel/generic/NOP.java new file mode 100644 index 000000000..d9f3f5ec2 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/NOP.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * NOP - Do nothing + * + * @version $Id$ + * @author M. Dahm + */ +public class NOP extends Instruction { + + public NOP() { + super(org.apache.tomcat.util.bcel.Constants.NOP, (short) 1); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitNOP(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/NamedAndTyped.java b/java/org/apache/tomcat/util/bcel/generic/NamedAndTyped.java new file mode 100644 index 000000000..68bbce2bd --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/NamedAndTyped.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote entity that has both name and type. This is true for local variables, + * methods and fields. + * + * @version $Id$ + * @author M. Dahm + */ +public interface NamedAndTyped { + + public String getName(); + + + public Type getType(); + + + public void setName( String name ); + + + public void setType( Type type ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ObjectType.java b/java/org/apache/tomcat/util/bcel/generic/ObjectType.java new file mode 100644 index 000000000..7d7d803b8 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ObjectType.java @@ -0,0 +1,155 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.Repository; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Denotes reference such as java.lang.String. + * + * @version $Id$ + * @author M. Dahm + */ +public class ObjectType extends ReferenceType { + + private String class_name; // Class name of type + + + /** + * @param class_name fully qualified class name, e.g. java.lang.String + */ + public ObjectType(String class_name) { + super(Constants.T_REFERENCE, "L" + class_name.replace('.', '/') + ";"); + this.class_name = class_name.replace('/', '.'); + } + + + /** @return name of referenced class + */ + public String getClassName() { + return class_name; + } + + + /** @return a hash code value for the object. + */ + public int hashCode() { + return class_name.hashCode(); + } + + + /** @return true if both type objects refer to the same class. + */ + public boolean equals( Object type ) { + return (type instanceof ObjectType) + ? ((ObjectType) type).class_name.equals(class_name) + : false; + } + + + /** + * If "this" doesn't reference a class, it references an interface + * or a non-existant entity. + * @deprecated this method returns an inaccurate result + * if the class or interface referenced cannot + * be found: use referencesClassExact() instead + */ + public boolean referencesClass() { + try { + JavaClass jc = Repository.lookupClass(class_name); + return jc.isClass(); + } catch (ClassNotFoundException e) { + return false; + } + } + + + /** + * If "this" doesn't reference an interface, it references a class + * or a non-existant entity. + * @deprecated this method returns an inaccurate result + * if the class or interface referenced cannot + * be found: use referencesInterfaceExact() instead + */ + public boolean referencesInterface() { + try { + JavaClass jc = Repository.lookupClass(class_name); + return !jc.isClass(); + } catch (ClassNotFoundException e) { + return false; + } + } + + + /** + * Return true if this type references a class, + * false if it references an interface. + * @return true if the type references a class, false if + * it references an interface + * @throws ClassNotFoundException if the class or interface + * referenced by this type can't be found + */ + public boolean referencesClassExact() throws ClassNotFoundException { + JavaClass jc = Repository.lookupClass(class_name); + return jc.isClass(); + } + + + /** + * Return true if this type references an interface, + * false if it references a class. + * @return true if the type references an interface, false if + * it references a class + * @throws ClassNotFoundException if the class or interface + * referenced by this type can't be found + */ + public boolean referencesInterfaceExact() throws ClassNotFoundException { + JavaClass jc = Repository.lookupClass(class_name); + return !jc.isClass(); + } + + + /** + * Return true if this type is a subclass of given ObjectType. + * @throws ClassNotFoundException if any of this class's superclasses + * can't be found + */ + public boolean subclassOf( ObjectType superclass ) throws ClassNotFoundException { + if (this.referencesInterface() || superclass.referencesInterface()) { + return false; + } + return Repository.instanceOf(this.class_name, superclass.class_name); + } + + + /** + * Java Virtual Machine Specification edition 2, � 5.4.4 Access Control + * @throws ClassNotFoundException if the class referenced by this type + * can't be found + */ + public boolean accessibleTo( ObjectType accessor ) throws ClassNotFoundException { + JavaClass jc = Repository.lookupClass(class_name); + if (jc.isPublic()) { + return true; + } else { + JavaClass acc = Repository.lookupClass(accessor.class_name); + return acc.getPackageName().equals(jc.getPackageName()); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/POP.java b/java/org/apache/tomcat/util/bcel/generic/POP.java new file mode 100644 index 000000000..4ca24dc13 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/POP.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * POP - Pop top operand stack word + * + *
      Stack: ..., word -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class POP extends StackInstruction implements PopInstruction { + + public POP() { + super(org.apache.tomcat.util.bcel.Constants.POP); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitPopInstruction(this); + v.visitStackInstruction(this); + v.visitPOP(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/POP2.java b/java/org/apache/tomcat/util/bcel/generic/POP2.java new file mode 100644 index 000000000..ebfd6ad51 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/POP2.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * POP2 - Pop two top operand stack words + * + *
      Stack: ..., word2, word1 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class POP2 extends StackInstruction implements PopInstruction { + + public POP2() { + super(org.apache.tomcat.util.bcel.Constants.POP2); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitPopInstruction(this); + v.visitStackInstruction(this); + v.visitPOP2(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/PUSH.java b/java/org/apache/tomcat/util/bcel/generic/PUSH.java new file mode 100644 index 000000000..d5c1329b3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/PUSH.java @@ -0,0 +1,178 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Wrapper class for push operations, which are implemented either as BIPUSH, + * LDC or xCONST_n instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public final class PUSH implements CompoundInstruction, VariableLengthInstruction, + InstructionConstants { + + private Instruction instruction; + + + /** + * This constructor also applies for values of type short, char, byte + * + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, int value) { + if ((value >= -1) && (value <= 5)) { + instruction = INSTRUCTIONS[Constants.ICONST_0 + value]; + } else if ((value >= -128) && (value <= 127)) { + instruction = new BIPUSH((byte) value); + } else if ((value >= -32768) && (value <= 32767)) { + instruction = new SIPUSH((short) value); + } else { + instruction = new LDC(cp.addInteger(value)); + } + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, boolean value) { + instruction = INSTRUCTIONS[Constants.ICONST_0 + (value ? 1 : 0)]; + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, float value) { + if (value == 0.0) { + instruction = FCONST_0; + } else if (value == 1.0) { + instruction = FCONST_1; + } else if (value == 2.0) { + instruction = FCONST_2; + } else { + instruction = new LDC(cp.addFloat(value)); + } + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, long value) { + if (value == 0) { + instruction = LCONST_0; + } else if (value == 1) { + instruction = LCONST_1; + } else { + instruction = new LDC2_W(cp.addLong(value)); + } + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, double value) { + if (value == 0.0) { + instruction = DCONST_0; + } else if (value == 1.0) { + instruction = DCONST_1; + } else { + instruction = new LDC2_W(cp.addDouble(value)); + } + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, String value) { + if (value == null) { + instruction = ACONST_NULL; + } else { + instruction = new LDC(cp.addString(value)); + } + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, Number value) { + if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) { + instruction = new PUSH(cp, value.intValue()).instruction; + } else if (value instanceof Double) { + instruction = new PUSH(cp, value.doubleValue()).instruction; + } else if (value instanceof Float) { + instruction = new PUSH(cp, value.floatValue()).instruction; + } else if (value instanceof Long) { + instruction = new PUSH(cp, value.longValue()).instruction; + } else { + throw new ClassGenException("What's this: " + value); + } + } + + + /** + * creates a push object from a Character value. Warning: Make sure not to attempt to allow + * autoboxing to create this value parameter, as an alternative constructor will be called + * + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, Character value) { + this(cp, value.charValue()); + } + + + /** + * @param cp Constant pool + * @param value to be pushed + */ + public PUSH(ConstantPoolGen cp, Boolean value) { + this(cp, value.booleanValue()); + } + + + public final InstructionList getInstructionList() { + return new InstructionList(instruction); + } + + + public final Instruction getInstruction() { + return instruction; + } + + + /** + * @return mnemonic for instruction + */ + public String toString() { + return instruction.toString() + " (PUSH)"; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/PUTFIELD.java b/java/org/apache/tomcat/util/bcel/generic/PUTFIELD.java new file mode 100644 index 000000000..133e83636 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/PUTFIELD.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * PUTFIELD - Put field in object + *
      Stack: ..., objectref, value -> ...
      + * OR + *
      Stack: ..., objectref, value.word1, value.word2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class PUTFIELD extends FieldInstruction implements PopInstruction, ExceptionThrower { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + PUTFIELD() { + } + + + public PUTFIELD(int index) { + super(Constants.PUTFIELD, index); + } + + + public int consumeStack( ConstantPoolGen cpg ) { + return getFieldSize(cpg) + 1; + } + + + public Class[] getExceptions() { + Class[] cs = new Class[2 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length + 1] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.NULL_POINTER_EXCEPTION; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackConsumer(this); + v.visitPopInstruction(this); + v.visitTypedInstruction(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitFieldInstruction(this); + v.visitPUTFIELD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/PUTSTATIC.java b/java/org/apache/tomcat/util/bcel/generic/PUTSTATIC.java new file mode 100644 index 000000000..335791262 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/PUTSTATIC.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * PUTSTATIC - Put static field in class + *
      Stack: ..., value -> ...
      + * OR + *
      Stack: ..., value.word1, value.word2 -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class PUTSTATIC extends FieldInstruction implements ExceptionThrower, PopInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + PUTSTATIC() { + } + + + public PUTSTATIC(int index) { + super(Constants.PUTSTATIC, index); + } + + + public int consumeStack( ConstantPoolGen cpg ) { + return getFieldSize(cpg); + } + + + public Class[] getExceptions() { + Class[] cs = new Class[1 + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length]; + System.arraycopy(ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION, 0, cs, 0, + ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length); + cs[ExceptionConstants.EXCS_FIELD_AND_METHOD_RESOLUTION.length] = ExceptionConstants.INCOMPATIBLE_CLASS_CHANGE_ERROR; + return cs; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitStackConsumer(this); + v.visitPopInstruction(this); + v.visitTypedInstruction(this); + v.visitLoadClass(this); + v.visitCPInstruction(this); + v.visitFieldOrMethod(this); + v.visitFieldInstruction(this); + v.visitPUTSTATIC(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/PopInstruction.java b/java/org/apache/tomcat/util/bcel/generic/PopInstruction.java new file mode 100644 index 000000000..d3f5d708d --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/PopInstruction.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an unparameterized instruction to pop a value on top from the stack, + * such as ISTORE, POP, PUTSTATIC. + * + * @version $Id$ + * @author M. Dahm + * @see ISTORE + * @see POP + */ +public interface PopInstruction extends StackConsumer { +} diff --git a/java/org/apache/tomcat/util/bcel/generic/PushInstruction.java b/java/org/apache/tomcat/util/bcel/generic/PushInstruction.java new file mode 100644 index 000000000..e3525cbe7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/PushInstruction.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an unparameterized instruction to produce a value on top of the stack, + * such as ILOAD, LDC, SIPUSH, DUP, ICONST, etc. + * + * @version $Id$ + * @author M. Dahm + + * @see ILOAD + * @see ICONST + * @see LDC + * @see DUP + * @see SIPUSH + * @see GETSTATIC + */ +public interface PushInstruction extends StackProducer { +} diff --git a/java/org/apache/tomcat/util/bcel/generic/RET.java b/java/org/apache/tomcat/util/bcel/generic/RET.java new file mode 100644 index 000000000..7a14ed68f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/RET.java @@ -0,0 +1,139 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * RET - Return from subroutine + * + *
      Stack: ... -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class RET extends Instruction implements IndexedInstruction, TypedInstruction { + + private boolean wide; + private int index; // index to local variable containg the return address + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + RET() { + } + + + public RET(int index) { + super(org.apache.tomcat.util.bcel.Constants.RET, (short) 2); + setIndex(index); // May set wide as side effect + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + if (wide) { + out.writeByte(org.apache.tomcat.util.bcel.Constants.WIDE); + } + out.writeByte(opcode); + if (wide) { + out.writeShort(index); + } else { + out.writeByte(index); + } + } + + + private final void setWide() { + wide = index > org.apache.tomcat.util.bcel.Constants.MAX_BYTE; + if (wide) { + length = 4; // Including the wide byte + } else { + length = 2; + } + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + this.wide = wide; + if (wide) { + index = bytes.readUnsignedShort(); + length = 4; + } else { + index = bytes.readUnsignedByte(); + length = 2; + } + } + + + /** + * @return index of local variable containg the return address + */ + public final int getIndex() { + return index; + } + + + /** + * Set index of local variable containg the return address + */ + public final void setIndex( int n ) { + if (n < 0) { + throw new ClassGenException("Negative index value: " + n); + } + index = n; + setWide(); + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + index; + } + + + /** @return return address type + */ + public Type getType( ConstantPoolGen cp ) { + return ReturnaddressType.NO_TARGET; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitRET(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/RETURN.java b/java/org/apache/tomcat/util/bcel/generic/RETURN.java new file mode 100644 index 000000000..afb438b2c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/RETURN.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * RETURN - Return from void method + *
      Stack: ... -> <empty>
      + * + * @version $Id$ + * @author M. Dahm + */ +public class RETURN extends ReturnInstruction { + + public RETURN() { + super(org.apache.tomcat.util.bcel.Constants.RETURN); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitStackConsumer(this); + v.visitReturnInstruction(this); + v.visitRETURN(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ReferenceType.java b/java/org/apache/tomcat/util/bcel/generic/ReferenceType.java new file mode 100644 index 000000000..f9cab4c6e --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ReferenceType.java @@ -0,0 +1,330 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.Repository; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Super class for object and array types. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class ReferenceType extends Type { + + protected ReferenceType(byte t, String s) { + super(t, s); + } + + + /** Class is non-abstract but not instantiable from the outside + */ + ReferenceType() { + super(Constants.T_OBJECT, ""); + } + + + /** + * Return true iff this type is castable to another type t as defined in + * the JVM specification. The case where this is Type.NULL is not + * defined (see the CHECKCAST definition in the JVM specification). + * However, because e.g. CHECKCAST doesn't throw a + * ClassCastException when casting a null reference to any Object, + * true is returned in this case. + * + * @throws ClassNotFoundException if any classes or interfaces required + * to determine assignment compatibility can't be found + */ + public boolean isCastableTo( Type t ) throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return true; // If this is ever changed in isAssignmentCompatible() + } + return isAssignmentCompatibleWith(t); + /* Yes, it's true: It's the same definition. + * See vmspec2 AASTORE / CHECKCAST definitions. + */ + } + + + /** + * Return true iff this is assignment compatible with another type t + * as defined in the JVM specification; see the AASTORE definition + * there. + * @throws ClassNotFoundException if any classes or interfaces required + * to determine assignment compatibility can't be found + */ + public boolean isAssignmentCompatibleWith( Type t ) throws ClassNotFoundException { + if (!(t instanceof ReferenceType)) { + return false; + } + ReferenceType T = (ReferenceType) t; + if (this.equals(Type.NULL)) { + return true; // This is not explicitely stated, but clear. Isn't it? + } + /* If this is a class type then + */ + if ((this instanceof ObjectType) && (((ObjectType) this).referencesClassExact())) { + /* If T is a class type, then this must be the same class as T, + or this must be a subclass of T; + */ + if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { + if (this.equals(T)) { + return true; + } + if (Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T) + .getClassName())) { + return true; + } + } + /* If T is an interface type, this must implement interface T. + */ + if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { + if (Repository.implementationOf(((ObjectType) this).getClassName(), + ((ObjectType) T).getClassName())) { + return true; + } + } + } + /* If this is an interface type, then: + */ + if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterfaceExact())) { + /* If T is a class type, then T must be Object (�2.4.7). + */ + if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { + if (T.equals(Type.OBJECT)) { + return true; + } + } + /* If T is an interface type, then T must be the same interface + * as this or a superinterface of this (�2.13.2). + */ + if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { + if (this.equals(T)) { + return true; + } + if (Repository.implementationOf(((ObjectType) this).getClassName(), + ((ObjectType) T).getClassName())) { + return true; + } + } + } + /* If this is an array type, namely, the type SC[], that is, an + * array of components of type SC, then: + */ + if (this instanceof ArrayType) { + /* If T is a class type, then T must be Object (�2.4.7). + */ + if ((T instanceof ObjectType) && (((ObjectType) T).referencesClassExact())) { + if (T.equals(Type.OBJECT)) { + return true; + } + } + /* If T is an array type TC[], that is, an array of components + * of type TC, then one of the following must be true: + */ + if (T instanceof ArrayType) { + /* TC and SC are the same primitive type (�2.4.1). + */ + Type sc = ((ArrayType) this).getElementType(); + Type tc = ((ArrayType) T).getElementType(); + if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc)) { + return true; + } + /* TC and SC are reference types (�2.4.6), and type SC is + * assignable to TC by these runtime rules. + */ + if (tc instanceof ReferenceType && sc instanceof ReferenceType + && ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) { + return true; + } + } + /* If T is an interface type, T must be one of the interfaces implemented by arrays (�2.15). */ + // TODO: Check if this is still valid or find a way to dynamically find out which + // interfaces arrays implement. However, as of the JVM specification edition 2, there + // are at least two different pages where assignment compatibility is defined and + // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or + // 'java.io.Serializable'" + if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterfaceExact())) { + for (int ii = 0; ii < Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++) { + if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) { + return true; + } + } + } + } + return false; // default. + } + + + /** + * This commutative operation returns the first common superclass (narrowest ReferenceType + * referencing a class, not an interface). + * If one of the types is a superclass of the other, the former is returned. + * If "this" is Type.NULL, then t is returned. + * If t is Type.NULL, then "this" is returned. + * If "this" equals t ['this.equals(t)'] "this" is returned. + * If "this" or t is an ArrayType, then Type.OBJECT is returned; + * unless their dimensions match. Then an ArrayType of the same + * number of dimensions is returned, with its basic type being the + * first common super class of the basic types of "this" and t. + * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. + * If not all of the two classes' superclasses cannot be found, "null" is returned. + * See the JVM specification edition 2, "�4.9.2 The Bytecode Verifier". + * + * @throws ClassNotFoundException on failure to find superclasses of this + * type, or the type passed as a parameter + */ + public ReferenceType getFirstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return t; + } + if (t.equals(Type.NULL)) { + return this; + } + if (this.equals(t)) { + return this; + /* + * TODO: Above sounds a little arbitrary. On the other hand, there is + * no object referenced by Type.NULL so we can also say all the objects + * referenced by Type.NULL were derived from java.lang.Object. + * However, the Java Language's "instanceof" operator proves us wrong: + * "null" is not referring to an instance of java.lang.Object :) + */ + } + /* This code is from a bug report by Konstantin Shagin */ + if ((this instanceof ArrayType) && (t instanceof ArrayType)) { + ArrayType arrType1 = (ArrayType) this; + ArrayType arrType2 = (ArrayType) t; + if ((arrType1.getDimensions() == arrType2.getDimensions()) + && arrType1.getBasicType() instanceof ObjectType + && arrType2.getBasicType() instanceof ObjectType) { + return new ArrayType(((ObjectType) arrType1.getBasicType()) + .getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()), arrType1 + .getDimensions()); + } + } + if ((this instanceof ArrayType) || (t instanceof ArrayType)) { + return Type.OBJECT; + // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + } + if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) + || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) { + return Type.OBJECT; + // TODO: The above line is correct comparing to the vmspec2. But one could + // make class file verification a bit stronger here by using the notion of + // superinterfaces or even castability or assignment compatibility. + } + // this and t are ObjectTypes, see above. + ObjectType thiz = (ObjectType) this; + ObjectType other = (ObjectType) t; + JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName()); + JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName()); + if ((thiz_sups == null) || (other_sups == null)) { + return null; + } + // Waaahh... + JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1]; + JavaClass[] t_sups = new JavaClass[other_sups.length + 1]; + System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length); + System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length); + this_sups[0] = Repository.lookupClass(thiz.getClassName()); + t_sups[0] = Repository.lookupClass(other.getClassName()); + for (int i = 0; i < t_sups.length; i++) { + for (int j = 0; j < this_sups.length; j++) { + if (this_sups[j].equals(t_sups[i])) { + return new ObjectType(this_sups[j].getClassName()); + } + } + } + // Huh? Did you ask for Type.OBJECT's superclass?? + return null; + } + + + /** + * This commutative operation returns the first common superclass (narrowest ReferenceType + * referencing a class, not an interface). + * If one of the types is a superclass of the other, the former is returned. + * If "this" is Type.NULL, then t is returned. + * If t is Type.NULL, then "this" is returned. + * If "this" equals t ['this.equals(t)'] "this" is returned. + * If "this" or t is an ArrayType, then Type.OBJECT is returned. + * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. + * If not all of the two classes' superclasses cannot be found, "null" is returned. + * See the JVM specification edition 2, "�4.9.2 The Bytecode Verifier". + * + * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has + * slightly changed semantics. + * @throws ClassNotFoundException on failure to find superclasses of this + * type, or the type passed as a parameter + */ + public ReferenceType firstCommonSuperclass( ReferenceType t ) throws ClassNotFoundException { + if (this.equals(Type.NULL)) { + return t; + } + if (t.equals(Type.NULL)) { + return this; + } + if (this.equals(t)) { + return this; + /* + * TODO: Above sounds a little arbitrary. On the other hand, there is + * no object referenced by Type.NULL so we can also say all the objects + * referenced by Type.NULL were derived from java.lang.Object. + * However, the Java Language's "instanceof" operator proves us wrong: + * "null" is not referring to an instance of java.lang.Object :) + */ + } + if ((this instanceof ArrayType) || (t instanceof ArrayType)) { + return Type.OBJECT; + // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + } + if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) + || ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface())) { + return Type.OBJECT; + // TODO: The above line is correct comparing to the vmspec2. But one could + // make class file verification a bit stronger here by using the notion of + // superinterfaces or even castability or assignment compatibility. + } + // this and t are ObjectTypes, see above. + ObjectType thiz = (ObjectType) this; + ObjectType other = (ObjectType) t; + JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName()); + JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName()); + if ((thiz_sups == null) || (other_sups == null)) { + return null; + } + // Waaahh... + JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1]; + JavaClass[] t_sups = new JavaClass[other_sups.length + 1]; + System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length); + System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length); + this_sups[0] = Repository.lookupClass(thiz.getClassName()); + t_sups[0] = Repository.lookupClass(other.getClassName()); + for (int i = 0; i < t_sups.length; i++) { + for (int j = 0; j < this_sups.length; j++) { + if (this_sups[j].equals(t_sups[i])) { + return new ObjectType(this_sups[j].getClassName()); + } + } + } + // Huh? Did you ask for Type.OBJECT's superclass?? + return null; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ReturnInstruction.java b/java/org/apache/tomcat/util/bcel/generic/ReturnInstruction.java new file mode 100644 index 000000000..63eba5622 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ReturnInstruction.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.ExceptionConstants; + +/** + * Super class for the xRETURN family of instructions. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class ReturnInstruction extends Instruction implements ExceptionThrower, + TypedInstruction, StackConsumer { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + ReturnInstruction() { + } + + + /** + * @param opcode of instruction + */ + protected ReturnInstruction(short opcode) { + super(opcode, (short) 1); + } + + + public Type getType() { + switch (opcode) { + case Constants.IRETURN: + return Type.INT; + case Constants.LRETURN: + return Type.LONG; + case Constants.FRETURN: + return Type.FLOAT; + case Constants.DRETURN: + return Type.DOUBLE; + case Constants.ARETURN: + return Type.OBJECT; + case Constants.RETURN: + return Type.VOID; + default: // Never reached + throw new ClassGenException("Unknown type " + opcode); + } + } + + + public Class[] getExceptions() { + return new Class[] { + ExceptionConstants.ILLEGAL_MONITOR_STATE + }; + } + + + /** @return type associated with the instruction + */ + public Type getType( ConstantPoolGen cp ) { + return getType(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/ReturnaddressType.java b/java/org/apache/tomcat/util/bcel/generic/ReturnaddressType.java new file mode 100644 index 000000000..aacf3e88a --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/ReturnaddressType.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import org.apache.tomcat.util.bcel.Constants; + +/** + * Returnaddress, the type JSR or JSR_W instructions push upon the stack. + * + * see vmspec2 �3.3.3 + * @version $Id$ + * @author Enver Haase + */ +public class ReturnaddressType extends Type { + + public static final ReturnaddressType NO_TARGET = new ReturnaddressType(); + private InstructionHandle returnTarget; + + + /** + * A Returnaddress [that doesn't know where to return to]. + */ + private ReturnaddressType() { + super(Constants.T_ADDRESS, ""); + } + + + /** + * Creates a ReturnaddressType object with a target. + */ + public ReturnaddressType(InstructionHandle returnTarget) { + super(Constants.T_ADDRESS, ""); + this.returnTarget = returnTarget; + } + + + /** @return a hash code value for the object. + */ + public int hashCode() { + if (returnTarget == null) { + return 0; + } + return returnTarget.hashCode(); + } + + + /** + * Returns if the two Returnaddresses refer to the same target. + */ + public boolean equals( Object rat ) { + if (!(rat instanceof ReturnaddressType)) { + return false; + } + ReturnaddressType that = (ReturnaddressType) rat; + if (this.returnTarget == null || that.returnTarget == null) { + return that.returnTarget == this.returnTarget; + } + return that.returnTarget.equals(this.returnTarget); + } + + + /** + * @return the target of this ReturnaddressType + */ + public InstructionHandle getTarget() { + return returnTarget; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SALOAD.java b/java/org/apache/tomcat/util/bcel/generic/SALOAD.java new file mode 100644 index 000000000..bf7a69f9f --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SALOAD.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * SALOAD - Load short from array + *
      Stack: ..., arrayref, index -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class SALOAD extends ArrayInstruction implements StackProducer { + + public SALOAD() { + super(org.apache.tomcat.util.bcel.Constants.SALOAD); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackProducer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitSALOAD(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SASTORE.java b/java/org/apache/tomcat/util/bcel/generic/SASTORE.java new file mode 100644 index 000000000..f6908f783 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SASTORE.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * SASTORE - Store into short array + *
      Stack: ..., arrayref, index, value -> ...
      + * + * @version $Id$ + * @author M. Dahm + */ +public class SASTORE extends ArrayInstruction implements StackConsumer { + + public SASTORE() { + super(org.apache.tomcat.util.bcel.Constants.SASTORE); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitExceptionThrower(this); + v.visitTypedInstruction(this); + v.visitArrayInstruction(this); + v.visitSASTORE(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SIPUSH.java b/java/org/apache/tomcat/util/bcel/generic/SIPUSH.java new file mode 100644 index 000000000..890d8dd51 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SIPUSH.java @@ -0,0 +1,103 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * SIPUSH - Push short + * + *
      Stack: ... -> ..., value
      + * + * @version $Id$ + * @author M. Dahm + */ +public class SIPUSH extends Instruction implements ConstantPushInstruction { + + private short b; + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + SIPUSH() { + } + + + public SIPUSH(short b) { + super(org.apache.tomcat.util.bcel.Constants.SIPUSH, (short) 3); + this.b = b; + } + + + /** + * Dump instruction as short code to stream out. + */ + public void dump( DataOutputStream out ) throws IOException { + super.dump(out); + out.writeShort(b); + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + return super.toString(verbose) + " " + b; + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + length = 3; + b = bytes.readShort(); + } + + + public Number getValue() { + return new Integer(b); + } + + + /** @return Type.SHORT + */ + public Type getType( ConstantPoolGen cp ) { + return Type.SHORT; + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitPushInstruction(this); + v.visitStackProducer(this); + v.visitTypedInstruction(this); + v.visitConstantPushInstruction(this); + v.visitSIPUSH(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SWAP.java b/java/org/apache/tomcat/util/bcel/generic/SWAP.java new file mode 100644 index 000000000..71ced1366 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SWAP.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * SWAP - Swa top operand stack word + *
      Stack: ..., word2, word1 -> ..., word1, word2
      + * + * @version $Id$ + * @author M. Dahm + */ +public class SWAP extends StackInstruction implements StackConsumer, StackProducer { + + public SWAP() { + super(org.apache.tomcat.util.bcel.Constants.SWAP); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitStackProducer(this); + v.visitStackInstruction(this); + v.visitSWAP(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SWITCH.java b/java/org/apache/tomcat/util/bcel/generic/SWITCH.java new file mode 100644 index 000000000..b9ea7e0b4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SWITCH.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or + * TABLESWITCH instruction, depending on whether the match values (int[]) can be + * sorted with no gaps between the numbers. + * + * @version $Id$ + * @author M. Dahm + */ +public final class SWITCH implements CompoundInstruction { + + private int[] match; + private InstructionHandle[] targets; + private Select instruction; + private int match_length; + + + /** + * Template for switch() constructs. If the match array can be + * sorted in ascending order with gaps no larger than max_gap + * between the numbers, a TABLESWITCH instruction is generated, and + * a LOOKUPSWITCH otherwise. The former may be more efficient, but + * needs more space. + * + * Note, that the key array always will be sorted, though we leave + * the original arrays unaltered. + * + * @param match array of match values (case 2: ... case 7: ..., etc.) + * @param targets the instructions to be branched to for each case + * @param target the default target + * @param max_gap maximum gap that may between case branches + */ + public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target, int max_gap) { + this.match = (int[]) match.clone(); + this.targets = (InstructionHandle[]) targets.clone(); + if ((match_length = match.length) < 2) { + instruction = new TABLESWITCH(match, targets, target); + } else { + sort(0, match_length - 1); + if (matchIsOrdered(max_gap)) { + fillup(max_gap, target); + instruction = new TABLESWITCH(this.match, this.targets, target); + } else { + instruction = new LOOKUPSWITCH(this.match, this.targets, target); + } + } + } + + + public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target) { + this(match, targets, target, 1); + } + + + private final void fillup( int max_gap, InstructionHandle target ) { + int max_size = match_length + match_length * max_gap; + int[] m_vec = new int[max_size]; + InstructionHandle[] t_vec = new InstructionHandle[max_size]; + int count = 1; + m_vec[0] = match[0]; + t_vec[0] = targets[0]; + for (int i = 1; i < match_length; i++) { + int prev = match[i - 1]; + int gap = match[i] - prev; + for (int j = 1; j < gap; j++) { + m_vec[count] = prev + j; + t_vec[count] = target; + count++; + } + m_vec[count] = match[i]; + t_vec[count] = targets[i]; + count++; + } + match = new int[count]; + targets = new InstructionHandle[count]; + System.arraycopy(m_vec, 0, match, 0, count); + System.arraycopy(t_vec, 0, targets, 0, count); + } + + + /** + * Sort match and targets array with QuickSort. + */ + private final void sort( int l, int r ) { + int i = l, j = r; + int h, m = match[(l + r) / 2]; + InstructionHandle h2; + do { + while (match[i] < m) { + i++; + } + while (m < match[j]) { + j--; + } + if (i <= j) { + h = match[i]; + match[i] = match[j]; + match[j] = h; // Swap elements + h2 = targets[i]; + targets[i] = targets[j]; + targets[j] = h2; // Swap instructions, too + i++; + j--; + } + } while (i <= j); + if (l < j) { + sort(l, j); + } + if (i < r) { + sort(i, r); + } + } + + + /** + * @return match is sorted in ascending order with no gap bigger than max_gap? + */ + private final boolean matchIsOrdered( int max_gap ) { + for (int i = 1; i < match_length; i++) { + if (match[i] - match[i - 1] > max_gap) { + return false; + } + } + return true; + } + + + public final InstructionList getInstructionList() { + return new InstructionList(instruction); + } + + + public final Instruction getInstruction() { + return instruction; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/Select.java b/java/org/apache/tomcat/util/bcel/generic/Select.java new file mode 100644 index 000000000..aef247c2b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/Select.java @@ -0,0 +1,236 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions. + * + *

      We use our super's target property as the default target. + * + * @version $Id$ + * @author M. Dahm + * @see LOOKUPSWITCH + * @see TABLESWITCH + * @see InstructionList + */ +public abstract class Select extends BranchInstruction implements VariableLengthInstruction, + StackProducer { + + protected int[] match; // matches, i.e., case 1: ... + protected int[] indices; // target offsets + protected InstructionHandle[] targets; // target objects in instruction list + protected int fixed_length; // fixed length defined by subclasses + protected int match_length; // number of cases + protected int padding = 0; // number of pad bytes for alignment + + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + Select() { + } + + + /** + * (Match, target) pairs for switch. + * `Match' and `targets' must have the same length of course. + * + * @param match array of matching values + * @param targets instruction targets + * @param defaultTarget default instruction target + */ + Select(short opcode, int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) { + super(opcode, defaultTarget); + this.targets = targets; + for (int i = 0; i < targets.length; i++) { + notifyTarget(null, targets[i], this); + } + this.match = match; + if ((match_length = match.length) != targets.length) { + throw new ClassGenException("Match and target array have not the same length: Match length: " + match.length + " Target length: " + targets.length); + } + indices = new int[match_length]; + } + + + /** + * Since this is a variable length instruction, it may shift the following + * instructions which then need to update their position. + * + * Called by InstructionList.setPositions when setting the position for every + * instruction. In the presence of variable length instructions `setPositions' + * performs multiple passes over the instruction list to calculate the + * correct (byte) positions and offsets by calling this function. + * + * @param offset additional offset caused by preceding (variable length) instructions + * @param max_offset the maximum offset that may be caused by these instructions + * @return additional offset caused by possible change of this instruction's length + */ + protected int updatePosition( int offset, int max_offset ) { + position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc. + short old_length = length; + /* Alignment on 4-byte-boundary, + 1, because of tag byte. + */ + padding = (4 - ((position + 1) % 4)) % 4; + length = (short) (fixed_length + padding); // Update length + return length - old_length; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + out.writeByte(opcode); + for (int i = 0; i < padding; i++) { + out.writeByte(0); + } + index = getTargetOffset(); // Write default target offset + out.writeInt(index); + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes + for (int i = 0; i < padding; i++) { + bytes.readByte(); + } + // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH) + index = bytes.readInt(); + } + + + /** + * @return mnemonic for instruction + */ + public String toString( boolean verbose ) { + StringBuffer buf = new StringBuffer(super.toString(verbose)); + if (verbose) { + for (int i = 0; i < match_length; i++) { + String s = "null"; + if (targets[i] != null) { + s = targets[i].getInstruction().toString(); + } + buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append( + indices[i]).append("})"); + } + } else { + buf.append(" ..."); + } + return buf.toString(); + } + + + /** + * Set branch target for `i'th case + */ + public void setTarget( int i, InstructionHandle target ) { + notifyTarget(targets[i], target, this); + targets[i] = target; + } + + + /** + * @param old_ih old target + * @param new_ih new target + */ + public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) { + boolean targeted = false; + if (target == old_ih) { + targeted = true; + setTarget(new_ih); + } + for (int i = 0; i < targets.length; i++) { + if (targets[i] == old_ih) { + targeted = true; + setTarget(i, new_ih); + } + } + if (!targeted) { + throw new ClassGenException("Not targeting " + old_ih); + } + } + + + /** + * @return true, if ih is target of this instruction + */ + public boolean containsTarget( InstructionHandle ih ) { + if (target == ih) { + return true; + } + for (int i = 0; i < targets.length; i++) { + if (targets[i] == ih) { + return true; + } + } + return false; + } + + + protected Object clone() throws CloneNotSupportedException { + Select copy = (Select) super.clone(); + copy.match = (int[]) match.clone(); + copy.indices = (int[]) indices.clone(); + copy.targets = (InstructionHandle[]) targets.clone(); + return copy; + } + + + /** + * Inform targets that they're not targeted anymore. + */ + void dispose() { + super.dispose(); + for (int i = 0; i < targets.length; i++) { + targets[i].removeTargeter(this); + } + } + + + /** + * @return array of match indices + */ + public int[] getMatchs() { + return match; + } + + + /** + * @return array of match target offsets + */ + public int[] getIndices() { + return indices; + } + + + /** + * @return array of match targets + */ + public InstructionHandle[] getTargets() { + return targets; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/SimpleElementValueGen.java b/java/org/apache/tomcat/util/bcel/generic/SimpleElementValueGen.java new file mode 100644 index 000000000..e1ae11b2b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/SimpleElementValueGen.java @@ -0,0 +1,245 @@ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.classfile.ConstantDouble; +import org.apache.tomcat.util.bcel.classfile.ConstantFloat; +import org.apache.tomcat.util.bcel.classfile.ConstantInteger; +import org.apache.tomcat.util.bcel.classfile.ConstantLong; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ElementValue; +import org.apache.tomcat.util.bcel.classfile.SimpleElementValue; + +public class SimpleElementValueGen extends ElementValueGen +{ + // For primitive types and string type, this points to the value entry in + // the cpGen + // For 'class' this points to the class entry in the cpGen + private int idx; + + // ctors for each supported type... type could be inferred but for now lets + // force it to be passed + /** + * Protected ctor used for deserialization, doesn't *put* an entry in the + * constant pool, assumes the one at the supplied index is correct. + */ + protected SimpleElementValueGen(int type, int idx, ConstantPoolGen cpGen) + { + super(type, cpGen); + this.idx = idx; + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, int value) + { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, long value) + { + super(type, cpGen); + idx = cpGen.addLong(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, double value) + { + super(type, cpGen); + idx = cpGen.addDouble(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, float value) + { + super(type, cpGen); + idx = cpGen.addFloat(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, short value) + { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, byte value) + { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, char value) + { + super(type, cpGen); + idx = cpGen.addInteger(value); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, boolean value) + { + super(type, cpGen); + if (value) + idx = cpGen.addInteger(1); + else + idx = cpGen.addInteger(0); + } + + public SimpleElementValueGen(int type, ConstantPoolGen cpGen, String value) + { + super(type, cpGen); + idx = cpGen.addUtf8(value); + } + + /** + * The boolean controls whether we copy info from the 'old' constant pool to + * the 'new'. You need to use this ctor if the annotation is being copied + * from one file to another. + */ + public SimpleElementValueGen(SimpleElementValue value, + ConstantPoolGen cpool, boolean copyPoolEntries) + { + super(value.getElementValueType(), cpool); + if (!copyPoolEntries) + { + // J5ASSERT: Could assert value.stringifyValue() is the same as + // cpool.getConstant(SimpleElementValuevalue.getIndex()) + idx = value.getIndex(); + } + else + { + switch (value.getElementValueType()) + { + case STRING: + idx = cpool.addUtf8(value.getValueString()); + break; + case PRIMITIVE_INT: + idx = cpool.addInteger(value.getValueInt()); + break; + case PRIMITIVE_BYTE: + idx = cpool.addInteger(value.getValueByte()); + break; + case PRIMITIVE_CHAR: + idx = cpool.addInteger(value.getValueChar()); + break; + case PRIMITIVE_LONG: + idx = cpool.addLong(value.getValueLong()); + break; + case PRIMITIVE_FLOAT: + idx = cpool.addFloat(value.getValueFloat()); + break; + case PRIMITIVE_DOUBLE: + idx = cpool.addDouble(value.getValueDouble()); + break; + case PRIMITIVE_BOOLEAN: + if (value.getValueBoolean()) + { + idx = cpool.addInteger(1); + } + else + { + idx = cpool.addInteger(0); + } + break; + case PRIMITIVE_SHORT: + idx = cpool.addInteger(value.getValueShort()); + break; + default: + throw new RuntimeException( + "SimpleElementValueGen class does not know how " + + "to copy this type " + type); + } + } + } + + /** + * Return immutable variant + */ + public ElementValue getElementValue() + { + return new SimpleElementValue(type, idx, cpGen.getConstantPool()); + } + + public int getIndex() + { + return idx; + } + + public String getValueString() + { + if (type != STRING) + throw new RuntimeException( + "Dont call getValueString() on a non STRING ElementValue"); + ConstantUtf8 c = (ConstantUtf8) cpGen.getConstant(idx); + return c.getBytes(); + } + + public int getValueInt() + { + if (type != PRIMITIVE_INT) + throw new RuntimeException( + "Dont call getValueString() on a non STRING ElementValue"); + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx); + return c.getBytes(); + } + + // Whatever kind of value it is, return it as a string + public String stringifyValue() + { + switch (type) + { + case PRIMITIVE_INT: + ConstantInteger c = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(c.getBytes()); + case PRIMITIVE_LONG: + ConstantLong j = (ConstantLong) cpGen.getConstant(idx); + return Long.toString(j.getBytes()); + case PRIMITIVE_DOUBLE: + ConstantDouble d = (ConstantDouble) cpGen.getConstant(idx); + return Double.toString(d.getBytes()); + case PRIMITIVE_FLOAT: + ConstantFloat f = (ConstantFloat) cpGen.getConstant(idx); + return Float.toString(f.getBytes()); + case PRIMITIVE_SHORT: + ConstantInteger s = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(s.getBytes()); + case PRIMITIVE_BYTE: + ConstantInteger b = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(b.getBytes()); + case PRIMITIVE_CHAR: + ConstantInteger ch = (ConstantInteger) cpGen.getConstant(idx); + return Integer.toString(ch.getBytes()); + case PRIMITIVE_BOOLEAN: + ConstantInteger bo = (ConstantInteger) cpGen.getConstant(idx); + if (bo.getBytes() == 0) + return "false"; + if (bo.getBytes() != 0) + return "true"; + case STRING: + ConstantUtf8 cu8 = (ConstantUtf8) cpGen.getConstant(idx); + return cu8.getBytes(); + default: + throw new RuntimeException( + "SimpleElementValueGen class does not know how to stringify type " + + type); + } + } + + public void dump(DataOutputStream dos) throws IOException + { + dos.writeByte(type); // u1 kind of value + switch (type) + { + case PRIMITIVE_INT: + case PRIMITIVE_BYTE: + case PRIMITIVE_CHAR: + case PRIMITIVE_FLOAT: + case PRIMITIVE_LONG: + case PRIMITIVE_BOOLEAN: + case PRIMITIVE_SHORT: + case PRIMITIVE_DOUBLE: + case STRING: + dos.writeShort(idx); + break; + default: + throw new RuntimeException( + "SimpleElementValueGen doesnt know how to write out type " + + type); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/StackConsumer.java b/java/org/apache/tomcat/util/bcel/generic/StackConsumer.java new file mode 100644 index 000000000..990f5757b --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/StackConsumer.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote an instruction that may consume a value from the stack. + * + * @version $Id$ + * @author M. Dahm + */ +public interface StackConsumer { + + /** @return how many words are consumed from stack + */ + public int consumeStack( ConstantPoolGen cpg ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/StackInstruction.java b/java/org/apache/tomcat/util/bcel/generic/StackInstruction.java new file mode 100644 index 000000000..5d7bf76fb --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/StackInstruction.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Super class for stack operations like DUP and POP. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class StackInstruction extends Instruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + StackInstruction() { + } + + + /** + * @param opcode instruction opcode + */ + protected StackInstruction(short opcode) { + super(opcode, (short) 1); + } + + + /** @return Type.UNKNOWN + */ + public Type getType( ConstantPoolGen cp ) { + return Type.UNKNOWN; + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/StackProducer.java b/java/org/apache/tomcat/util/bcel/generic/StackProducer.java new file mode 100644 index 000000000..04a32beb9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/StackProducer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denote an instruction that may produce a value on top of the stack + * (this excludes DUP_X1, e.g.) + * + * @version $Id$ + * @author M. Dahm + */ +public interface StackProducer { + + /** @return how many words are produced on stack + */ + public int produceStack( ConstantPoolGen cpg ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/StoreInstruction.java b/java/org/apache/tomcat/util/bcel/generic/StoreInstruction.java new file mode 100644 index 000000000..6ce354f43 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/StoreInstruction.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an unparameterized instruction to store a value into a local variable, + * e.g. ISTORE. + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class StoreInstruction extends LocalVariableInstruction implements PopInstruction { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + * tag and length are defined in readInstruction and initFromFile, respectively. + */ + StoreInstruction(short canon_tag, short c_tag) { + super(canon_tag, c_tag); + } + + + /** + * @param opcode Instruction opcode + * @param c_tag Instruction number for compact version, ASTORE_0, e.g. + * @param n local variable index (unsigned short) + */ + protected StoreInstruction(short opcode, short c_tag, int n) { + super(opcode, c_tag, n); + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitStackConsumer(this); + v.visitPopInstruction(this); + v.visitTypedInstruction(this); + v.visitLocalVariableInstruction(this); + v.visitStoreInstruction(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/TABLESWITCH.java b/java/org/apache/tomcat/util/bcel/generic/TABLESWITCH.java new file mode 100644 index 000000000..15a3f5bd5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/TABLESWITCH.java @@ -0,0 +1,107 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.io.DataOutputStream; +import java.io.IOException; +import org.apache.tomcat.util.bcel.util.ByteSequence; + +/** + * TABLESWITCH - Switch within given range of values, i.e., low..high + * + * @version $Id$ + * @author M. Dahm + * @see SWITCH + */ +public class TABLESWITCH extends Select { + + /** + * Empty constructor needed for the Class.newInstance() statement in + * Instruction.readInstruction(). Not to be used otherwise. + */ + TABLESWITCH() { + } + + + /** + * @param match sorted array of match values, match[0] must be low value, + * match[match_length - 1] high value + * @param targets where to branch for matched values + * @param defaultTarget default branch + */ + public TABLESWITCH(int[] match, InstructionHandle[] targets, InstructionHandle defaultTarget) { + super(org.apache.tomcat.util.bcel.Constants.TABLESWITCH, match, targets, defaultTarget); + length = (short) (13 + match_length * 4); /* Alignment remainder assumed + * 0 here, until dump time */ + fixed_length = length; + } + + + /** + * Dump instruction as byte code to stream out. + * @param out Output stream + */ + public void dump( DataOutputStream out ) throws IOException { + super.dump(out); + int low = (match_length > 0) ? match[0] : 0; + out.writeInt(low); + int high = (match_length > 0) ? match[match_length - 1] : 0; + out.writeInt(high); + for (int i = 0; i < match_length; i++) { + out.writeInt(indices[i] = getTargetOffset(targets[i])); + } + } + + + /** + * Read needed data (e.g. index) from file. + */ + protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException { + super.initFromFile(bytes, wide); + int low = bytes.readInt(); + int high = bytes.readInt(); + match_length = high - low + 1; + fixed_length = (short) (13 + match_length * 4); + length = (short) (fixed_length + padding); + match = new int[match_length]; + indices = new int[match_length]; + targets = new InstructionHandle[match_length]; + for (int i = low; i <= high; i++) { + match[i - low] = i; + } + for (int i = 0; i < match_length; i++) { + indices[i] = bytes.readInt(); + } + } + + + /** + * Call corresponding visitor method(s). The order is: + * Call visitor methods of implemented interfaces first, then + * call methods according to the class hierarchy in descending order, + * i.e., the most specific visitXXX() call comes last. + * + * @param v Visitor object + */ + public void accept( Visitor v ) { + v.visitVariableLengthInstruction(this); + v.visitStackProducer(this); + v.visitBranchInstruction(this); + v.visitSelect(this); + v.visitTABLESWITCH(this); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/TargetLostException.java b/java/org/apache/tomcat/util/bcel/generic/TargetLostException.java new file mode 100644 index 000000000..dd7c993ed --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/TargetLostException.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Thrown by InstructionList.remove() when one or multiple disposed instruction + * are still being referenced by a InstructionTargeter object. I.e. the + * InstructionTargeter has to be notified that (one of) the InstructionHandle it + * is referencing is being removed from the InstructionList and thus not valid anymore. + * + * Making this an exception instead of a return value forces the user to handle + * these case explicitely in a try { ... } catch. The following code illustrates + * how this may be done: + * + *

      + *     ...
      + *     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);
      + *       }
      + *     }
      + * 
      + * + * @see InstructionHandle + * @see InstructionList + * @see InstructionTargeter + * @version $Id$ + * @author M. Dahm + */ +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/java/org/apache/tomcat/util/bcel/generic/Type.java b/java/org/apache/tomcat/util/bcel/generic/Type.java new file mode 100644 index 000000000..1c5d51310 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/Type.java @@ -0,0 +1,369 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +import java.util.ArrayList; +import java.util.List; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.ClassFormatException; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Abstract super class for all possible java types, namely basic types + * such as int, object types like String and array types, e.g. int[] + * + * @version $Id$ + * @author M. Dahm + */ +public abstract class Type implements java.io.Serializable { + + protected byte type; + protected String signature; // signature for the type + /** Predefined constants + */ + public static final BasicType VOID = new BasicType(Constants.T_VOID); + public static final BasicType BOOLEAN = new BasicType(Constants.T_BOOLEAN); + public static final BasicType INT = new BasicType(Constants.T_INT); + public static final BasicType SHORT = new BasicType(Constants.T_SHORT); + public static final BasicType BYTE = new BasicType(Constants.T_BYTE); + public static final BasicType LONG = new BasicType(Constants.T_LONG); + public static final BasicType DOUBLE = new BasicType(Constants.T_DOUBLE); + public static final BasicType FLOAT = new BasicType(Constants.T_FLOAT); + public static final BasicType CHAR = new BasicType(Constants.T_CHAR); + public static final ObjectType OBJECT = new ObjectType("java.lang.Object"); + public static final ObjectType CLASS = new ObjectType("java.lang.Class"); + public static final ObjectType STRING = new ObjectType("java.lang.String"); + public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer"); + public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable"); + public static final Type[] NO_ARGS = new Type[0]; + public static final ReferenceType NULL = new ReferenceType() { + }; + public static final Type UNKNOWN = new Type(Constants.T_UNKNOWN, "") { + }; + + + protected Type(byte t, String s) { + type = t; + signature = s; + } + + + /** + * @return hashcode of Type + */ + public int hashCode() { + return type ^ signature.hashCode(); + } + + + /** + * @return whether the Types are equal + */ + public boolean equals(Object o) { + if (o instanceof Type) { + Type t = (Type)o; + return (type == t.type) && signature.equals(t.signature); + } + return false; + } + + + /** + * @return signature for given type. + */ + public String getSignature() { + return signature; + } + + + /** + * @return type as defined in Constants + */ + public byte getType() { + return type; + } + + + /** + * @return stack size of this type (2 for long and double, 0 for void, 1 otherwise) + */ + public int getSize() { + switch (type) { + case Constants.T_DOUBLE: + case Constants.T_LONG: + return 2; + case Constants.T_VOID: + return 0; + default: + return 1; + } + } + + + /** + * @return Type string, e.g. `int[]' + */ + public String toString() { + return ((this.equals(Type.NULL) || (type >= Constants.T_UNKNOWN))) ? signature : Utility + .signatureToString(signature, false); + } + + + /** + * Convert type to Java method signature, e.g. int[] f(java.lang.String x) + * becomes (Ljava/lang/String;)[I + * + * @param return_type what the method returns + * @param arg_types what are the argument types + * @return method signature for given type(s). + */ + public static String getMethodSignature( Type return_type, Type[] arg_types ) { + StringBuffer buf = new StringBuffer("("); + int length = (arg_types == null) ? 0 : arg_types.length; + for (int i = 0; i < length; i++) { + buf.append(arg_types[i].getSignature()); + } + buf.append(')'); + buf.append(return_type.getSignature()); + return buf.toString(); + } + + private static ThreadLocal consumed_chars = new ThreadLocal() { + + protected Object initialValue() { + return new Integer(0); + } + };//int consumed_chars=0; // Remember position in string, see getArgumentTypes + + + private static int unwrap( ThreadLocal tl ) { + return ((Integer) tl.get()).intValue(); + } + + + private static void wrap( ThreadLocal tl, int value ) { + tl.set(new Integer(value)); + } + + + /** + * Convert signature to a Type object. + * @param signature signature string such as Ljava/lang/String; + * @return type object + */ + public static final Type getType( String signature ) throws StringIndexOutOfBoundsException { + byte type = Utility.typeOfSignature(signature); + if (type <= Constants.T_VOID) { + //corrected concurrent private static field acess + wrap(consumed_chars, 1); + return BasicType.getType(type); + } else if (type == Constants.T_ARRAY) { + int dim = 0; + do { // Count dimensions + dim++; + } while (signature.charAt(dim) == '['); + // Recurse, but just once, if the signature is ok + Type t = getType(signature.substring(dim)); + //corrected concurrent private static field acess + // consumed_chars += dim; // update counter - is replaced by + int _temp = unwrap(consumed_chars) + dim; + wrap(consumed_chars, _temp); + return new ArrayType(t, dim); + } else { // type == T_REFERENCE + int index = signature.indexOf(';'); // Look for closing `;' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + //corrected concurrent private static field acess + wrap(consumed_chars, index + 1); // "Lblabla;" `L' and `;' are removed + return new ObjectType(signature.substring(1, index).replace('/', '.')); + } + } + + + /** + * Convert return value of a method (signature) to a Type object. + * + * @param signature signature string such as (Ljava/lang/String;)V + * @return return type + */ + public static Type getReturnType( String signature ) { + try { + // Read return type after `)' + int index = signature.lastIndexOf(')') + 1; + return getType(signature.substring(index)); + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + } + + + /** + * Convert arguments of a method (signature) to an array of Type objects. + * @param signature signature string such as (Ljava/lang/String;)V + * @return array of argument types + */ + public static Type[] getArgumentTypes( String signature ) { + List vec = new ArrayList(); + int index; + Type[] types; + try { // Read all declarations between for `(' and `)' + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + index = 1; // current string position + while (signature.charAt(index) != ')') { + vec.add(getType(signature.substring(index))); + //corrected concurrent private static field acess + index += unwrap(consumed_chars); // update position + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + types = new Type[vec.size()]; + vec.toArray(types); + return types; + } + + + /** Convert runtime java.lang.Class to BCEL Type object. + * @param cl Java class + * @return corresponding Type object + */ + public static Type getType( java.lang.Class cl ) { + if (cl == null) { + throw new IllegalArgumentException("Class must not be null"); + } + /* That's an amzingly easy case, because getName() returns + * the signature. That's what we would have liked anyway. + */ + if (cl.isArray()) { + return getType(cl.getName()); + } else if (cl.isPrimitive()) { + if (cl == Integer.TYPE) { + return INT; + } else if (cl == Void.TYPE) { + return VOID; + } else if (cl == Double.TYPE) { + return DOUBLE; + } else if (cl == Float.TYPE) { + return FLOAT; + } else if (cl == Boolean.TYPE) { + return BOOLEAN; + } else if (cl == Byte.TYPE) { + return BYTE; + } else if (cl == Short.TYPE) { + return SHORT; + } else if (cl == Byte.TYPE) { + return BYTE; + } else if (cl == Long.TYPE) { + return LONG; + } else if (cl == Character.TYPE) { + return CHAR; + } else { + throw new IllegalStateException("Ooops, what primitive type is " + cl); + } + } else { // "Real" class + return new ObjectType(cl.getName()); + } + } + + + /** + * Convert runtime java.lang.Class[] to BCEL Type objects. + * @param classes an array of runtime class objects + * @return array of corresponding Type objects + */ + public static Type[] getTypes( java.lang.Class[] classes ) { + Type[] ret = new Type[classes.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = getType(classes[i]); + } + return ret; + } + + + public static String getSignature( java.lang.reflect.Method meth ) { + StringBuffer sb = new StringBuffer("("); + Class[] params = meth.getParameterTypes(); // avoid clone + for (int j = 0; j < params.length; j++) { + sb.append(getType(params[j]).getSignature()); + } + sb.append(")"); + sb.append(getType(meth.getReturnType()).getSignature()); + return sb.toString(); + } + + private static int size(int coded) { + return coded & 3; + } + + private static int consumed(int coded) { + return coded >> 2; + } + + private static int encode(int size, int consumed) { + return consumed << 2 | size; + } + + static int getArgumentTypesSize( String signature ) { + int res = 0; + int index; + Type[] types; + try { // Read all declarations between for `(' and `)' + if (signature.charAt(0) != '(') { + throw new ClassFormatException("Invalid method signature: " + signature); + } + index = 1; // current string position + while (signature.charAt(index) != ')') { + int coded = getTypeSize(signature.substring(index)); + res += size(coded); + index += consumed(coded); + } + } catch (StringIndexOutOfBoundsException e) { // Should never occur + throw new ClassFormatException("Invalid method signature: " + signature, e); + } + return res; + } + + static final int getTypeSize( String signature ) throws StringIndexOutOfBoundsException { + byte type = Utility.typeOfSignature(signature); + if (type <= Constants.T_VOID) { + return encode(BasicType.getType(type).getSize(), 1); + } else if (type == Constants.T_ARRAY) { + int dim = 0; + do { // Count dimensions + dim++; + } while (signature.charAt(dim) == '['); + // Recurse, but just once, if the signature is ok + int consumed = consumed(getTypeSize(signature.substring(dim))); + return encode(1, dim + consumed); + } else { // type == T_REFERENCE + int index = signature.indexOf(';'); // Look for closing `;' + if (index < 0) { + throw new ClassFormatException("Invalid signature: " + signature); + } + return encode(1, index + 1); + } + } + + + static int getReturnTypeSize(String signature) { + int index = signature.lastIndexOf(')') + 1; + return getTypeSize(signature.substring(index)); + } +} diff --git a/java/org/apache/tomcat/util/bcel/generic/TypedInstruction.java b/java/org/apache/tomcat/util/bcel/generic/TypedInstruction.java new file mode 100644 index 000000000..db2b4e9ce --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/TypedInstruction.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Get the type associated with an instruction, int for ILOAD, or the type + * of the field of a PUTFIELD instruction, e.g.. + * + * @version $Id$ + * @author M. Dahm + */ +public interface TypedInstruction { + + public Type getType( ConstantPoolGen cpg ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/UnconditionalBranch.java b/java/org/apache/tomcat/util/bcel/generic/UnconditionalBranch.java new file mode 100644 index 000000000..710f893c7 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/UnconditionalBranch.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an instruction to perform an unconditional branch, i.e., GOTO, JSR. + * + * @version $Id$ + * @author M. Dahm + + * @see GOTO + * @see JSR + */ +public interface UnconditionalBranch { +} diff --git a/java/org/apache/tomcat/util/bcel/generic/VariableLengthInstruction.java b/java/org/apache/tomcat/util/bcel/generic/VariableLengthInstruction.java new file mode 100644 index 000000000..00704c368 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/VariableLengthInstruction.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Denotes an instruction to be a variable length instruction, such as + * GOTO, JSR, LOOKUPSWITCH and TABLESWITCH. + * + * @version $Id$ + * @author M. Dahm + + * @see GOTO + * @see JSR + * @see LOOKUPSWITCH + * @see TABLESWITCH + */ +public interface VariableLengthInstruction { +} diff --git a/java/org/apache/tomcat/util/bcel/generic/Visitor.java b/java/org/apache/tomcat/util/bcel/generic/Visitor.java new file mode 100644 index 000000000..65b4838c9 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/Visitor.java @@ -0,0 +1,568 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.generic; + +/** + * Interface implementing the Visitor pattern programming style. + * I.e., a class that implements this interface can handle all types of + * instructions with the properly typed methods just by calling the accept() + * method. + * + * @version $Id$ + * @author M. Dahm + */ +public interface Visitor { + + public void visitStackInstruction( StackInstruction obj ); + + + public void visitLocalVariableInstruction( LocalVariableInstruction obj ); + + + public void visitBranchInstruction( BranchInstruction obj ); + + + public void visitLoadClass( LoadClass obj ); + + + public void visitFieldInstruction( FieldInstruction obj ); + + + public void visitIfInstruction( IfInstruction obj ); + + + public void visitConversionInstruction( ConversionInstruction obj ); + + + public void visitPopInstruction( PopInstruction obj ); + + + public void visitStoreInstruction( StoreInstruction obj ); + + + public void visitTypedInstruction( TypedInstruction obj ); + + + public void visitSelect( Select obj ); + + + public void visitJsrInstruction( JsrInstruction obj ); + + + public void visitGotoInstruction( GotoInstruction obj ); + + + public void visitUnconditionalBranch( UnconditionalBranch obj ); + + + public void visitPushInstruction( PushInstruction obj ); + + + public void visitArithmeticInstruction( ArithmeticInstruction obj ); + + + public void visitCPInstruction( CPInstruction obj ); + + + public void visitInvokeInstruction( InvokeInstruction obj ); + + + public void visitArrayInstruction( ArrayInstruction obj ); + + + public void visitAllocationInstruction( AllocationInstruction obj ); + + + public void visitReturnInstruction( ReturnInstruction obj ); + + + public void visitFieldOrMethod( FieldOrMethod obj ); + + + public void visitConstantPushInstruction( ConstantPushInstruction obj ); + + + public void visitExceptionThrower( ExceptionThrower obj ); + + + public void visitLoadInstruction( LoadInstruction obj ); + + + public void visitVariableLengthInstruction( VariableLengthInstruction obj ); + + + public void visitStackProducer( StackProducer obj ); + + + public void visitStackConsumer( StackConsumer obj ); + + + public void visitACONST_NULL( ACONST_NULL obj ); + + + public void visitGETSTATIC( GETSTATIC obj ); + + + public void visitIF_ICMPLT( IF_ICMPLT obj ); + + + public void visitMONITOREXIT( MONITOREXIT obj ); + + + public void visitIFLT( IFLT obj ); + + + public void visitLSTORE( LSTORE obj ); + + + public void visitPOP2( POP2 obj ); + + + public void visitBASTORE( BASTORE obj ); + + + public void visitISTORE( ISTORE obj ); + + + public void visitCHECKCAST( CHECKCAST obj ); + + + public void visitFCMPG( FCMPG obj ); + + + public void visitI2F( I2F obj ); + + + public void visitATHROW( ATHROW obj ); + + + public void visitDCMPL( DCMPL obj ); + + + public void visitARRAYLENGTH( ARRAYLENGTH obj ); + + + public void visitDUP( DUP obj ); + + + public void visitINVOKESTATIC( INVOKESTATIC obj ); + + + public void visitLCONST( LCONST obj ); + + + public void visitDREM( DREM obj ); + + + public void visitIFGE( IFGE obj ); + + + public void visitCALOAD( CALOAD obj ); + + + public void visitLASTORE( LASTORE obj ); + + + public void visitI2D( I2D obj ); + + + public void visitDADD( DADD obj ); + + + public void visitINVOKESPECIAL( INVOKESPECIAL obj ); + + + public void visitIAND( IAND obj ); + + + public void visitPUTFIELD( PUTFIELD obj ); + + + public void visitILOAD( ILOAD obj ); + + + public void visitDLOAD( DLOAD obj ); + + + public void visitDCONST( DCONST obj ); + + + public void visitNEW( NEW obj ); + + + public void visitIFNULL( IFNULL obj ); + + + public void visitLSUB( LSUB obj ); + + + public void visitL2I( L2I obj ); + + + public void visitISHR( ISHR obj ); + + + public void visitTABLESWITCH( TABLESWITCH obj ); + + + public void visitIINC( IINC obj ); + + + public void visitDRETURN( DRETURN obj ); + + + public void visitFSTORE( FSTORE obj ); + + + public void visitDASTORE( DASTORE obj ); + + + public void visitIALOAD( IALOAD obj ); + + + public void visitDDIV( DDIV obj ); + + + public void visitIF_ICMPGE( IF_ICMPGE obj ); + + + public void visitLAND( LAND obj ); + + + public void visitIDIV( IDIV obj ); + + + public void visitLOR( LOR obj ); + + + public void visitCASTORE( CASTORE obj ); + + + public void visitFREM( FREM obj ); + + + public void visitLDC( LDC obj ); + + + public void visitBIPUSH( BIPUSH obj ); + + + public void visitDSTORE( DSTORE obj ); + + + public void visitF2L( F2L obj ); + + + public void visitFMUL( FMUL obj ); + + + public void visitLLOAD( LLOAD obj ); + + + public void visitJSR( JSR obj ); + + + public void visitFSUB( FSUB obj ); + + + public void visitSASTORE( SASTORE obj ); + + + public void visitALOAD( ALOAD obj ); + + + public void visitDUP2_X2( DUP2_X2 obj ); + + + public void visitRETURN( RETURN obj ); + + + public void visitDALOAD( DALOAD obj ); + + + public void visitSIPUSH( SIPUSH obj ); + + + public void visitDSUB( DSUB obj ); + + + public void visitL2F( L2F obj ); + + + public void visitIF_ICMPGT( IF_ICMPGT obj ); + + + public void visitF2D( F2D obj ); + + + public void visitI2L( I2L obj ); + + + public void visitIF_ACMPNE( IF_ACMPNE obj ); + + + public void visitPOP( POP obj ); + + + public void visitI2S( I2S obj ); + + + public void visitIFEQ( IFEQ obj ); + + + public void visitSWAP( SWAP obj ); + + + public void visitIOR( IOR obj ); + + + public void visitIREM( IREM obj ); + + + public void visitIASTORE( IASTORE obj ); + + + public void visitNEWARRAY( NEWARRAY obj ); + + + public void visitINVOKEINTERFACE( INVOKEINTERFACE obj ); + + + public void visitINEG( INEG obj ); + + + public void visitLCMP( LCMP obj ); + + + public void visitJSR_W( JSR_W obj ); + + + public void visitMULTIANEWARRAY( MULTIANEWARRAY obj ); + + + public void visitDUP_X2( DUP_X2 obj ); + + + public void visitSALOAD( SALOAD obj ); + + + public void visitIFNONNULL( IFNONNULL obj ); + + + public void visitDMUL( DMUL obj ); + + + public void visitIFNE( IFNE obj ); + + + public void visitIF_ICMPLE( IF_ICMPLE obj ); + + + public void visitLDC2_W( LDC2_W obj ); + + + public void visitGETFIELD( GETFIELD obj ); + + + public void visitLADD( LADD obj ); + + + public void visitNOP( NOP obj ); + + + public void visitFALOAD( FALOAD obj ); + + + public void visitINSTANCEOF( INSTANCEOF obj ); + + + public void visitIFLE( IFLE obj ); + + + public void visitLXOR( LXOR obj ); + + + public void visitLRETURN( LRETURN obj ); + + + public void visitFCONST( FCONST obj ); + + + public void visitIUSHR( IUSHR obj ); + + + public void visitBALOAD( BALOAD obj ); + + + public void visitDUP2( DUP2 obj ); + + + public void visitIF_ACMPEQ( IF_ACMPEQ obj ); + + + public void visitIMPDEP1( IMPDEP1 obj ); + + + public void visitMONITORENTER( MONITORENTER obj ); + + + public void visitLSHL( LSHL obj ); + + + public void visitDCMPG( DCMPG obj ); + + + public void visitD2L( D2L obj ); + + + public void visitIMPDEP2( IMPDEP2 obj ); + + + public void visitL2D( L2D obj ); + + + public void visitRET( RET obj ); + + + public void visitIFGT( IFGT obj ); + + + public void visitIXOR( IXOR obj ); + + + public void visitINVOKEVIRTUAL( INVOKEVIRTUAL obj ); + + + public void visitFASTORE( FASTORE obj ); + + + public void visitIRETURN( IRETURN obj ); + + + public void visitIF_ICMPNE( IF_ICMPNE obj ); + + + public void visitFLOAD( FLOAD obj ); + + + public void visitLDIV( LDIV obj ); + + + public void visitPUTSTATIC( PUTSTATIC obj ); + + + public void visitAALOAD( AALOAD obj ); + + + public void visitD2I( D2I obj ); + + + public void visitIF_ICMPEQ( IF_ICMPEQ obj ); + + + public void visitAASTORE( AASTORE obj ); + + + public void visitARETURN( ARETURN obj ); + + + public void visitDUP2_X1( DUP2_X1 obj ); + + + public void visitFNEG( FNEG obj ); + + + public void visitGOTO_W( GOTO_W obj ); + + + public void visitD2F( D2F obj ); + + + public void visitGOTO( GOTO obj ); + + + public void visitISUB( ISUB obj ); + + + public void visitF2I( F2I obj ); + + + public void visitDNEG( DNEG obj ); + + + public void visitICONST( ICONST obj ); + + + public void visitFDIV( FDIV obj ); + + + public void visitI2B( I2B obj ); + + + public void visitLNEG( LNEG obj ); + + + public void visitLREM( LREM obj ); + + + public void visitIMUL( IMUL obj ); + + + public void visitIADD( IADD obj ); + + + public void visitLSHR( LSHR obj ); + + + public void visitLOOKUPSWITCH( LOOKUPSWITCH obj ); + + + public void visitDUP_X1( DUP_X1 obj ); + + + public void visitFCMPL( FCMPL obj ); + + + public void visitI2C( I2C obj ); + + + public void visitLMUL( LMUL obj ); + + + public void visitLUSHR( LUSHR obj ); + + + public void visitISHL( ISHL obj ); + + + public void visitLALOAD( LALOAD obj ); + + + public void visitASTORE( ASTORE obj ); + + + public void visitANEWARRAY( ANEWARRAY obj ); + + + public void visitFRETURN( FRETURN obj ); + + + public void visitFADD( FADD obj ); + + + public void visitBREAKPOINT( BREAKPOINT obj ); +} diff --git a/java/org/apache/tomcat/util/bcel/generic/package.html b/java/org/apache/tomcat/util/bcel/generic/package.html new file mode 100644 index 000000000..2ae21266c --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/generic/package.html @@ -0,0 +1,16 @@ + + + + + + +

      +This package contains the "generic" part of the +Byte Code Engineering +Library, i.e., classes to dynamically modify class objects and +byte code instructions. +

      + + diff --git a/java/org/apache/tomcat/util/bcel/package.html b/java/org/apache/tomcat/util/bcel/package.html new file mode 100644 index 000000000..773bac104 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/package.html @@ -0,0 +1,17 @@ + + + + + + +

      +This package contains basic classes for the +Byte Code Engineering Library + and constants defined by the + + JVM specification. +

      + + diff --git a/java/org/apache/tomcat/util/bcel/util/AttributeHTML.java b/java/org/apache/tomcat/util/bcel/util/AttributeHTML.java new file mode 100644 index 000000000..52c2f5454 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/AttributeHTML.java @@ -0,0 +1,211 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Code; +import org.apache.tomcat.util.bcel.classfile.CodeException; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.ConstantValue; +import org.apache.tomcat.util.bcel.classfile.ExceptionTable; +import org.apache.tomcat.util.bcel.classfile.InnerClass; +import org.apache.tomcat.util.bcel.classfile.InnerClasses; +import org.apache.tomcat.util.bcel.classfile.LineNumber; +import org.apache.tomcat.util.bcel.classfile.LineNumberTable; +import org.apache.tomcat.util.bcel.classfile.LocalVariable; +import org.apache.tomcat.util.bcel.classfile.LocalVariableTable; +import org.apache.tomcat.util.bcel.classfile.SourceFile; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Convert found attributes into HTML file. + * + * @version $Id$ + * @author M. Dahm + * + */ +final class AttributeHTML implements org.apache.tomcat.util.bcel.Constants { + + private String class_name; // name of current class + private PrintWriter file; // file to write to + private int attr_count = 0; + private ConstantHTML constant_html; + private ConstantPool constant_pool; + + + AttributeHTML(String dir, String class_name, ConstantPool constant_pool, + ConstantHTML constant_html) throws IOException { + this.class_name = class_name; + this.constant_pool = constant_pool; + this.constant_html = constant_html; + file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html")); + file.println(""); + } + + + private final String codeLink( int link, int method_number ) { + return "" + link + ""; + } + + + final void close() { + file.println("
      "); + file.close(); + } + + + final void writeAttribute( Attribute attribute, String anchor ) throws IOException { + writeAttribute(attribute, anchor, 0); + } + + + final void writeAttribute( Attribute attribute, String anchor, int method_number ) + throws IOException { + byte tag = attribute.getTag(); + int index; + if (tag == ATTR_UNKNOWN) { + return; + } + attr_count++; // Increment number of attributes found so far + if (attr_count % 2 == 0) { + file.print(""); + } else { + file.print(""); + } + file.println("

      " + attr_count + " " + ATTRIBUTE_NAMES[tag] + + "

      "); + /* Handle different attributes + */ + switch (tag) { + case ATTR_CODE: + Code c = (Code) attribute; + // Some directly printable values + file.print("
      • Maximum stack size = " + c.getMaxStack() + + "
      • \n
      • Number of local variables = " + c.getMaxLocals() + + "
      • \n
      • Byte code
      \n"); + // Get handled exceptions and list them + CodeException[] ce = c.getExceptionTable(); + int len = ce.length; + if (len > 0) { + file.print("

      Exceptions handled

        "); + for (int i = 0; i < len; i++) { + int catch_type = ce[i].getCatchType(); // Index in constant pool + file.print("
      • "); + if (catch_type != 0) { + file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html + } else { + file.print("Any Exception"); + } + file.print("
        (Ranging from lines " + + codeLink(ce[i].getStartPC(), method_number) + " to " + + codeLink(ce[i].getEndPC(), method_number) + ", handled at line " + + codeLink(ce[i].getHandlerPC(), method_number) + ")
      • "); + } + file.print("
      "); + } + break; + case ATTR_CONSTANT_VALUE: + index = ((ConstantValue) attribute).getConstantValueIndex(); + // Reference _cp.html + file.print("\n"); + break; + case ATTR_SOURCE_FILE: + index = ((SourceFile) attribute).getSourceFileIndex(); + // Reference _cp.html + file.print("\n"); + break; + case ATTR_EXCEPTIONS: + // List thrown exceptions + int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable(); + file.print("\n"); + break; + case ATTR_LINE_NUMBER_TABLE: + LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable(); + // List line number pairs + file.print("

      "); + for (int i = 0; i < line_numbers.length; i++) { + file.print("(" + line_numbers[i].getStartPC() + ", " + + line_numbers[i].getLineNumber() + ")"); + if (i < line_numbers.length - 1) { + file.print(", "); // breakable + } + } + break; + case ATTR_LOCAL_VARIABLE_TABLE: + LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable(); + // List name, range and type + file.print("

        "); + for (int i = 0; i < vars.length; i++) { + index = vars[i].getSignatureIndex(); + String signature = ((ConstantUtf8) constant_pool.getConstant(index, + CONSTANT_Utf8)).getBytes(); + signature = Utility.signatureToString(signature, false); + int start = vars[i].getStartPC(); + int end = (start + vars[i].getLength()); + file.println("
      • " + Class2HTML.referenceType(signature) + " " + + vars[i].getName() + " in slot %" + vars[i].getIndex() + + "
        Valid from lines " + "" + + start + " to " + "" + end + "
      • "); + } + file.print("
      \n"); + break; + case ATTR_INNER_CLASSES: + InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses(); + // List inner classes + file.print("
        "); + for (int i = 0; i < classes.length; i++) { + String name, access; + index = classes[i].getInnerNameIndex(); + if (index > 0) { + name = ((ConstantUtf8) constant_pool.getConstant(index, CONSTANT_Utf8)) + .getBytes(); + } else { + name = "<anonymous>"; + } + access = Utility.accessToString(classes[i].getInnerAccessFlags()); + file.print("
      • " + access + " " + + constant_html.referenceConstant(classes[i].getInnerClassIndex()) + + " in class " + + constant_html.referenceConstant(classes[i].getOuterClassIndex()) + + " named " + name + "
      • \n"); + } + file.print("
      \n"); + break; + default: // Such as Unknown attribute or Deprecated + file.print("

      " + attribute.toString()); + } + file.println(""); + file.flush(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/BCELComparator.java b/java/org/apache/tomcat/util/bcel/util/BCELComparator.java new file mode 100644 index 000000000..866fa2b71 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/BCELComparator.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +/** + * Used for BCEL comparison strategy + * + * @author M. Dahm + * @version $Id$ + * @since 5.2 + */ +public interface BCELComparator { + + /** + * Compare two objects and return what THIS.equals(THAT) should return + * + * @param THIS + * @param THAT + * @return true if and only if THIS equals THAT + */ + public boolean equals( Object THIS, Object THAT ); + + + /** + * Return hashcode for THIS.hashCode() + * + * @param THIS + * @return hashcode for THIS.hashCode() + */ + public int hashCode( Object THIS ); +} diff --git a/java/org/apache/tomcat/util/bcel/util/BCELFactory.java b/java/org/apache/tomcat/util/bcel/util/BCELFactory.java new file mode 100644 index 000000000..0cdd27ad3 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/BCELFactory.java @@ -0,0 +1,332 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Utility; +import org.apache.tomcat.util.bcel.generic.AllocationInstruction; +import org.apache.tomcat.util.bcel.generic.ArrayInstruction; +import org.apache.tomcat.util.bcel.generic.ArrayType; +import org.apache.tomcat.util.bcel.generic.BranchHandle; +import org.apache.tomcat.util.bcel.generic.BranchInstruction; +import org.apache.tomcat.util.bcel.generic.CHECKCAST; +import org.apache.tomcat.util.bcel.generic.CPInstruction; +import org.apache.tomcat.util.bcel.generic.CodeExceptionGen; +import org.apache.tomcat.util.bcel.generic.ConstantPoolGen; +import org.apache.tomcat.util.bcel.generic.ConstantPushInstruction; +import org.apache.tomcat.util.bcel.generic.EmptyVisitor; +import org.apache.tomcat.util.bcel.generic.FieldInstruction; +import org.apache.tomcat.util.bcel.generic.IINC; +import org.apache.tomcat.util.bcel.generic.INSTANCEOF; +import org.apache.tomcat.util.bcel.generic.Instruction; +import org.apache.tomcat.util.bcel.generic.InstructionConstants; +import org.apache.tomcat.util.bcel.generic.InstructionHandle; +import org.apache.tomcat.util.bcel.generic.InvokeInstruction; +import org.apache.tomcat.util.bcel.generic.LDC; +import org.apache.tomcat.util.bcel.generic.LDC2_W; +import org.apache.tomcat.util.bcel.generic.LocalVariableInstruction; +import org.apache.tomcat.util.bcel.generic.MULTIANEWARRAY; +import org.apache.tomcat.util.bcel.generic.MethodGen; +import org.apache.tomcat.util.bcel.generic.NEWARRAY; +import org.apache.tomcat.util.bcel.generic.ObjectType; +import org.apache.tomcat.util.bcel.generic.RET; +import org.apache.tomcat.util.bcel.generic.ReturnInstruction; +import org.apache.tomcat.util.bcel.generic.Select; +import org.apache.tomcat.util.bcel.generic.Type; + +/** + * Factory creates il.append() statements, and sets instruction targets. + * A helper class for BCELifier. + * + * @see BCELifier + * @version $Id$ + * @author M. Dahm + */ +class BCELFactory extends EmptyVisitor { + + private MethodGen _mg; + private PrintWriter _out; + private ConstantPoolGen _cp; + + + BCELFactory(MethodGen mg, PrintWriter out) { + _mg = mg; + _cp = mg.getConstantPool(); + _out = out; + } + + private Map branch_map = new HashMap(); // Map + + + public void start() { + if (!_mg.isAbstract() && !_mg.isNative()) { + for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih + .getNext()) { + Instruction i = ih.getInstruction(); + if (i instanceof BranchInstruction) { + branch_map.put(i, ih); // memorize container + } + if (ih.hasTargeters()) { + if (i instanceof BranchInstruction) { + _out.println(" InstructionHandle ih_" + ih.getPosition() + ";"); + } else { + _out.print(" InstructionHandle ih_" + ih.getPosition() + " = "); + } + } else { + _out.print(" "); + } + if (!visitInstruction(i)) { + i.accept(this); + } + } + updateBranchTargets(); + updateExceptionHandlers(); + } + } + + + private boolean visitInstruction( Instruction i ) { + short opcode = i.getOpcode(); + if ((InstructionConstants.INSTRUCTIONS[opcode] != null) + && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction)) { // Handled below + _out.println("il.append(InstructionConstants." + + i.getName().toUpperCase(Locale.ENGLISH) + ");"); + return true; + } + return false; + } + + + public void visitLocalVariableInstruction( LocalVariableInstruction i ) { + short opcode = i.getOpcode(); + Type type = i.getType(_cp); + if (opcode == Constants.IINC) { + _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement() + + "));"); + } else { + String kind = (opcode < Constants.ISTORE) ? "Load" : "Store"; + _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type) + + ", " + i.getIndex() + "));"); + } + } + + + public void visitArrayInstruction( ArrayInstruction i ) { + short opcode = i.getOpcode(); + Type type = i.getType(_cp); + String kind = (opcode < Constants.IASTORE) ? "Load" : "Store"; + _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type) + + "));"); + } + + + public void visitFieldInstruction( FieldInstruction i ) { + short opcode = i.getOpcode(); + String class_name = i.getClassName(_cp); + String field_name = i.getFieldName(_cp); + Type type = i.getFieldType(_cp); + _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name + + "\", " + BCELifier.printType(type) + ", " + "Constants." + + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));"); + } + + + public void visitInvokeInstruction( InvokeInstruction i ) { + short opcode = i.getOpcode(); + String class_name = i.getClassName(_cp); + String method_name = i.getMethodName(_cp); + Type type = i.getReturnType(_cp); + Type[] arg_types = i.getArgumentTypes(_cp); + _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name + + "\", " + BCELifier.printType(type) + ", " + + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants." + + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));"); + } + + + public void visitAllocationInstruction( AllocationInstruction i ) { + Type type; + if (i instanceof CPInstruction) { + type = ((CPInstruction) i).getType(_cp); + } else { + type = ((NEWARRAY) i).getType(); + } + short opcode = ((Instruction) i).getOpcode(); + int dim = 1; + switch (opcode) { + case Constants.NEW: + _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName() + + "\"));"); + break; + case Constants.MULTIANEWARRAY: + dim = ((MULTIANEWARRAY) i).getDimensions(); + /* FALL THRU */ + case Constants.ANEWARRAY: + case Constants.NEWARRAY: + if (type instanceof ArrayType) { + type = ((ArrayType) type).getBasicType(); + } + _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type) + + ", (short) " + dim + "));"); + break; + default: + throw new RuntimeException("Oops: " + opcode); + } + } + + + private void createConstant( Object value ) { + String embed = value.toString(); + if (value instanceof String) { + embed = '"' + Utility.convertString(embed) + '"'; + } else if (value instanceof Character) { + embed = "(char)0x" + Integer.toHexString(((Character) value).charValue()); + } else if (value instanceof Float) { + embed += "f"; + } else if (value instanceof Long) { + embed += "L"; + } + _out.println("il.append(new PUSH(_cp, " + embed + "));"); + } + + + public void visitLDC( LDC i ) { + createConstant(i.getValue(_cp)); + } + + + public void visitLDC2_W( LDC2_W i ) { + createConstant(i.getValue(_cp)); + } + + + public void visitConstantPushInstruction( ConstantPushInstruction i ) { + createConstant(i.getValue()); + } + + + public void visitINSTANCEOF( INSTANCEOF i ) { + Type type = i.getType(_cp); + _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));"); + } + + + public void visitCHECKCAST( CHECKCAST i ) { + Type type = i.getType(_cp); + _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));"); + } + + + public void visitReturnInstruction( ReturnInstruction i ) { + Type type = i.getType(_cp); + _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));"); + } + + // Memorize BranchInstructions that need an update + private List branches = new ArrayList(); + + + public void visitBranchInstruction( BranchInstruction bi ) { + BranchHandle bh = (BranchHandle) branch_map.get(bi); + int pos = bh.getPosition(); + String name = bi.getName() + "_" + pos; + if (bi instanceof Select) { + Select s = (Select) bi; + branches.add(bi); + StringBuffer args = new StringBuffer("new int[] { "); + int[] matchs = s.getMatchs(); + for (int i = 0; i < matchs.length; i++) { + args.append(matchs[i]); + if (i < matchs.length - 1) { + args.append(", "); + } + } + args.append(" }"); + _out.print("Select " + name + " = new " + bi.getName().toUpperCase(Locale.ENGLISH) + + "(" + args + ", new InstructionHandle[] { "); + for (int i = 0; i < matchs.length; i++) { + _out.print("null"); + if (i < matchs.length - 1) { + _out.print(", "); + } + } + _out.println(" }, null);"); + } else { + int t_pos = bh.getTarget().getPosition(); + String target; + if (pos > t_pos) { + target = "ih_" + t_pos; + } else { + branches.add(bi); + target = "null"; + } + _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction(" + + "Constants." + bi.getName().toUpperCase(Locale.ENGLISH) + ", " + target + + ");"); + } + if (bh.hasTargeters()) { + _out.println(" ih_" + pos + " = il.append(" + name + ");"); + } else { + _out.println(" il.append(" + name + ");"); + } + } + + + public void visitRET( RET i ) { + _out.println("il.append(new RET(" + i.getIndex() + ")));"); + } + + + private void updateBranchTargets() { + for (Iterator i = branches.iterator(); i.hasNext();) { + BranchInstruction bi = (BranchInstruction) i.next(); + BranchHandle bh = (BranchHandle) branch_map.get(bi); + int pos = bh.getPosition(); + String name = bi.getName() + "_" + pos; + int t_pos = bh.getTarget().getPosition(); + _out.println(" " + name + ".setTarget(ih_" + t_pos + ");"); + if (bi instanceof Select) { + InstructionHandle[] ihs = ((Select) bi).getTargets(); + for (int j = 0; j < ihs.length; j++) { + t_pos = ihs[j].getPosition(); + _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");"); + } + } + } + } + + + private void updateExceptionHandlers() { + CodeExceptionGen[] handlers = _mg.getExceptionHandlers(); + for (int i = 0; i < handlers.length; i++) { + CodeExceptionGen h = handlers[i]; + String type = (h.getCatchType() == null) ? "null" : BCELifier.printType(h + .getCatchType()); + _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition() + + ", " + "ih_" + h.getEndPC().getPosition() + ", " + "ih_" + + h.getHandlerPC().getPosition() + ", " + type + ");"); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/BCELifier.java b/java/org/apache/tomcat/util/bcel/util/BCELifier.java new file mode 100644 index 000000000..4acc55b20 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/BCELifier.java @@ -0,0 +1,268 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Locale; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.Repository; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.ConstantValue; +import org.apache.tomcat.util.bcel.classfile.Field; +import org.apache.tomcat.util.bcel.classfile.JavaClass; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.Utility; +import org.apache.tomcat.util.bcel.generic.ArrayType; +import org.apache.tomcat.util.bcel.generic.ConstantPoolGen; +import org.apache.tomcat.util.bcel.generic.MethodGen; +import org.apache.tomcat.util.bcel.generic.Type; + +/** + * This class takes a given JavaClass object and converts it to a + * Java program that creates that very class using BCEL. This + * gives new users of BCEL a useful example showing how things + * are done with BCEL. It does not cover all features of BCEL, + * but tries to mimic hand-written code as close as possible. + * + * @version $Id$ + * @author M. Dahm + */ +public class BCELifier extends org.apache.tomcat.util.bcel.classfile.EmptyVisitor { + + private static final int FLAG_FOR_UNKNOWN = -1; + private static final int FLAG_FOR_CLASS = 0; + private static final int FLAG_FOR_METHOD = 1; + private JavaClass _clazz; + private PrintWriter _out; + private ConstantPoolGen _cp; + + + /** @param clazz Java class to "decompile" + * @param out where to output Java program + */ + public BCELifier(JavaClass clazz, OutputStream out) { + _clazz = clazz; + _out = new PrintWriter(out); + _cp = new ConstantPoolGen(_clazz.getConstantPool()); + } + + + /** Start Java code generation + */ + public void start() { + visitJavaClass(_clazz); + _out.flush(); + } + + + public void visitJavaClass( JavaClass clazz ) { + String class_name = clazz.getClassName(); + String super_name = clazz.getSuperclassName(); + String package_name = clazz.getPackageName(); + String inter = Utility.printArray(clazz.getInterfaceNames(), false, true); + if (!"".equals(package_name)) { + class_name = class_name.substring(package_name.length() + 1); + _out.println("package " + package_name + ";"); + _out.println(); + } + _out.println("import org.apache.tomcat.util.bcel.generic.*;"); + _out.println("import org.apache.tomcat.util.bcel.classfile.*;"); + _out.println("import org.apache.tomcat.util.bcel.*;"); + _out.println("import java.io.*;"); + _out.println(); + _out.println("public class " + class_name + "Creator implements Constants {"); + _out.println(" private InstructionFactory _factory;"); + _out.println(" private ConstantPoolGen _cp;"); + _out.println(" private ClassGen _cg;"); + _out.println(); + _out.println(" public " + class_name + "Creator() {"); + _out.println(" _cg = new ClassGen(\"" + + (("".equals(package_name)) ? class_name : package_name + "." + class_name) + + "\", \"" + super_name + "\", " + "\"" + clazz.getSourceFileName() + "\", " + + printFlags(clazz.getAccessFlags(), FLAG_FOR_CLASS) + ", " + "new String[] { " + + inter + " });"); + _out.println(); + _out.println(" _cp = _cg.getConstantPool();"); + _out.println(" _factory = new InstructionFactory(_cg, _cp);"); + _out.println(" }"); + _out.println(); + printCreate(); + Field[] fields = clazz.getFields(); + if (fields.length > 0) { + _out.println(" private void createFields() {"); + _out.println(" FieldGen field;"); + for (int i = 0; i < fields.length; i++) { + fields[i].accept(this); + } + _out.println(" }"); + _out.println(); + } + Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + _out.println(" private void createMethod_" + i + "() {"); + methods[i].accept(this); + _out.println(" }"); + _out.println(); + } + printMain(); + _out.println("}"); + } + + + private void printCreate() { + _out.println(" public void create(OutputStream out) throws IOException {"); + Field[] fields = _clazz.getFields(); + if (fields.length > 0) { + _out.println(" createFields();"); + } + Method[] methods = _clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + _out.println(" createMethod_" + i + "();"); + } + _out.println(" _cg.getJavaClass().dump(out);"); + _out.println(" }"); + _out.println(); + } + + + private void printMain() { + String class_name = _clazz.getClassName(); + _out.println(" public static void main(String[] args) throws Exception {"); + _out.println(" " + class_name + "Creator creator = new " + class_name + "Creator();"); + _out.println(" creator.create(new FileOutputStream(\"" + class_name + ".class\"));"); + _out.println(" }"); + } + + + public void visitField( Field field ) { + _out.println(); + _out.println(" field = new FieldGen(" + printFlags(field.getAccessFlags()) + ", " + + printType(field.getSignature()) + ", \"" + field.getName() + "\", _cp);"); + ConstantValue cv = field.getConstantValue(); + if (cv != null) { + String value = cv.toString(); + _out.println(" field.setInitValue(" + value + ")"); + } + _out.println(" _cg.addField(field.getField());"); + } + + + public void visitMethod( Method method ) { + MethodGen mg = new MethodGen(method, _clazz.getClassName(), _cp); + Type result_type = mg.getReturnType(); + Type[] arg_types = mg.getArgumentTypes(); + _out.println(" InstructionList il = new InstructionList();"); + _out.println(" MethodGen method = new MethodGen(" + + printFlags(method.getAccessFlags(), FLAG_FOR_METHOD) + ", " + + printType(result_type) + ", " + printArgumentTypes(arg_types) + ", " + + "new String[] { " + Utility.printArray(mg.getArgumentNames(), false, true) + + " }, \"" + method.getName() + "\", \"" + _clazz.getClassName() + "\", il, _cp);"); + _out.println(); + BCELFactory factory = new BCELFactory(mg, _out); + factory.start(); + _out.println(" method.setMaxStack();"); + _out.println(" method.setMaxLocals();"); + _out.println(" _cg.addMethod(method.getMethod());"); + _out.println(" il.dispose();"); + } + + + static String printFlags( int flags ) { + return printFlags(flags, FLAG_FOR_UNKNOWN); + } + + + static String printFlags( int flags, int reason ) { + if (flags == 0) { + return "0"; + } + StringBuffer buf = new StringBuffer(); + for (int i = 0, pow = 1; pow <= Constants.MAX_ACC_FLAG; i++) { + if ((flags & pow) != 0) { + if ((pow == Constants.ACC_SYNCHRONIZED) && (reason == FLAG_FOR_CLASS)) { + buf.append("ACC_SUPER | "); + } else if ((pow == Constants.ACC_VOLATILE) && (reason == FLAG_FOR_METHOD)) { + buf.append("ACC_BRIDGE | "); + } else if ((pow == Constants.ACC_TRANSIENT) && (reason == FLAG_FOR_METHOD)) { + buf.append("ACC_VARARGS | "); + } else { + buf.append("ACC_") + .append(Constants.ACCESS_NAMES[i].toUpperCase(Locale.ENGLISH)).append( + " | "); + } + } + pow <<= 1; + } + String str = buf.toString(); + return str.substring(0, str.length() - 3); + } + + + static String printArgumentTypes( Type[] arg_types ) { + if (arg_types.length == 0) { + return "Type.NO_ARGS"; + } + StringBuffer args = new StringBuffer(); + for (int i = 0; i < arg_types.length; i++) { + args.append(printType(arg_types[i])); + if (i < arg_types.length - 1) { + args.append(", "); + } + } + return "new Type[] { " + args.toString() + " }"; + } + + + static String printType( Type type ) { + return printType(type.getSignature()); + } + + + static String printType( String signature ) { + Type type = Type.getType(signature); + byte t = type.getType(); + if (t <= Constants.T_VOID) { + return "Type." + Constants.TYPE_NAMES[t].toUpperCase(Locale.ENGLISH); + } else if (type.toString().equals("java.lang.String")) { + return "Type.STRING"; + } else if (type.toString().equals("java.lang.Object")) { + return "Type.OBJECT"; + } else if (type.toString().equals("java.lang.StringBuffer")) { + return "Type.STRINGBUFFER"; + } else if (type instanceof ArrayType) { + ArrayType at = (ArrayType) type; + return "new ArrayType(" + printType(at.getBasicType()) + ", " + at.getDimensions() + + ")"; + } else { + return "new ObjectType(\"" + Utility.signatureToString(signature, false) + "\")"; + } + } + + + /** Default main method + */ + public static void main( String[] argv ) throws Exception { + JavaClass java_class; + String name = argv[0]; + if ((java_class = Repository.lookupClass(name)) == null) { + java_class = new ClassParser(name).parse(); // May throw IOException + } + BCELifier bcelifier = new BCELifier(java_class, System.out); + bcelifier.start(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ByteSequence.java b/java/org/apache/tomcat/util/bcel/util/ByteSequence.java new file mode 100644 index 000000000..9823df5af --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ByteSequence.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; + +/** + * Utility class that implements a sequence of bytes which can be read + * via the `readByte()' method. This is used to implement a wrapper for the + * Java byte code stream to gain some more readability. + * + * @version $Id$ + * @author M. Dahm + */ +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/java/org/apache/tomcat/util/bcel/util/Class2HTML.java b/java/org/apache/tomcat/util/bcel/util/Class2HTML.java new file mode 100644 index 000000000..032860993 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/Class2HTML.java @@ -0,0 +1,231 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.JavaClass; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Read class file(s) and convert them into HTML files. + * + * Given a JavaClass object "class" that is in package "package" five files + * will be created in the specified directory. + * + *

        + *
      1. "package"."class".html as the main file which defines the frames for + * the following subfiles. + *
      2. "package"."class"_attributes.html contains all (known) attributes found in the file + *
      3. "package"."class"_cp.html contains the constant pool + *
      4. "package"."class"_code.html contains the byte code + *
      5. "package"."class"_methods.html contains references to all methods and fields of the class + *
      + * + * All subfiles reference each other appropiately, e.g. clicking on a + * method in the Method's frame will jump to the appropiate method in + * the Code frame. + * + * @version $Id$ + * @author M. Dahm + */ +public class Class2HTML implements Constants { + + private JavaClass java_class; // current class object + private String dir; + private static String class_package; // name of package, unclean to make it static, but ... + private static String class_name; // name of current class, dito + private static ConstantPool constant_pool; + + + /** + * Write contents of the given JavaClass into HTML files. + * + * @param java_class The class to write + * @param dir The directory to put the files in + */ + public Class2HTML(JavaClass java_class, String dir) throws IOException { + Method[] methods = java_class.getMethods(); + this.java_class = java_class; + this.dir = dir; + class_name = java_class.getClassName(); // Remember full name + constant_pool = java_class.getConstantPool(); + // Get package name by tacking off everything after the last `.' + int index = class_name.lastIndexOf('.'); + if (index > -1) { + class_package = class_name.substring(0, index); + } else { + class_package = ""; // default package + } + ConstantHTML constant_html = new ConstantHTML(dir, class_name, class_package, methods, + constant_pool); + /* Attributes can't be written in one step, so we just open a file + * which will be written consequently. + */ + AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool, + constant_html); +// MethodHTML method_html = new MethodHTML(dir, class_name, methods, java_class.getFields(), +// constant_html, attribute_html); + // Write main file (with frames, yuk) + writeMainHTML(attribute_html); + new CodeHTML(dir, class_name, methods, constant_pool, constant_html); + attribute_html.close(); + } + + + public static void main( String argv[] ) { + String[] file_name = new String[argv.length]; + int files = 0; + ClassParser parser = null; + JavaClass java_class = null; + String zip_file = null; + char sep = System.getProperty("file.separator").toCharArray()[0]; + String dir = "." + sep; // Where to store HTML files + try { + /* Parse command line arguments. + */ + for (int i = 0; i < argv.length; i++) { + if (argv[i].charAt(0) == '-') { // command line switch + if (argv[i].equals("-d")) { // Specify target directory, default `.� + dir = argv[++i]; + if (!dir.endsWith("" + sep)) { + dir = dir + sep; + } + new File(dir).mkdirs(); // Create target directory if necessary + } else if (argv[i].equals("-zip")) { + zip_file = argv[++i]; + } else { + System.out.println("Unknown option " + argv[i]); + } + } else { + file_name[files++] = argv[i]; + } + } + if (files == 0) { + System.err.println("Class2HTML: No input files specified."); + } else { // Loop through files ... + for (int i = 0; i < files; i++) { + System.out.print("Processing " + file_name[i] + "..."); + if (zip_file == null) { + parser = new ClassParser(file_name[i]); // Create parser object from file + } else { + parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file + } + java_class = parser.parse(); + new Class2HTML(java_class, dir); + System.out.println("Done."); + } + } + } catch (Exception e) { + System.out.println(e); + e.printStackTrace(System.out); + } + } + + + /** + * Utility method that converts a class reference in the constant pool, + * i.e., an index to a string. + */ + static String referenceClass( int index ) { + String str = constant_pool.getConstantString(index, CONSTANT_Class); + str = Utility.compactClassName(str); + str = Utility.compactClassName(str, class_package + ".", true); + return "" + str + + ""; + } + + + static final String referenceType( String type ) { + String short_type = Utility.compactClassName(type); + short_type = Utility.compactClassName(short_type, class_package + ".", true); + int index = type.indexOf('['); // Type is an array? + String base_type = type; + if (index > -1) { + base_type = type.substring(0, index); // Tack of the `[' + } + // test for basic type + if (base_type.equals("int") || base_type.equals("short") || base_type.equals("boolean") + || base_type.equals("void") || base_type.equals("char") || base_type.equals("byte") + || base_type.equals("long") || base_type.equals("double") + || base_type.equals("float")) { + return "" + type + ""; + } else { + return "" + short_type + ""; + } + } + + + static String toHTML( String str ) { + StringBuffer buf = new StringBuffer(); + try { // Filter any characters HTML doesn't like such as < and > in particular + for (int i = 0; i < str.length(); i++) { + char ch; + switch (ch = str.charAt(i)) { + case '<': + buf.append("<"); + break; + case '>': + buf.append(">"); + break; + case '\n': + buf.append("\\n"); + break; + case '\r': + buf.append("\\r"); + break; + default: + buf.append(ch); + } + } + } catch (StringIndexOutOfBoundsException e) { + } // Never occurs + return buf.toString(); + } + + + private void writeMainHTML( AttributeHTML attribute_html ) throws IOException { + PrintWriter file = new PrintWriter(new FileOutputStream(dir + class_name + ".html")); + Attribute[] attributes = java_class.getAttributes(); + file.println("\n" + "Documentation for " + class_name + "" + + "\n" + "\n" + + "\n" + "\n" + + "\n" + "\n" + + "\n" + "\n" + + "\n" + + ""); + file.close(); + for (int i = 0; i < attributes.length; i++) { + attribute_html.writeAttribute(attributes[i], "class" + i); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassLoader.java b/java/org/apache/tomcat/util/bcel/util/ClassLoader.java new file mode 100644 index 000000000..b7be17537 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassLoader.java @@ -0,0 +1,184 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.ByteArrayInputStream; +import java.util.Hashtable; +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.ConstantClass; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantUtf8; +import org.apache.tomcat.util.bcel.classfile.JavaClass; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + *

      Drop in replacement for the standard class loader of the JVM. You can use it + * in conjunction with the JavaWrapper to dynamically modify/create classes + * as they're requested.

      + * + *

      This class loader recognizes special requests in a distinct + * format, i.e., when the name of the requested class contains with + * "$$BCEL$$" it calls the createClass() method with that name + * (everything bevor the $$BCEL$$ is considered to be the package + * name. You can subclass the class loader and override that + * method. "Normal" classes class can be modified by overriding the + * modifyClass() method which is called just before defineClass().

      + * + *

      There may be a number of packages where you have to use the + * default class loader (which may also be faster). You can define the + * set of packages where to use the system class loader in the + * constructor. The default value contains "java.", "sun.", + * "javax."

      + * + * @version $Id$ + * @author M. Dahm + * @see JavaWrapper + * @see ClassPath + */ +public class ClassLoader extends java.lang.ClassLoader { + + public static final String[] DEFAULT_IGNORED_PACKAGES = { + "java.", "javax.", "sun." + }; + private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe + private String[] ignored_packages; + private Repository repository = SyntheticRepository.getInstance(); + + + /** Ignored packages are by default ( "java.", "sun.", + * "javax."), i.e. loaded by system class loader + */ + public ClassLoader() { + this(DEFAULT_IGNORED_PACKAGES); + } + + + /** @param deferTo delegate class loader to use for ignored packages + */ + public ClassLoader(java.lang.ClassLoader deferTo) { + super(deferTo); + this.ignored_packages = DEFAULT_IGNORED_PACKAGES; + this.repository = new ClassLoaderRepository(deferTo); + } + + + /** @param ignored_packages classes contained in these packages will be loaded + * with the system class loader + */ + public ClassLoader(String[] ignored_packages) { + this.ignored_packages = ignored_packages; + } + + + /** @param ignored_packages classes contained in these packages will be loaded + * with the system class loader + * @param deferTo delegate class loader to use for ignored packages + */ + public ClassLoader(java.lang.ClassLoader deferTo, String[] ignored_packages) { + this(ignored_packages); + this.repository = new ClassLoaderRepository(deferTo); + } + + + protected Class loadClass( String class_name, boolean resolve ) throws ClassNotFoundException { + Class cl = null; + /* First try: lookup hash table. + */ + if ((cl = (Class) classes.get(class_name)) == null) { + /* Second try: Load system class using system class loader. You better + * don't mess around with them. + */ + for (int i = 0; i < ignored_packages.length; i++) { + if (class_name.startsWith(ignored_packages[i])) { + cl = getParent().loadClass(class_name); + break; + } + } + if (cl == null) { + JavaClass clazz = null; + /* Third try: Special request? + */ + if (class_name.indexOf("$$BCEL$$") >= 0) { + clazz = createClass(class_name); + } else { // Fourth try: Load classes via repository + if ((clazz = repository.loadClass(class_name)) != null) { + clazz = modifyClass(clazz); + } else { + throw new ClassNotFoundException(class_name); + } + } + if (clazz != null) { + byte[] bytes = clazz.getBytes(); + cl = defineClass(class_name, bytes, 0, bytes.length); + } else { + cl = Class.forName(class_name); + } + } + if (resolve) { + resolveClass(cl); + } + } + classes.put(class_name, cl); + return cl; + } + + + /** Override this method if you want to alter a class before it gets actually + * loaded. Does nothing by default. + */ + protected JavaClass modifyClass( JavaClass clazz ) { + return clazz; + } + + + /** + * Override this method to create you own classes on the fly. The + * name contains the special token $$BCEL$$. Everything before that + * token is consddered to be a package name. You can encode you own + * arguments into the subsequent string. You must regard however not + * to use any "illegal" characters, i.e., characters that may not + * appear in a Java class name too
      + * + * The default implementation interprets the string as a encoded compressed + * Java class, unpacks and decodes it with the Utility.decode() method, and + * parses the resulting byte array and returns the resulting JavaClass object. + * + * @param class_name compressed byte code with "$$BCEL$$" in it + */ + protected JavaClass createClass( String class_name ) { + int index = class_name.indexOf("$$BCEL$$"); + String real_name = class_name.substring(index + 8); + JavaClass clazz = null; + try { + byte[] bytes = Utility.decode(real_name, true); + ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo"); + clazz = parser.parse(); + } catch (Throwable e) { + e.printStackTrace(); + return null; + } + // Adapt the class name to the passed value + ConstantPool cp = clazz.getConstantPool(); + ConstantClass cl = (ConstantClass) cp.getConstant(clazz.getClassNameIndex(), + Constants.CONSTANT_Class); + ConstantUtf8 name = (ConstantUtf8) cp.getConstant(cl.getNameIndex(), + Constants.CONSTANT_Utf8); + name.setBytes(class_name.replace('.', '/')); + return clazz; + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassLoaderRepository.java b/java/org/apache/tomcat/util/bcel/util/ClassLoaderRepository.java new file mode 100644 index 000000000..8cd0bc5c4 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassLoaderRepository.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * The repository maintains information about which classes have + * been loaded. + * + * It loads its data from the ClassLoader implementation + * passed into its constructor. + * + * @see org.apache.tomcat.util.bcel.Repository + * + * @version $Id$ + * @author M. Dahm + * @author David Dixon-Peugh + */ +public class ClassLoaderRepository implements Repository { + + private java.lang.ClassLoader loader; + private Map loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS + + + public ClassLoaderRepository(java.lang.ClassLoader loader) { + this.loader = loader; + } + + + /** + * Store a new JavaClass into this Repository. + */ + public void storeClass( JavaClass clazz ) { + loadedClasses.put(clazz.getClassName(), clazz); + clazz.setRepository(this); + } + + + /** + * Remove class from repository + */ + public void removeClass( JavaClass clazz ) { + loadedClasses.remove(clazz.getClassName()); + } + + + /** + * Find an already defined JavaClass. + */ + public JavaClass findClass( String className ) { + if (loadedClasses.containsKey(className)) { + return (JavaClass) loadedClasses.get(className); + } else { + return null; + } + } + + + /** + * Lookup a JavaClass object from the Class Name provided. + */ + public JavaClass loadClass( String className ) throws ClassNotFoundException { + String classFile = className.replace('.', '/'); + JavaClass RC = findClass(className); + if (RC != null) { + return RC; + } + try { + InputStream is = loader.getResourceAsStream(classFile + ".class"); + if (is == null) { + throw new ClassNotFoundException(className + " not found."); + } + ClassParser parser = new ClassParser(is, className); + RC = parser.parse(); + storeClass(RC); + return RC; + } catch (IOException e) { + throw new ClassNotFoundException(className + " not found: " + e.toString(), e); + } + } + + + public JavaClass loadClass( Class clazz ) throws ClassNotFoundException { + return loadClass(clazz.getName()); + } + + + /** Clear all entries from cache. + */ + public void clear() { + loadedClasses.clear(); + } + + + /* + * @return null + */ + public ClassPath getClassPath() { + return null; + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassPath.java b/java/org/apache/tomcat/util/bcel/util/ClassPath.java new file mode 100644 index 000000000..284a491bd --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassPath.java @@ -0,0 +1,485 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Responsible for loading (class) files from the CLASSPATH. Inspired by + * sun.tools.ClassPath. + * + * @version $Id$ + * @author M. Dahm + */ +public class ClassPath implements Serializable { + + public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath(); + private PathEntry[] paths; + private String class_path; + + + /** + * Search for classes in given path. + */ + public ClassPath(String class_path) { + this.class_path = class_path; + List vec = new ArrayList(); + for (StringTokenizer tok = new StringTokenizer(class_path, System + .getProperty("path.separator")); tok.hasMoreTokens();) { + String path = tok.nextToken(); + if (!path.equals("")) { + File file = new File(path); + try { + if (file.exists()) { + if (file.isDirectory()) { + vec.add(new Dir(path)); + } else { + vec.add(new Zip(new ZipFile(file))); + } + } + } catch (IOException e) { + System.err.println("CLASSPATH component " + file + ": " + e); + } + } + } + paths = new PathEntry[vec.size()]; + vec.toArray(paths); + } + + + /** + * Search for classes in CLASSPATH. + * @deprecated Use SYSTEM_CLASS_PATH constant + */ + public ClassPath() { + this(getClassPath()); + } + + + /** @return used class path string + */ + public String toString() { + return class_path; + } + + + public int hashCode() { + return class_path.hashCode(); + } + + + public boolean equals( Object o ) { + if (o instanceof ClassPath) { + return class_path.equals(((ClassPath) o).class_path); + } + return false; + } + + + private static final void getPathComponents( String path, List list ) { + if (path != null) { + StringTokenizer tok = new StringTokenizer(path, File.pathSeparator); + while (tok.hasMoreTokens()) { + String name = tok.nextToken(); + File file = new File(name); + if (file.exists()) { + list.add(name); + } + } + } + } + + + /** Checks for class path components in the following properties: + * "java.class.path", "sun.boot.class.path", "java.ext.dirs" + * + * @return class path as used by default by BCEL + */ + public static final String getClassPath() { + String class_path = System.getProperty("java.class.path"); + String boot_path = System.getProperty("sun.boot.class.path"); + String ext_path = System.getProperty("java.ext.dirs"); + List list = new ArrayList(); + getPathComponents(class_path, list); + getPathComponents(boot_path, list); + List dirs = new ArrayList(); + getPathComponents(ext_path, dirs); + for (Iterator e = dirs.iterator(); e.hasNext();) { + File ext_dir = new File((String) e.next()); + String[] extensions = ext_dir.list(new FilenameFilter() { + + public boolean accept( File dir, String name ) { + name = name.toLowerCase(Locale.ENGLISH); + return name.endsWith(".zip") || name.endsWith(".jar"); + } + }); + if (extensions != null) { + for (int i = 0; i < extensions.length; i++) { + list.add(ext_dir.getPath() + File.separatorChar + extensions[i]); + } + } + } + StringBuffer buf = new StringBuffer(); + for (Iterator e = list.iterator(); e.hasNext();) { + buf.append((String) e.next()); + if (e.hasNext()) { + buf.append(File.pathSeparatorChar); + } + } + return buf.toString().intern(); + } + + + /** + * @param name fully qualified class name, e.g. java.lang.String + * @return input stream for class + */ + public InputStream getInputStream( String name ) throws IOException { + return getInputStream(name.replace('.', '/'), ".class"); + } + + + /** + * Return stream for class or resource on CLASSPATH. + * + * @param name fully qualified file name, e.g. java/lang/String + * @param suffix file name ends with suff, e.g. .java + * @return input stream for file on class path + */ + public InputStream getInputStream( String name, String suffix ) throws IOException { + InputStream is = null; + try { + is = getClass().getClassLoader().getResourceAsStream(name + suffix); + } catch (Exception e) { + } + if (is != null) { + return is; + } + return getClassFile(name, suffix).getInputStream(); + } + + /** + * @param name fully qualified resource name, e.g. java/lang/String.class + * @return InputStream supplying the resource, or null if no resource with that name. + */ + public InputStream getResourceAsStream(String name) { + for (int i = 0; i < paths.length; i++) { + InputStream is; + if ((is = paths[i].getResourceAsStream(name)) != null) { + return is; + } + } + return null; + } + + /** + * @param name fully qualified resource name, e.g. java/lang/String.class + * @return URL supplying the resource, or null if no resource with that name. + */ + public URL getResource(String name) { + for (int i = 0; i < paths.length; i++) { + URL url; + if ((url = paths[i].getResource(name)) != null) { + return url; + } + } + return null; + } + + /** + * @param name fully qualified resource name, e.g. java/lang/String.class + * @return An Enumeration of URLs supplying the resource, or an + * empty Enumeration if no resource with that name. + */ + public Enumeration getResources(String name) { + Vector results = new Vector(); + for (int i = 0; i < paths.length; i++) { + URL url; + if ((url = paths[i].getResource(name)) != null) { + results.add(url); + } + } + return results.elements(); + } + + /** + * @param name fully qualified file name, e.g. java/lang/String + * @param suffix file name ends with suff, e.g. .java + * @return class file for the java class + */ + public ClassFile getClassFile( String name, String suffix ) throws IOException { + for (int i = 0; i < paths.length; i++) { + ClassFile cf; + if ((cf = paths[i].getClassFile(name, suffix)) != null) { + return cf; + } + } + throw new IOException("Couldn't find: " + name + suffix); + } + + + /** + * @param name fully qualified class name, e.g. java.lang.String + * @return input stream for class + */ + public ClassFile getClassFile( String name ) throws IOException { + return getClassFile(name, ".class"); + } + + + /** + * @param name fully qualified file name, e.g. java/lang/String + * @param suffix file name ends with suffix, e.g. .java + * @return byte array for file on class path + */ + public byte[] getBytes( String name, String suffix ) throws IOException { + DataInputStream dis = null; + try { + InputStream is = getInputStream(name, suffix); + if (is == null) { + throw new IOException("Couldn't find: " + name + suffix); + } + dis = new DataInputStream(is); + byte[] bytes = new byte[is.available()]; + dis.readFully(bytes); + return bytes; + } finally { + if (dis != null) { + dis.close(); + } + } + } + + + /** + * @return byte array for class + */ + public byte[] getBytes( String name ) throws IOException { + return getBytes(name, ".class"); + } + + + /** + * @param name name of file to search for, e.g. java/lang/String.java + * @return full (canonical) path for file + */ + public String getPath( String name ) throws IOException { + int index = name.lastIndexOf('.'); + String suffix = ""; + if (index > 0) { + suffix = name.substring(index); + name = name.substring(0, index); + } + return getPath(name, suffix); + } + + + /** + * @param name name of file to search for, e.g. java/lang/String + * @param suffix file name suffix, e.g. .java + * @return full (canonical) path for file, if it exists + */ + public String getPath( String name, String suffix ) throws IOException { + return getClassFile(name, suffix).getPath(); + } + + private static abstract class PathEntry implements Serializable { + + abstract ClassFile getClassFile( String name, String suffix ) throws IOException; + abstract URL getResource(String name); + abstract InputStream getResourceAsStream(String name); + } + + /** Contains information about file/ZIP entry of the Java class. + */ + public interface ClassFile { + + /** @return input stream for class file. + */ + public abstract InputStream getInputStream() throws IOException; + + + /** @return canonical path to class file. + */ + public abstract String getPath(); + + + /** @return base path of found class, i.e. class is contained relative + * to that path, which may either denote a directory, or zip file + */ + public abstract String getBase(); + + + /** @return modification time of class file. + */ + public abstract long getTime(); + + + /** @return size of class file. + */ + public abstract long getSize(); + } + + private static class Dir extends PathEntry { + + private String dir; + + + Dir(String d) { + dir = d; + } + + URL getResource(String name) { + // Resource specification uses '/' whatever the platform + final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar)); + try { + return file.exists() ? file.toURL() : null; + } catch (MalformedURLException e) { + return null; + } + } + + InputStream getResourceAsStream(String name) { + // Resource specification uses '/' whatever the platform + final File file = new File(dir + File.separatorChar + name.replace('/', File.separatorChar)); + try { + return file.exists() ? new FileInputStream(file) : null; + } catch (IOException e) { + return null; + } + } + + ClassFile getClassFile( String name, String suffix ) throws IOException { + final File file = new File(dir + File.separatorChar + + name.replace('.', File.separatorChar) + suffix); + return file.exists() ? new ClassFile() { + + public InputStream getInputStream() throws IOException { + return new FileInputStream(file); + } + + + public String getPath() { + try { + return file.getCanonicalPath(); + } catch (IOException e) { + return null; + } + } + + + public long getTime() { + return file.lastModified(); + } + + + public long getSize() { + return file.length(); + } + + + public String getBase() { + return dir; + } + } : null; + } + + + public String toString() { + return dir; + } + } + + private static class Zip extends PathEntry { + + private ZipFile zip; + + + Zip(ZipFile z) { + zip = z; + } + + URL getResource(String name) { + final ZipEntry entry = zip.getEntry(name); + try { + return (entry != null) ? new URL("jar:file:" + zip.getName() + "!/" + name) : null; + } catch (MalformedURLException e) { + return null; + } + } + + InputStream getResourceAsStream(String name) { + final ZipEntry entry = zip.getEntry(name); + try { + return (entry != null) ? zip.getInputStream(entry) : null; + } catch (IOException e) { + return null; + } + } + + ClassFile getClassFile( String name, String suffix ) throws IOException { + final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix); + + if (entry == null) + return null; + + return new ClassFile() { + + public InputStream getInputStream() throws IOException { + return zip.getInputStream(entry); + } + + + public String getPath() { + return entry.toString(); + } + + + public long getTime() { + return entry.getTime(); + } + + + public long getSize() { + return entry.getSize(); + } + + + public String getBase() { + return zip.getName(); + } + }; + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassQueue.java b/java/org/apache/tomcat/util/bcel/util/ClassQueue.java new file mode 100644 index 000000000..0f5239efa --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassQueue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.util.LinkedList; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Utility class implementing a (typesafe) queue of JavaClass + * objects. + * + * @version $Id$ + * @author M. Dahm + */ +public class ClassQueue implements java.io.Serializable { + + protected LinkedList vec = new LinkedList(); + + + public void enqueue( JavaClass clazz ) { + vec.addLast(clazz); + } + + + public JavaClass dequeue() { + return (JavaClass) vec.removeFirst(); + } + + + public boolean empty() { + return vec.isEmpty(); + } + + + public String toString() { + return vec.toString(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassSet.java b/java/org/apache/tomcat/util/bcel/util/ClassSet.java new file mode 100644 index 000000000..1acc5daa8 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassSet.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Utility class implementing a (typesafe) set of JavaClass objects. + * Since JavaClass has no equals() method, the name of the class is + * used for comparison. + * + * @version $Id$ + * @author M. Dahm + * @see ClassStack + */ +public class ClassSet implements java.io.Serializable { + + private Map _map = new HashMap(); + + + public boolean add( JavaClass clazz ) { + boolean result = false; + if (!_map.containsKey(clazz.getClassName())) { + result = true; + _map.put(clazz.getClassName(), clazz); + } + return result; + } + + + public void remove( JavaClass clazz ) { + _map.remove(clazz.getClassName()); + } + + + public boolean empty() { + return _map.isEmpty(); + } + + + public JavaClass[] toArray() { + Collection values = _map.values(); + JavaClass[] classes = new JavaClass[values.size()]; + values.toArray(classes); + return classes; + } + + + public String[] getClassNames() { + return (String[]) _map.keySet().toArray(new String[_map.keySet().size()]); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassStack.java b/java/org/apache/tomcat/util/bcel/util/ClassStack.java new file mode 100644 index 000000000..cd5455948 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassStack.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.util.Stack; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Utility class implementing a (typesafe) stack of JavaClass objects. + * + * @version $Id$ + * @author M. Dahm + * @see Stack + */ +public class ClassStack implements java.io.Serializable { + + private Stack stack = new Stack(); + + + public void push( JavaClass clazz ) { + stack.push(clazz); + } + + + public JavaClass pop() { + return (JavaClass) stack.pop(); + } + + + public JavaClass top() { + return (JavaClass) stack.peek(); + } + + + public boolean empty() { + return stack.empty(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ClassVector.java b/java/org/apache/tomcat/util/bcel/util/ClassVector.java new file mode 100644 index 000000000..1ab387063 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ClassVector.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.util.ArrayList; +import java.util.List; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Utility class implementing a (typesafe) collection of JavaClass + * objects. Contains the most important methods of a Vector. + * + * @version $Id$ + * @author M. Dahm + * + * @deprecated as of 5.1.1 - 7/17/2005 + */ +public class ClassVector implements java.io.Serializable { + + protected List vec = new ArrayList(); + + + public void addElement( JavaClass clazz ) { + vec.add(clazz); + } + + + public JavaClass elementAt( int index ) { + return (JavaClass) vec.get(index); + } + + + public void removeElementAt( int index ) { + vec.remove(index); + } + + + public JavaClass[] toArray() { + JavaClass[] classes = new JavaClass[vec.size()]; + vec.toArray(classes); + return classes; + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/CodeHTML.java b/java/org/apache/tomcat/util/bcel/util/CodeHTML.java new file mode 100644 index 000000000..d09b5c4bf --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/CodeHTML.java @@ -0,0 +1,567 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.BitSet; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Code; +import org.apache.tomcat.util.bcel.classfile.CodeException; +import org.apache.tomcat.util.bcel.classfile.ConstantFieldref; +import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.LocalVariable; +import org.apache.tomcat.util.bcel.classfile.LocalVariableTable; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Convert code into HTML file. + * + * @version $Id$ + * @author M. Dahm + * + */ +final class CodeHTML implements org.apache.tomcat.util.bcel.Constants { + + private String class_name; // name of current class +// private Method[] methods; // Methods to print + private PrintWriter file; // file to write to + private BitSet goto_set; + private ConstantPool constant_pool; + private ConstantHTML constant_html; + private static boolean wide = false; + + + CodeHTML(String dir, String class_name, Method[] methods, ConstantPool constant_pool, + ConstantHTML constant_html) throws IOException { + this.class_name = class_name; +// this.methods = methods; + this.constant_pool = constant_pool; + this.constant_html = constant_html; + file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html")); + file.println(""); + for (int i = 0; i < methods.length; i++) { + writeMethod(methods[i], i); + } + file.println(""); + file.close(); + } + + + /** + * Disassemble a stream of byte codes and return the + * string representation. + * + * @param stream data input stream + * @return String representation of byte code + */ + private final String codeToHTML( ByteSequence bytes, int method_number ) throws IOException { + short opcode = (short) bytes.readUnsignedByte(); + StringBuffer buf; + String name, signature; + int default_offset = 0, low, high; + int index, class_index, vindex, constant; + int[] jump_table; + int no_pad_bytes = 0, offset; + buf = new StringBuffer(256); + buf.append("").append(OPCODE_NAMES[opcode]).append(""); + /* Special case: Skip (0-3) padding bytes, i.e., the + * following bytes are 4-byte-aligned + */ + if ((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) { + int remainder = bytes.getIndex() % 4; + no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; + for (int i = 0; i < no_pad_bytes; i++) { + bytes.readByte(); + } + // Both cases have a field default_offset in common + default_offset = bytes.readInt(); + } + switch (opcode) { + case TABLESWITCH: + low = bytes.readInt(); + high = bytes.readInt(); + offset = bytes.getIndex() - 12 - no_pad_bytes - 1; + default_offset += offset; + buf.append(""); + // Print switch indices in first row (and default) + jump_table = new int[high - low + 1]; + for (int i = 0; i < jump_table.length; i++) { + jump_table[i] = offset + bytes.readInt(); + buf.append(""); + } + buf.append("\n"); + // Print target and default indices in second row + for (int i = 0; i < jump_table.length; i++) { + buf.append(""); + } + buf.append("\n
      ").append(low + i).append("default
      ").append(jump_table[i]).append("").append(default_offset).append( + "
      \n"); + break; + /* Lookup switch has variable length arguments. + */ + case LOOKUPSWITCH: + int npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - no_pad_bytes - 1; + jump_table = new int[npairs]; + default_offset += offset; + buf.append(""); + // Print switch indices in first row (and default) + for (int i = 0; i < npairs; i++) { + int match = bytes.readInt(); + jump_table[i] = offset + bytes.readInt(); + buf.append(""); + } + buf.append("\n"); + // Print target and default indices in second row + for (int i = 0; i < npairs; i++) { + buf.append(""); + } + buf.append("\n
      ").append(match).append("default
      ").append(jump_table[i]).append("").append(default_offset).append( + "
      \n"); + break; + /* Two address bytes + offset from start of byte stream form the + * jump target. + */ + case GOTO: + case IFEQ: + case IFGE: + case IFGT: + case IFLE: + case IFLT: + case IFNE: + case IFNONNULL: + case IFNULL: + case IF_ACMPEQ: + case IF_ACMPNE: + case IF_ICMPEQ: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ICMPLT: + case IF_ICMPNE: + case JSR: + index = (int) (bytes.getIndex() + bytes.readShort() - 1); + buf.append("").append(index).append(""); + break; + /* Same for 32-bit wide jumps + */ + case GOTO_W: + case JSR_W: + int windex = bytes.getIndex() + bytes.readInt() - 1; + buf.append("").append(windex).append(""); + break; + /* Index byte references local variable (register) + */ + case ALOAD: + case ASTORE: + case DLOAD: + case DSTORE: + case FLOAD: + case FSTORE: + case ILOAD: + case ISTORE: + case LLOAD: + case LSTORE: + case RET: + if (wide) { + vindex = bytes.readShort(); + wide = false; // Clear flag + } else { + vindex = bytes.readUnsignedByte(); + } + buf.append("%").append(vindex); + break; + /* + * Remember wide byte which is used to form a 16-bit address in the + * following instruction. Relies on that the method is called again with + * the following opcode. + */ + case WIDE: + wide = true; + buf.append("(wide)"); + break; + /* Array of basic type. + */ + case NEWARRAY: + buf.append("").append(TYPE_NAMES[bytes.readByte()]).append( + ""); + break; + /* Access object/class fields. + */ + case GETFIELD: + case GETSTATIC: + case PUTFIELD: + case PUTSTATIC: + index = bytes.readShort(); + ConstantFieldref c1 = (ConstantFieldref) constant_pool.getConstant(index, + CONSTANT_Fieldref); + class_index = c1.getClassIndex(); + name = constant_pool.getConstantString(class_index, CONSTANT_Class); + name = Utility.compactClassName(name, false); + index = c1.getNameAndTypeIndex(); + String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType); + if (name.equals(class_name)) { // Local field + buf.append("").append(field_name) + .append("\n"); + } else { + buf.append(constant_html.referenceConstant(class_index)).append(".").append( + field_name); + } + break; + /* Operands are references to classes in constant pool + */ + case CHECKCAST: + case INSTANCEOF: + case NEW: + index = bytes.readShort(); + buf.append(constant_html.referenceConstant(index)); + break; + /* Operands are references to methods in constant pool + */ + case INVOKESPECIAL: + case INVOKESTATIC: + case INVOKEVIRTUAL: + case INVOKEINTERFACE: + int m_index = bytes.readShort(); + String str; + if (opcode == INVOKEINTERFACE) { // Special treatment needed + bytes.readUnsignedByte(); // Redundant + bytes.readUnsignedByte(); // Reserved +// int nargs = bytes.readUnsignedByte(); // Redundant +// int reserved = bytes.readUnsignedByte(); // Reserved + ConstantInterfaceMethodref c = (ConstantInterfaceMethodref) constant_pool + .getConstant(m_index, CONSTANT_InterfaceMethodref); + class_index = c.getClassIndex(); + str = constant_pool.constantToString(c); + index = c.getNameAndTypeIndex(); + } else { + ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(m_index, + CONSTANT_Methodref); + class_index = c.getClassIndex(); + str = constant_pool.constantToString(c); + index = c.getNameAndTypeIndex(); + } + name = Class2HTML.referenceClass(class_index); + str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant( + index, CONSTANT_NameAndType))); + // Get signature, i.e., types + ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(index, + CONSTANT_NameAndType); + signature = constant_pool.constantToString(c2.getSignatureIndex(), CONSTANT_Utf8); + String[] args = Utility.methodSignatureArgumentTypes(signature, false); + String type = Utility.methodSignatureReturnType(signature, false); + buf.append(name).append(".").append(str).append( + "").append("("); + // List arguments + for (int i = 0; i < args.length; i++) { + buf.append(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + buf.append(", "); + } + } + // Attach return type + buf.append("):").append(Class2HTML.referenceType(type)); + break; + /* Operands are references to items in constant pool + */ + case LDC_W: + case LDC2_W: + index = bytes.readShort(); + buf.append("").append( + Class2HTML.toHTML(constant_pool.constantToString(index, + constant_pool.getConstant(index).getTag()))).append(""); + break; + case LDC: + index = bytes.readUnsignedByte(); + buf.append("").append( + Class2HTML.toHTML(constant_pool.constantToString(index, + constant_pool.getConstant(index).getTag()))).append(""); + break; + /* Array of references. + */ + case ANEWARRAY: + index = bytes.readShort(); + buf.append(constant_html.referenceConstant(index)); + break; + /* Multidimensional array of references. + */ + case MULTIANEWARRAY: + index = bytes.readShort(); + int dimensions = bytes.readByte(); + buf.append(constant_html.referenceConstant(index)).append(":").append(dimensions) + .append("-dimensional"); + break; + /* Increment local variable. + */ + case IINC: + if (wide) { + vindex = bytes.readShort(); + constant = bytes.readShort(); + wide = false; + } else { + vindex = bytes.readUnsignedByte(); + constant = bytes.readByte(); + } + buf.append("%").append(vindex).append(" ").append(constant); + break; + default: + if (NO_OF_OPERANDS[opcode] > 0) { + for (int i = 0; i < TYPE_OF_OPERANDS[opcode].length; i++) { + switch (TYPE_OF_OPERANDS[opcode][i]) { + case T_BYTE: + buf.append(bytes.readUnsignedByte()); + break; + case T_SHORT: // Either branch or index + buf.append(bytes.readShort()); + break; + case T_INT: + buf.append(bytes.readInt()); + break; + default: // Never reached + System.err.println("Unreachable default case reached!"); + System.exit(-1); + } + buf.append(" "); + } + } + } + buf.append(""); + return buf.toString(); + } + + + /** + * Find all target addresses in code, so that they can be marked + * with <A NAME = ...>. Target addresses are kept in an BitSet object. + */ + private final void findGotos( ByteSequence bytes, Method method, Code code ) throws IOException { + int index; + goto_set = new BitSet(bytes.available()); + int opcode; + /* First get Code attribute from method and the exceptions handled + * (try .. catch) in this method. We only need the line number here. + */ + if (code != null) { + CodeException[] ce = code.getExceptionTable(); + int len = ce.length; + for (int i = 0; i < len; i++) { + goto_set.set(ce[i].getStartPC()); + goto_set.set(ce[i].getEndPC()); + goto_set.set(ce[i].getHandlerPC()); + } + // Look for local variables and their range + Attribute[] attributes = code.getAttributes(); + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].getTag() == ATTR_LOCAL_VARIABLE_TABLE) { + LocalVariable[] vars = ((LocalVariableTable) attributes[i]) + .getLocalVariableTable(); + for (int j = 0; j < vars.length; j++) { + int start = vars[j].getStartPC(); + int end = (int) (start + vars[j].getLength()); + goto_set.set(start); + goto_set.set(end); + } + break; + } + } + } + // Get target addresses from GOTO, JSR, TABLESWITCH, etc. + for (int i = 0; bytes.available() > 0; i++) { + opcode = bytes.readUnsignedByte(); + //System.out.println(OPCODE_NAMES[opcode]); + switch (opcode) { + case TABLESWITCH: + case LOOKUPSWITCH: + //bytes.readByte(); // Skip already read byte + int remainder = bytes.getIndex() % 4; + int no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder; + int default_offset, + offset; + for (int j = 0; j < no_pad_bytes; j++) { + bytes.readByte(); + } + // Both cases have a field default_offset in common + default_offset = bytes.readInt(); + if (opcode == TABLESWITCH) { + int low = bytes.readInt(); + int high = bytes.readInt(); + offset = bytes.getIndex() - 12 - no_pad_bytes - 1; + default_offset += offset; + goto_set.set(default_offset); + for (int j = 0; j < (high - low + 1); j++) { + index = offset + bytes.readInt(); + goto_set.set(index); + } + } else { // LOOKUPSWITCH + int npairs = bytes.readInt(); + offset = bytes.getIndex() - 8 - no_pad_bytes - 1; + default_offset += offset; + goto_set.set(default_offset); + for (int j = 0; j < npairs; j++) { +// int match = bytes.readInt(); + bytes.readInt(); + index = offset + bytes.readInt(); + goto_set.set(index); + } + } + break; + case GOTO: + case IFEQ: + case IFGE: + case IFGT: + case IFLE: + case IFLT: + case IFNE: + case IFNONNULL: + case IFNULL: + case IF_ACMPEQ: + case IF_ACMPNE: + case IF_ICMPEQ: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ICMPLT: + case IF_ICMPNE: + case JSR: + //bytes.readByte(); // Skip already read byte + index = bytes.getIndex() + bytes.readShort() - 1; + goto_set.set(index); + break; + case GOTO_W: + case JSR_W: + //bytes.readByte(); // Skip already read byte + index = bytes.getIndex() + bytes.readInt() - 1; + goto_set.set(index); + break; + default: + bytes.unreadByte(); + codeToHTML(bytes, 0); // Ignore output + } + } + } + + + /** + * Write a single method with the byte code associated with it. + */ + private void writeMethod( Method method, int method_number ) throws IOException { + // Get raw signature + String signature = method.getSignature(); + // Get array of strings containing the argument types + String[] args = Utility.methodSignatureArgumentTypes(signature, false); + // Get return type string + String type = Utility.methodSignatureReturnType(signature, false); + // Get method name + String name = method.getName(); + String html_name = Class2HTML.toHTML(name); + // Get method's access flags + String access = Utility.accessToString(method.getAccessFlags()); + access = Utility.replace(access, " ", " "); + // Get the method's attributes, the Code Attribute in particular + Attribute[] attributes = method.getAttributes(); + file.print("

      " + access + " " + "" + Class2HTML.referenceType(type) + " " + + html_name + "("); + for (int i = 0; i < args.length; i++) { + file.print(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + file.print(", "); + } + } + file.println(")

      "); + Code c = null; + byte[] code = null; + if (attributes.length > 0) { + file.print("

      Attributes

        \n"); + for (int i = 0; i < attributes.length; i++) { + byte tag = attributes[i].getTag(); + if (tag != ATTR_UNKNOWN) { + file.print("
      • " + + ATTRIBUTE_NAMES[tag] + "
      • \n"); + } else { + file.print("
      • " + attributes[i] + "
      • "); + } + if (tag == ATTR_CODE) { + c = (Code) attributes[i]; + Attribute[] attributes2 = c.getAttributes(); + code = c.getCode(); + file.print("
          "); + for (int j = 0; j < attributes2.length; j++) { + tag = attributes2[j].getTag(); + file.print("
        • " + + ATTRIBUTE_NAMES[tag] + "
        • \n"); + } + file.print("
        "); + } + } + file.println("
      "); + } + if (code != null) { // No code, an abstract method, e.g. + //System.out.println(name + "\n" + Utility.codeToString(code, constant_pool, 0, -1)); + // Print the byte code + ByteSequence stream = new ByteSequence(code); + stream.mark(stream.available()); + findGotos(stream, method, c); + stream.reset(); + file.println("" + + ""); + for (int i = 0; stream.available() > 0; i++) { + int offset = stream.getIndex(); + String str = codeToHTML(stream, method_number); + String anchor = ""; + /* Set an anchor mark if this line is targetted by a goto, jsr, etc. + * Defining an anchor for every line is very inefficient! + */ + if (goto_set.get(offset)) { + anchor = ""; + } + String anchor2; + if (stream.getIndex() == code.length) { + anchor2 = "" + offset + + ""; + } else { + anchor2 = "" + offset; + } + file + .println(""); + } + // Mark last line, may be targetted from Attributes window + file.println(""); + file.println("
      Byte
      offset
      InstructionArgument
      " + anchor2 + "" + anchor + str + + "
      "); + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/ConstantHTML.java b/java/org/apache/tomcat/util/bcel/util/ConstantHTML.java new file mode 100644 index 000000000..ea56a6e58 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/ConstantHTML.java @@ -0,0 +1,233 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import org.apache.tomcat.util.bcel.classfile.Constant; +import org.apache.tomcat.util.bcel.classfile.ConstantClass; +import org.apache.tomcat.util.bcel.classfile.ConstantFieldref; +import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantMethodref; +import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType; +import org.apache.tomcat.util.bcel.classfile.ConstantPool; +import org.apache.tomcat.util.bcel.classfile.ConstantString; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Convert constant pool into HTML file. + * + * @version $Id$ + * @author M. Dahm + * + */ +final class ConstantHTML implements org.apache.tomcat.util.bcel.Constants { + + private String class_name; // name of current class + private String class_package; // name of package + private ConstantPool constant_pool; // reference to constant pool + private PrintWriter file; // file to write to + private String[] constant_ref; // String to return for cp[i] + private Constant[] constants; // The constants in the cp + private Method[] methods; + + + ConstantHTML(String dir, String class_name, String class_package, Method[] methods, + ConstantPool constant_pool) throws IOException { + this.class_name = class_name; + this.class_package = class_package; + this.constant_pool = constant_pool; + this.methods = methods; + constants = constant_pool.getConstantPool(); + file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html")); + constant_ref = new String[constants.length]; + constant_ref[0] = "<unknown>"; + file.println(""); + // Loop through constants, constants[0] is reserved + for (int i = 1; i < constants.length; i++) { + if (i % 2 == 0) { + file.print("\n"); + } + file.println("
      "); + } else { + file.print("
      "); + } + if (constants[i] != null) { + writeConstant(i); + } + file.print("
      "); + file.close(); + } + + + String referenceConstant( int index ) { + return constant_ref[index]; + } + + + private void writeConstant( int index ) { + byte tag = constants[index].getTag(); + int class_index, name_index; + String ref; + // The header is always the same + file.println("

      " + index + " " + CONSTANT_NAMES[tag] + + "

      "); + /* For every constant type get the needed parameters and print them appropiately + */ + switch (tag) { + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + // Get class_index and name_and_type_index, depending on type + if (tag == CONSTANT_Methodref) { + ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(index, + CONSTANT_Methodref); + class_index = c.getClassIndex(); + name_index = c.getNameAndTypeIndex(); + } else { + ConstantInterfaceMethodref c1 = (ConstantInterfaceMethodref) constant_pool + .getConstant(index, CONSTANT_InterfaceMethodref); + class_index = c1.getClassIndex(); + name_index = c1.getNameAndTypeIndex(); + } + // Get method name and its class + String method_name = constant_pool.constantToString(name_index, + CONSTANT_NameAndType); + String html_method_name = Class2HTML.toHTML(method_name); + // Partially compacted class name, i.e., / -> . + String method_class = constant_pool.constantToString(class_index, CONSTANT_Class); + String short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang. + short_method_class = Utility.compactClassName(short_method_class, class_package + + ".", true); // Remove class package prefix + // Get method signature + ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant( + name_index, CONSTANT_NameAndType); + String signature = constant_pool.constantToString(c2.getSignatureIndex(), + CONSTANT_Utf8); + // Get array of strings containing the argument types + String[] args = Utility.methodSignatureArgumentTypes(signature, false); + // Get return type string + String type = Utility.methodSignatureReturnType(signature, false); + String ret_type = Class2HTML.referenceType(type); + StringBuffer buf = new StringBuffer("("); + for (int i = 0; i < args.length; i++) { + buf.append(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + buf.append(", "); + } + } + buf.append(")"); + String arg_types = buf.toString(); + if (method_class.equals(class_name)) { + ref = "" + + html_method_name + ""; + } else { + ref = "" + + short_method_class + "." + html_method_name; + } + constant_ref[index] = ret_type + " " + short_method_class + + "." + html_method_name + " " + arg_types; + file.println("

      " + ret_type + " " + ref + arg_types + + " \n

      "); + break; + case CONSTANT_Fieldref: + // Get class_index and name_and_type_index + ConstantFieldref c3 = (ConstantFieldref) constant_pool.getConstant(index, + CONSTANT_Fieldref); + class_index = c3.getClassIndex(); + name_index = c3.getNameAndTypeIndex(); + // Get method name and its class (compacted) + String field_class = constant_pool.constantToString(class_index, CONSTANT_Class); + String short_field_class = Utility.compactClassName(field_class); // I.e., remove java.lang. + short_field_class = Utility.compactClassName(short_field_class, + class_package + ".", true); // Remove class package prefix + String field_name = constant_pool + .constantToString(name_index, CONSTANT_NameAndType); + if (field_class.equals(class_name)) { + ref = "" + field_name + ""; + } else { + ref = "" + short_field_class + + "." + field_name + "\n"; + } + constant_ref[index] = "" + short_field_class + "." + + field_name + ""; + file.println("

      " + ref + "
      \n" + "

      "); + break; + case CONSTANT_Class: + ConstantClass c4 = (ConstantClass) constant_pool.getConstant(index, CONSTANT_Class); + name_index = c4.getNameIndex(); + String class_name2 = constant_pool.constantToString(index, tag); // / -> . + String short_class_name = Utility.compactClassName(class_name2); // I.e., remove java.lang. + short_class_name = Utility.compactClassName(short_class_name, class_package + ".", + true); // Remove class package prefix + ref = "" + short_class_name + + ""; + constant_ref[index] = "" + short_class_name + ""; + file.println("

      " + ref + "

      \n"); + break; + case CONSTANT_String: + ConstantString c5 = (ConstantString) constant_pool.getConstant(index, + CONSTANT_String); + name_index = c5.getStringIndex(); + String str = Class2HTML.toHTML(constant_pool.constantToString(index, tag)); + file.println("

      " + str + "

      \n"); + break; + case CONSTANT_NameAndType: + ConstantNameAndType c6 = (ConstantNameAndType) constant_pool.getConstant(index, + CONSTANT_NameAndType); + name_index = c6.getNameIndex(); + int signature_index = c6.getSignatureIndex(); + file.println("

      " + + Class2HTML.toHTML(constant_pool.constantToString(index, tag)) + + "

      \n"); + break; + default: + file + .println("

      " + + Class2HTML.toHTML(constant_pool.constantToString(index, tag)) + + "\n"); + } // switch + } + + + private final int getMethodNumber( String str ) { + for (int i = 0; i < methods.length; i++) { + String cmp = methods[i].getName() + methods[i].getSignature(); + if (cmp.equals(str)) { + return i; + } + } + return -1; + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/InstructionFinder.java b/java/org/apache/tomcat/util/bcel/util/InstructionFinder.java new file mode 100644 index 000000000..16d2a1b13 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/InstructionFinder.java @@ -0,0 +1,428 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.generic.ClassGenException; +import org.apache.tomcat.util.bcel.generic.Instruction; +import org.apache.tomcat.util.bcel.generic.InstructionHandle; +import org.apache.tomcat.util.bcel.generic.InstructionList; + +/** + * InstructionFinder is a tool to search for given instructions patterns, i.e., + * match sequences of instructions in an instruction list via regular + * expressions. This can be used, e.g., in order to implement a peep hole + * optimizer that looks for code patterns and replaces them with faster + * equivalents. + * + *

      + * This class internally uses the java.util.regex + * package to search for regular expressions. + * + * A typical application would look like this: + * + *

      + * 
      + *  
      + *   InstructionFinder f   = new InstructionFinder(il);
      + *   String            pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP (IFEQ|IFNE)";
      + *   
      + *   for(Iterator i = f.search(pat, constraint); i.hasNext(); ) {
      + *   InstructionHandle[] match = (InstructionHandle[])i.next();
      + *   ...
      + *   il.delete(match[1], match[5]);
      + *   ...
      + *   }
      + *   
      + *  
      + * 
      + * + * @version $Id$ + * @author M. Dahm + * @see Instruction + * @see InstructionList + */ +public class InstructionFinder { + + private static final int OFFSET = 32767; // char + OFFSET is + // outside of + // LATIN-1 + private static final int NO_OPCODES = 256; // Potential number, + // some are not used + private static final Map map = new HashMap(); // Map + private InstructionList il; + private String il_string; // instruction list + // as string + private InstructionHandle[] handles; // map instruction + + + // list to array + /** + * @param il + * instruction list to search for given patterns + */ + public InstructionFinder(InstructionList il) { + this.il = il; + reread(); + } + + + /** + * Reread the instruction list, e.g., after you've altered the list upon a + * match. + */ + public final void reread() { + int size = il.getLength(); + char[] buf = new char[size]; // Create a string with length equal to il + // length + handles = il.getInstructionHandles(); + // Map opcodes to characters + for (int i = 0; i < size; i++) { + buf[i] = makeChar(handles[i].getInstruction().getOpcode()); + } + il_string = new String(buf); + } + + + /** + * Map symbolic instruction names like "getfield" to a single character. + * + * @param pattern + * instruction pattern in lower case + * @return encoded string for a pattern such as "BranchInstruction". + */ + private static final String mapName( String pattern ) { + String result = (String) map.get(pattern); + if (result != null) { + return result; + } + for (short i = 0; i < NO_OPCODES; i++) { + if (pattern.equals(Constants.OPCODE_NAMES[i])) { + return "" + makeChar(i); + } + } + throw new RuntimeException("Instruction unknown: " + pattern); + } + + + /** + * Replace symbolic names of instructions with the appropiate character and + * remove all white space from string. Meta characters such as +, * are + * ignored. + * + * @param pattern + * The pattern to compile + * @return translated regular expression string + */ + private static final String compilePattern( String pattern ) { + //Bug: 38787 - Instructions are assumed to be english, to avoid odd Locale issues + String lower = pattern.toLowerCase(Locale.ENGLISH); + StringBuffer buf = new StringBuffer(); + int size = pattern.length(); + for (int i = 0; i < size; i++) { + char ch = lower.charAt(i); + if (Character.isLetterOrDigit(ch)) { + StringBuffer name = new StringBuffer(); + while ((Character.isLetterOrDigit(ch) || ch == '_') && i < size) { + name.append(ch); + if (++i < size) { + ch = lower.charAt(i); + } else { + break; + } + } + i--; + buf.append(mapName(name.toString())); + } else if (!Character.isWhitespace(ch)) { + buf.append(ch); + } + } + return buf.toString(); + } + + + /** + * @return the matched piece of code as an array of instruction (handles) + */ + private InstructionHandle[] getMatch( int matched_from, int match_length ) { + InstructionHandle[] match = new InstructionHandle[match_length]; + System.arraycopy(handles, matched_from, match, 0, match_length); + return match; + } + + + /** + * Search for the given pattern in the instruction list. You can search for + * any valid opcode via its symbolic name, e.g. "istore". You can also use a + * super class or an interface name to match a whole set of instructions, e.g. + * "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all + * "istore_x" instructions. Additional aliases are "if" for "ifxx", "if_icmp" + * for "if_icmpxx", "if_acmp" for "if_acmpxx". + * + * Consecutive instruction names must be separated by white space which will + * be removed during the compilation of the pattern. + * + * For the rest the usual pattern matching rules for regular expressions + * apply. + *

      + * Example pattern: + * + *

      +     * search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
      +     * 
      + * + *

      + * If you alter the instruction list upon a match such that other matching + * areas are affected, you should call reread() to update the finder and call + * search() again, because the matches are cached. + * + * @param pattern + * the instruction pattern to search for, where case is ignored + * @param from + * where to start the search in the instruction list + * @param constraint + * optional CodeConstraint to check the found code pattern for + * user-defined constraints + * @return iterator of matches where e.nextElement() returns an array of + * instruction handles describing the matched area + */ + public final Iterator search( String pattern, InstructionHandle from, CodeConstraint constraint ) { + String search = compilePattern(pattern); + int start = -1; + for (int i = 0; i < handles.length; i++) { + if (handles[i] == from) { + start = i; // Where to start search from (index) + break; + } + } + if (start == -1) { + throw new ClassGenException("Instruction handle " + from + + " not found in instruction list."); + } + Pattern regex = Pattern.compile(search); + List matches = new ArrayList(); + Matcher matcher = regex.matcher(il_string); + while (start < il_string.length() && matcher.find(start)) { + int startExpr = matcher.start(); + int endExpr = matcher.end(); + int lenExpr = (endExpr - startExpr); + InstructionHandle[] match = getMatch(startExpr, lenExpr); + if ((constraint == null) || constraint.checkCode(match)) { + matches.add(match); + } + start = endExpr; + } + return matches.iterator(); + } + + + /** + * Start search beginning from the start of the given instruction list. + * + * @param pattern + * the instruction pattern to search for, where case is ignored + * @return iterator of matches where e.nextElement() returns an array of + * instruction handles describing the matched area + */ + public final Iterator search( String pattern ) { + return search(pattern, il.getStart(), null); + } + + + /** + * Start search beginning from `from'. + * + * @param pattern + * the instruction pattern to search for, where case is ignored + * @param from + * where to start the search in the instruction list + * @return iterator of matches where e.nextElement() returns an array of + * instruction handles describing the matched area + */ + public final Iterator search( String pattern, InstructionHandle from ) { + return search(pattern, from, null); + } + + + /** + * Start search beginning from the start of the given instruction list. Check + * found matches with the constraint object. + * + * @param pattern + * the instruction pattern to search for, case is ignored + * @param constraint + * constraints to be checked on matching code + * @return instruction handle or `null' if the match failed + */ + public final Iterator search( String pattern, CodeConstraint constraint ) { + return search(pattern, il.getStart(), constraint); + } + + + /** + * Convert opcode number to char. + */ + private static final char makeChar( short opcode ) { + return (char) (opcode + OFFSET); + } + + + /** + * @return the inquired instruction list + */ + public final InstructionList getInstructionList() { + return il; + } + + /** + * Code patterns found may be checked using an additional user-defined + * constraint object whether they really match the needed criterion. I.e., + * check constraints that can not expressed with regular expressions. + * + */ + public static interface CodeConstraint { + + /** + * @param match + * array of instructions matching the requested pattern + * @return true if the matched area is really useful + */ + public boolean checkCode( InstructionHandle[] match ); + } + + // Initialize pattern map + static { + map.put("arithmeticinstruction","(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)"); + map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial)"); + map.put("arrayinstruction", "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)"); + map.put("gotoinstruction", "(goto|goto_w)"); + map.put("conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)"); + map.put("localvariableinstruction","(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)"); + map.put("loadinstruction", "(fload|dload|lload|iload|aload)"); + map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)"); + map.put("cpinstruction", "(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)"); + map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)"); + map.put("branchinstruction", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)"); + map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)"); + map.put("select", "(tableswitch|lookupswitch)"); + map.put("ifinstruction", "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)"); + map.put("jsrinstruction", "(jsr|jsr_w)"); + map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)"); + map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)"); + map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)"); + map.put("typedinstruction", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)"); + map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)"); + map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)"); + map.put("indexedinstruction", "(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)"); + map.put("pushinstruction", "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)"); + map.put("stackproducer", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)"); + map.put("stackconsumer", "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)"); + map.put("exceptionthrower","(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)"); + map.put("loadclass", "(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)"); + map.put("instructiontargeter", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)"); + // Some aliases + map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)"); + map.put("if_acmp", "(if_acmpeq|if_acmpne)"); + map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)"); + // Precompile some aliases first + map.put("iconst", precompile(Constants.ICONST_0, Constants.ICONST_5, Constants.ICONST_M1)); + map.put("lconst", new String(new char[] { '(', makeChar(Constants.LCONST_0), '|', makeChar(Constants.LCONST_1), ')' })); + map.put("dconst", new String(new char[] { '(', makeChar(Constants.DCONST_0), '|', makeChar(Constants.DCONST_1), ')' })); + map.put("fconst", new String(new char[] { '(', makeChar(Constants.FCONST_0), '|', makeChar(Constants.FCONST_1), ')' })); + map.put("iload", precompile(Constants.ILOAD_0, Constants.ILOAD_3, Constants.ILOAD)); + map.put("dload", precompile(Constants.DLOAD_0, Constants.DLOAD_3, Constants.DLOAD)); + map.put("fload", precompile(Constants.FLOAD_0, Constants.FLOAD_3, Constants.FLOAD)); + map.put("aload", precompile(Constants.ALOAD_0, Constants.ALOAD_3, Constants.ALOAD)); + map.put("istore", precompile(Constants.ISTORE_0, Constants.ISTORE_3, Constants.ISTORE)); + map.put("dstore", precompile(Constants.DSTORE_0, Constants.DSTORE_3, Constants.DSTORE)); + map.put("fstore", precompile(Constants.FSTORE_0, Constants.FSTORE_3, Constants.FSTORE)); + map.put("astore", precompile(Constants.ASTORE_0, Constants.ASTORE_3, Constants.ASTORE)); + // Compile strings + for (Iterator i = map.keySet().iterator(); i.hasNext();) { + String key = (String) i.next(); + String value = (String) map.get(key); + char ch = value.charAt(1); // Omit already precompiled patterns + if (ch < OFFSET) { + map.put(key, compilePattern(value)); // precompile all + // patterns + } + } + // Add instruction alias to match anything + StringBuffer buf = new StringBuffer("("); + for (short i = 0; i < NO_OPCODES; i++) { + if (Constants.NO_OF_OPERANDS[i] != Constants.UNDEFINED) { // Not + // an + // invalid + // opcode + buf.append(makeChar(i)); + if (i < NO_OPCODES - 1) { + buf.append('|'); + } + } + } + buf.append(')'); + map.put("instruction", buf.toString()); + } + + + private static String precompile( short from, short to, short extra ) { + StringBuffer buf = new StringBuffer("("); + for (short i = from; i <= to; i++) { + buf.append(makeChar(i)); + buf.append('|'); + } + buf.append(makeChar(extra)); + buf.append(")"); + return buf.toString(); + } + + + /* + * Internal debugging routines. + */ +// private static final String pattern2string( String pattern ) { +// return pattern2string(pattern, true); +// } + + +// private static final String pattern2string( String pattern, boolean make_string ) { +// StringBuffer buf = new StringBuffer(); +// for (int i = 0; i < pattern.length(); i++) { +// char ch = pattern.charAt(i); +// if (ch >= OFFSET) { +// if (make_string) { +// buf.append(Constants.OPCODE_NAMES[ch - OFFSET]); +// } else { +// buf.append((ch - OFFSET)); +// } +// } else { +// buf.append(ch); +// } +// } +// return buf.toString(); +// } +} diff --git a/java/org/apache/tomcat/util/bcel/util/JavaWrapper.java b/java/org/apache/tomcat/util/bcel/util/JavaWrapper.java new file mode 100644 index 000000000..7b8db45ef --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/JavaWrapper.java @@ -0,0 +1,117 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader + * to modify/generate classes as they're requested. You can take this as a template + * for your own applications.
      + * Call this wrapper with + *

      java org.apache.tomcat.util.bcel.util.JavaWrapper <real.class.name> [arguments]
      + *

      + * To use your own class loader you can set the "bcel.classloader" system property + * which defaults to "org.apache.tomcat.util.bcel.util.ClassLoader", e.g., with + *

      java org.apache.tomcat.util.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments]
      + *

      + * + * @version $Id$ + * @author M. Dahm + * @see ClassLoader + */ +public class JavaWrapper { + + private java.lang.ClassLoader loader; + + + private static java.lang.ClassLoader getClassLoader() { + String s = System.getProperty("bcel.classloader"); + if ((s == null) || "".equals(s)) { + s = "org.apache.tomcat.util.bcel.util.ClassLoader"; + } + try { + return (java.lang.ClassLoader) Class.forName(s).newInstance(); + } catch (Exception e) { + throw new RuntimeException(e.toString(), e); + } + } + + + public JavaWrapper(java.lang.ClassLoader loader) { + this.loader = loader; + } + + + public JavaWrapper() { + this(getClassLoader()); + } + + + /** Runs the main method of the given class with the arguments passed in argv + * + * @param class_name the fully qualified class name + * @param argv the arguments just as you would pass them directly + */ + public void runMain( String class_name, String[] argv ) throws ClassNotFoundException { + Class cl = loader.loadClass(class_name); + Method method = null; + try { + method = cl.getMethod("main", new Class[] { + argv.getClass() + }); + /* Method main is sane ? + */ + int m = method.getModifiers(); + Class r = method.getReturnType(); + if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m) + || (r != Void.TYPE)) { + throw new NoSuchMethodException(); + } + } catch (NoSuchMethodException no) { + System.out.println("In class " + class_name + + ": public static void main(String[] argv) is not defined"); + return; + } + try { + method.invoke(null, new Object[] { + argv + }); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + + /** Default main method used as wrapper, expects the fully qualified class name + * of the real class as the first argument. + */ + public static void main( String[] argv ) throws Exception { + /* Expects class name as first argument, other arguments are by-passed. + */ + if (argv.length == 0) { + System.out.println("Missing class name."); + return; + } + String class_name = argv[0]; + String[] new_argv = new String[argv.length - 1]; + System.arraycopy(argv, 1, new_argv, 0, new_argv.length); + JavaWrapper wrapper = new JavaWrapper(); + wrapper.runMain(class_name, new_argv); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/MethodHTML.java b/java/org/apache/tomcat/util/bcel/util/MethodHTML.java new file mode 100644 index 000000000..6aa5118d6 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/MethodHTML.java @@ -0,0 +1,156 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import org.apache.tomcat.util.bcel.classfile.Attribute; +import org.apache.tomcat.util.bcel.classfile.Code; +import org.apache.tomcat.util.bcel.classfile.ConstantValue; +import org.apache.tomcat.util.bcel.classfile.ExceptionTable; +import org.apache.tomcat.util.bcel.classfile.Field; +import org.apache.tomcat.util.bcel.classfile.Method; +import org.apache.tomcat.util.bcel.classfile.Utility; + +/** + * Convert methods and fields into HTML file. + * + * @version $Id$ + * @author M. Dahm + * + */ +final class MethodHTML implements org.apache.tomcat.util.bcel.Constants { + + private String class_name; // name of current class + private PrintWriter file; // file to write to + private ConstantHTML constant_html; + private AttributeHTML attribute_html; + + + MethodHTML(String dir, String class_name, Method[] methods, Field[] fields, + ConstantHTML constant_html, AttributeHTML attribute_html) throws IOException { + this.class_name = class_name; + this.attribute_html = attribute_html; + this.constant_html = constant_html; + file = new PrintWriter(new FileOutputStream(dir + class_name + "_methods.html")); + file.println(""); + file.println("" + + ""); + for (int i = 0; i < fields.length; i++) { + writeField(fields[i]); + } + file.println("
      Access flagsTypeField name
      "); + file.println("" + + "" + + ""); + for (int i = 0; i < methods.length; i++) { + writeMethod(methods[i], i); + } + file.println("
      Access flagsReturn typeMethod nameArguments
      "); + file.close(); + } + + + /** + * Print field of class. + * + * @param field field to print + * @exception java.io.IOException + */ + private void writeField( Field field ) throws IOException { + String type = Utility.signatureToString(field.getSignature()); + String name = field.getName(); + String access = Utility.accessToString(field.getAccessFlags()); + Attribute[] attributes; + access = Utility.replace(access, " ", " "); + file.print("" + access + "\n" + + Class2HTML.referenceType(type) + "" + name + + ""); + attributes = field.getAttributes(); + // Write them to the Attributes.html file with anchor "[]" + for (int i = 0; i < attributes.length; i++) { + attribute_html.writeAttribute(attributes[i], name + "@" + i); + } + for (int i = 0; i < attributes.length; i++) { + if (attributes[i].getTag() == ATTR_CONSTANT_VALUE) { // Default value + String str = ((ConstantValue) attributes[i]).toString(); + // Reference attribute in _attributes.html + file.print("= " + str + "\n"); + break; + } + } + file.println(""); + } + + + private final void writeMethod( Method method, int method_number ) throws IOException { + // Get raw signature + String signature = method.getSignature(); + // Get array of strings containing the argument types + String[] args = Utility.methodSignatureArgumentTypes(signature, false); + // Get return type string + String type = Utility.methodSignatureReturnType(signature, false); + // Get method name + String name = method.getName(), html_name; + // Get method's access flags + String access = Utility.accessToString(method.getAccessFlags()); + // Get the method's attributes, the Code Attribute in particular + Attribute[] attributes = method.getAttributes(); + /* HTML doesn't like names like and spaces are places to break + * lines. Both we don't want... + */ + access = Utility.replace(access, " ", " "); + html_name = Class2HTML.toHTML(name); + file.print("" + access + ""); + file.print("" + Class2HTML.referenceType(type) + "" + "" + html_name + + "\n("); + for (int i = 0; i < args.length; i++) { + file.print(Class2HTML.referenceType(args[i])); + if (i < args.length - 1) { + file.print(", "); + } + } + file.print(")"); + // Check for thrown exceptions + for (int i = 0; i < attributes.length; i++) { + attribute_html.writeAttribute(attributes[i], "method" + method_number + "@" + i, + method_number); + byte tag = attributes[i].getTag(); + if (tag == ATTR_EXCEPTIONS) { + file.print("throws"); + int[] exceptions = ((ExceptionTable) attributes[i]).getExceptionIndexTable(); + for (int j = 0; j < exceptions.length; j++) { + file.print(constant_html.referenceConstant(exceptions[j])); + if (j < exceptions.length - 1) { + file.print(", "); + } + } + file.println(""); + } else if (tag == ATTR_CODE) { + Attribute[] c_a = ((Code) attributes[i]).getAttributes(); + for (int j = 0; j < c_a.length; j++) { + attribute_html.writeAttribute(c_a[j], "method" + method_number + "@" + i + "@" + + j, method_number); + } + } + } + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/Repository.java b/java/org/apache/tomcat/util/bcel/util/Repository.java new file mode 100644 index 000000000..47484eec5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/Repository.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * Abstract definition of a class repository. Instances may be used + * to load classes from different sources and may be used in the + * Repository.setRepository method. + * + * @see org.apache.tomcat.util.bcel.Repository + * @version $Id$ + * @author M. Dahm + * @author David Dixon-Peugh + */ +public interface Repository extends java.io.Serializable { + + /** + * Store the provided class under "clazz.getClassName()" + */ + public void storeClass( JavaClass clazz ); + + + /** + * Remove class from repository + */ + public void removeClass( JavaClass clazz ); + + + /** + * Find the class with the name provided, if the class + * isn't there, return NULL. + */ + public JavaClass findClass( String className ); + + + /** + * Find the class with the name provided, if the class + * isn't there, make an attempt to load it. + */ + public JavaClass loadClass( String className ) throws java.lang.ClassNotFoundException; + + + /** + * Find the JavaClass instance for the given run-time class object + */ + public JavaClass loadClass( Class clazz ) throws java.lang.ClassNotFoundException; + + + /** Clear all entries from cache. + */ + public void clear(); + + + /** Get the ClassPath associated with this Repository + */ + public ClassPath getClassPath(); +} diff --git a/java/org/apache/tomcat/util/bcel/util/SyntheticRepository.java b/java/org/apache/tomcat/util/bcel/util/SyntheticRepository.java new file mode 100644 index 000000000..336e5a942 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/SyntheticRepository.java @@ -0,0 +1,202 @@ +/* + * Copyright 2000-2009 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tomcat.util.bcel.util; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.Map; +import org.apache.tomcat.util.bcel.classfile.ClassParser; +import org.apache.tomcat.util.bcel.classfile.JavaClass; + +/** + * This repository is used in situations where a Class is created + * outside the realm of a ClassLoader. Classes are loaded from + * the file systems using the paths specified in the given + * class path. By default, this is the value returned by + * ClassPath.getClassPath(). + *
      + * It is designed to be used as a singleton, however it + * can also be used with custom classpaths. + * + /** + * Abstract definition of a class repository. Instances may be used + * to load classes from different sources and may be used in the + * Repository.setRepository method. + * + * @see org.apache.tomcat.util.bcel.Repository + * + * @version $Id$ + * @author M. Dahm + * @author David Dixon-Peugh + */ +public class SyntheticRepository implements Repository { + + //private static final String DEFAULT_PATH = ClassPath.getClassPath(); + private static Map _instances = new HashMap(); // CLASSPATH X REPOSITORY + private ClassPath _path = null; + private Map _loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS + + + private SyntheticRepository(ClassPath path) { + _path = path; + } + + + public static SyntheticRepository getInstance() { + return getInstance(ClassPath.SYSTEM_CLASS_PATH); + } + + + public static SyntheticRepository getInstance( ClassPath classPath ) { + SyntheticRepository rep = (SyntheticRepository) _instances.get(classPath); + if (rep == null) { + rep = new SyntheticRepository(classPath); + _instances.put(classPath, rep); + } + return rep; + } + + + /** + * Store a new JavaClass instance into this Repository. + */ + public void storeClass( JavaClass clazz ) { + _loadedClasses.put(clazz.getClassName(), new SoftReference(clazz)); + clazz.setRepository(this); + } + + + /** + * Remove class from repository + */ + public void removeClass( JavaClass clazz ) { + _loadedClasses.remove(clazz.getClassName()); + } + + + /** + * Find an already defined (cached) JavaClass object by name. + */ + public JavaClass findClass( String className ) { + SoftReference ref = (SoftReference) _loadedClasses.get(className); + if (ref == null) { + return null; + } + return (JavaClass) ref.get(); + } + + + /** + * Find a JavaClass object by name. + * If it is already in this Repository, the Repository version + * is returned. Otherwise, the Repository's classpath is searched for + * the class (and it is added to the Repository if found). + * + * @param className the name of the class + * @return the JavaClass object + * @throws ClassNotFoundException if the class is not in the + * Repository, and could not be found on the classpath + */ + public JavaClass loadClass( String className ) throws ClassNotFoundException { + if (className == null || className.equals("")) { + throw new IllegalArgumentException("Invalid class name " + className); + } + className = className.replace('/', '.'); // Just in case, canonical form + JavaClass clazz = findClass(className); + if (clazz != null) { + return clazz; + } + try { + return loadClass(_path.getInputStream(className), className); + } catch (IOException e) { + throw new ClassNotFoundException("Exception while looking for class " + className + + ": " + e.toString(), e); + } + } + + + /** + * Find the JavaClass object for a runtime Class object. + * If a class with the same name is already in this Repository, + * the Repository version is returned. Otherwise, getResourceAsStream() + * is called on the Class object to find the class's representation. + * If the representation is found, it is added to the Repository. + * + * @see Class + * @param clazz the runtime Class object + * @return JavaClass object for given runtime class + * @throws ClassNotFoundException if the class is not in the + * Repository, and its representation could not be found + */ + public JavaClass loadClass( Class clazz ) throws ClassNotFoundException { + InputStream clsStream = null; + try{ + String className = clazz.getName(); + JavaClass repositoryClass = findClass(className); + if (repositoryClass != null) { + return repositoryClass; + } + String name = className; + int i = name.lastIndexOf('.'); + if (i > 0) { + name = name.substring(i + 1); + } + clsStream = clazz.getResourceAsStream(name + ".class"); + return loadClass(clsStream, className); + } finally { + try{ + if (clsStream != null){ + clsStream.close(); + } + } catch(IOException ioe){ + //don't care + } + } + } + + + private JavaClass loadClass( InputStream is, String className ) throws ClassNotFoundException { + try { + if (is != null) { + ClassParser parser = new ClassParser(is, className); + JavaClass clazz = parser.parse(); + storeClass(clazz); + return clazz; + } + } catch (IOException e) { + throw new ClassNotFoundException("Exception while looking for class " + className + + ": " + e.toString(), e); + } + throw new ClassNotFoundException("SyntheticRepository could not load " + className); + } + + + /** ClassPath associated with the Repository. + */ + public ClassPath getClassPath() { + return _path; + } + + + /** Clear all entries from cache. + */ + public void clear() { + _loadedClasses.clear(); + } +} diff --git a/java/org/apache/tomcat/util/bcel/util/package.html b/java/org/apache/tomcat/util/bcel/util/package.html new file mode 100644 index 000000000..abef411d5 --- /dev/null +++ b/java/org/apache/tomcat/util/bcel/util/package.html @@ -0,0 +1,25 @@ + + + + + + +

      +This package contains utility classes for the +Byte Code Engineering +Library, namely: +

      +

      +

        +
      • Collection classes for JavaClass objects
      • +
      • A converter for class files to HTML
      • +
      • A tool to find instructions patterns via regular expressions
      • +
      • A class to find classes as defined in the CLASSPATH
      • +
      • A class loader that allows to create classes at run time
      • +
      + +

      + + -- 2.11.0