+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.classfile;
-
-import java.util.Stack;
-
-/**
- * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
- * applied to all components of a JavaClass object. I.e. this class supplies the
- * traversal strategy, other classes can make use of it.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- */
-public class DescendingVisitor implements Visitor
-{
- private JavaClass clazz;
-
- private Visitor visitor;
-
- private Stack stack = new Stack();
-
- /**
- * @return container of current entitity, i.e., predecessor during traversal
- */
- public Object predecessor()
- {
- return predecessor(0);
- }
-
- /**
- * @param level
- * nesting level, i.e., 0 returns the direct predecessor
- * @return container of current entitity, i.e., predecessor during traversal
- */
- public Object predecessor(int level)
- {
- int size = stack.size();
- if ((size < 2) || (level < 0))
- {
- return null;
- }
- else
- {
- return stack.elementAt(size - (level + 2)); // size - 1 == current
- }
- }
-
- /**
- * @return current object
- */
- public Object current()
- {
- return stack.peek();
- }
-
- /**
- * @param clazz
- * Class to traverse
- * @param visitor
- * visitor object to apply to all components
- */
- public DescendingVisitor(JavaClass clazz, Visitor visitor)
- {
- this.clazz = clazz;
- this.visitor = visitor;
- }
-
- /**
- * Start traversal.
- */
- public void visit()
- {
- clazz.accept(this);
- }
-
- public void visitJavaClass(JavaClass _clazz)
- {
- stack.push(_clazz);
- _clazz.accept(visitor);
- Field[] fields = _clazz.getFields();
- for (int i = 0; i < fields.length; i++)
- {
- fields[i].accept(this);
- }
- Method[] methods = _clazz.getMethods();
- for (int i = 0; i < methods.length; i++)
- {
- methods[i].accept(this);
- }
- Attribute[] attributes = _clazz.getAttributes();
- for (int i = 0; i < attributes.length; i++)
- {
- attributes[i].accept(this);
- }
- _clazz.getConstantPool().accept(this);
- stack.pop();
- }
-
- public void visitAnnotation(Annotations annotation)
- {
- stack.push(annotation);
- annotation.accept(visitor);
- AnnotationEntry[] entries = annotation.getAnnotationEntries();
- for (int i = 0; i < entries.length; i++)
- {
- entries[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitAnnotationEntry(AnnotationEntry annotationEntry)
- {
- stack.push(annotationEntry);
- annotationEntry.accept(visitor);
- stack.pop();
- }
-
- public void visitField(Field field)
- {
- stack.push(field);
- field.accept(visitor);
- Attribute[] attributes = field.getAttributes();
- for (int i = 0; i < attributes.length; i++)
- {
- attributes[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitConstantValue(ConstantValue cv)
- {
- stack.push(cv);
- cv.accept(visitor);
- stack.pop();
- }
-
- public void visitMethod(Method method)
- {
- stack.push(method);
- method.accept(visitor);
- Attribute[] attributes = method.getAttributes();
- for (int i = 0; i < attributes.length; i++)
- {
- attributes[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitExceptionTable(ExceptionTable table)
- {
- stack.push(table);
- table.accept(visitor);
- stack.pop();
- }
-
- public void visitCode(Code code)
- {
- stack.push(code);
- code.accept(visitor);
- CodeException[] table = code.getExceptionTable();
- for (int i = 0; i < table.length; i++)
- {
- table[i].accept(this);
- }
- Attribute[] attributes = code.getAttributes();
- for (int i = 0; i < attributes.length; i++)
- {
- attributes[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitCodeException(CodeException ce)
- {
- stack.push(ce);
- ce.accept(visitor);
- stack.pop();
- }
-
- public void visitLineNumberTable(LineNumberTable table)
- {
- stack.push(table);
- table.accept(visitor);
- LineNumber[] numbers = table.getLineNumberTable();
- for (int i = 0; i < numbers.length; i++)
- {
- numbers[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitLineNumber(LineNumber number)
- {
- stack.push(number);
- number.accept(visitor);
- stack.pop();
- }
-
- public void visitLocalVariableTable(LocalVariableTable table)
- {
- stack.push(table);
- table.accept(visitor);
- LocalVariable[] vars = table.getLocalVariableTable();
- for (int i = 0; i < vars.length; i++)
- {
- vars[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitStackMap(StackMap table)
- {
- stack.push(table);
- table.accept(visitor);
- StackMapEntry[] vars = table.getStackMap();
- for (int i = 0; i < vars.length; i++)
- {
- vars[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitStackMapEntry(StackMapEntry var)
- {
- stack.push(var);
- var.accept(visitor);
- stack.pop();
- }
-
- public void visitStackMapTable(StackMapTable table)
- {
- stack.push(table);
- table.accept(visitor);
- StackMapTableEntry[] vars = table.getStackMapTable();
- for (int i = 0; i < vars.length; i++)
- {
- vars[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitStackMapTableEntry(StackMapTableEntry var)
- {
- stack.push(var);
- var.accept(visitor);
- stack.pop();
- }
-
- public void visitLocalVariable(LocalVariable var)
- {
- stack.push(var);
- var.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantPool(ConstantPool cp)
- {
- stack.push(cp);
- cp.accept(visitor);
- Constant[] constants = cp.getConstantPool();
- for (int i = 1; i < constants.length; i++)
- {
- if (constants[i] != null)
- {
- constants[i].accept(this);
- }
- }
- stack.pop();
- }
-
- public void visitConstantClass(ConstantClass constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantDouble(ConstantDouble constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantFieldref(ConstantFieldref constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantFloat(ConstantFloat constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantInteger(ConstantInteger constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantInterfaceMethodref(
- ConstantInterfaceMethodref constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantLong(ConstantLong constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantMethodref(ConstantMethodref constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantNameAndType(ConstantNameAndType constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantString(ConstantString constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitConstantUtf8(ConstantUtf8 constant)
- {
- stack.push(constant);
- constant.accept(visitor);
- stack.pop();
- }
-
- public void visitInnerClasses(InnerClasses ic)
- {
- stack.push(ic);
- ic.accept(visitor);
- InnerClass[] ics = ic.getInnerClasses();
- for (int i = 0; i < ics.length; i++)
- {
- ics[i].accept(this);
- }
- stack.pop();
- }
-
- public void visitInnerClass(InnerClass inner)
- {
- stack.push(inner);
- inner.accept(visitor);
- stack.pop();
- }
-
- public void visitDeprecated(Deprecated attribute)
- {
- stack.push(attribute);
- attribute.accept(visitor);
- stack.pop();
- }
-
- public void visitSignature(Signature attribute)
- {
- stack.push(attribute);
- attribute.accept(visitor);
- stack.pop();
- }
-
- public void visitSourceFile(SourceFile attribute)
- {
- stack.push(attribute);
- attribute.accept(visitor);
- stack.pop();
- }
-
- public void visitSynthetic(Synthetic attribute)
- {
- stack.push(attribute);
- attribute.accept(visitor);
- stack.pop();
- }
-
- public void visitUnknown(Unknown attribute)
- {
- stack.push(attribute);
- attribute.accept(visitor);
- stack.pop();
- }
-
- public void visitAnnotationDefault(AnnotationDefault obj)
- {
- stack.push(obj);
- obj.accept(visitor);
- stack.pop();
- }
-
- public void visitEnclosingMethod(EnclosingMethod obj)
- {
- stack.push(obj);
- obj.accept(visitor);
- stack.pop();
- }
-
- public void visitLocalVariableTypeTable(LocalVariableTypeTable obj)
- {
- stack.push(obj);
- obj.accept(visitor);
- stack.pop();
- }
-
- public void visitParameterAnnotation(ParameterAnnotations obj)
- {
- stack.push(obj);
- obj.accept(visitor);
- stack.pop();
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.generic;
-
-import org.apache.tomcat.util.bcel.Constants;
-
-/**
- * Instances of this class may be used, e.g., to generate typed
- * versions of instructions. Its main purpose is to be used as the
- * byte code generating backend of a compiler. You can subclass it to
- * add your own create methods.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see Constants
- */
-public class InstructionFactory implements InstructionConstants, java.io.Serializable {
-
- private static final String[] short_names = {
- "C", "F", "D", "B", "S", "I", "L"
- };
-
- protected ClassGen cg;
- protected ConstantPoolGen cp;
-
-
- public InstructionFactory(ClassGen cg, ConstantPoolGen cp) {
- this.cg = cg;
- this.cp = cp;
- }
-
-
- /** Initialize with ClassGen object
- */
- public InstructionFactory(ClassGen cg) {
- this(cg, cg.getConstantPool());
- }
-
-
- /** Initialize just with ConstantPoolGen object
- */
- public InstructionFactory(ConstantPoolGen cp) {
- this(null, cp);
- }
-
-
- /** Create an invoke instruction.
- *
- * @param class_name name of the called class
- * @param name name of the called method
- * @param ret_type return type of method
- * @param arg_types argument types of method
- * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
- * or INVOKESPECIAL
- * @see Constants
- */
- public InvokeInstruction createInvoke( String class_name, String name, Type ret_type,
- Type[] arg_types, short kind ) {
- int index;
- int nargs = 0;
- String signature = Type.getMethodSignature(ret_type, arg_types);
- for (int i = 0; i < arg_types.length; i++) {
- nargs += arg_types[i].getSize();
- }
- if (kind == Constants.INVOKEINTERFACE) {
- index = cp.addInterfaceMethodref(class_name, name, signature);
- } else {
- index = cp.addMethodref(class_name, name, signature);
- }
- switch (kind) {
- case Constants.INVOKESPECIAL:
- return new INVOKESPECIAL(index);
- case Constants.INVOKEVIRTUAL:
- return new INVOKEVIRTUAL(index);
- case Constants.INVOKESTATIC:
- return new INVOKESTATIC(index);
- case Constants.INVOKEINTERFACE:
- return new INVOKEINTERFACE(index, nargs + 1);
- default:
- throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
- }
- }
-
-
- /** Create a call to the most popular System.out.println() method.
- *
- * @param s the string to print
- */
- public InstructionList createPrintln( String s ) {
- InstructionList il = new InstructionList();
- int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
- int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
- il.append(new GETSTATIC(out));
- il.append(new PUSH(cp, s));
- il.append(new INVOKEVIRTUAL(println));
- return il;
- }
-
-
- /** Uses PUSH to push a constant value onto the stack.
- * @param value must be of type Number, Boolean, Character or String
- */
- public Instruction createConstant( Object value ) {
- PUSH push;
- if (value instanceof Number) {
- push = new PUSH(cp, (Number) value);
- } else if (value instanceof String) {
- push = new PUSH(cp, (String) value);
- } else if (value instanceof Boolean) {
- push = new PUSH(cp, (Boolean) value);
- } else if (value instanceof Character) {
- push = new PUSH(cp, (Character) value);
- } else {
- throw new ClassGenException("Illegal type: " + value.getClass());
- }
- return push.getInstruction();
- }
-
- private static class MethodObject {
-
- Type[] arg_types;
- Type result_type;
- String class_name;
- String name;
- int access;
-
-
- MethodObject(String c, String n, Type r, Type[] a, int acc) {
- class_name = c;
- name = n;
- result_type = r;
- arg_types = a;
- access = acc;
- }
- }
-
-
- private InvokeInstruction createInvoke( MethodObject m, short kind ) {
- return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
- }
-
- private static MethodObject[] append_mos = {
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.STRING
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.OBJECT
- }, Constants.ACC_PUBLIC),
- null,
- null, // indices 2, 3
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.BOOLEAN
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.CHAR
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.FLOAT
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.DOUBLE
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.INT
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte)
- new Type[] {
- Type.INT
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short)
- new Type[] {
- Type.INT
- }, Constants.ACC_PUBLIC),
- new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, new Type[] {
- Type.LONG
- }, Constants.ACC_PUBLIC)
- };
-
-
- private static final boolean isString( Type type ) {
- return ((type instanceof ObjectType) && ((ObjectType) type).getClassName().equals(
- "java.lang.String"));
- }
-
-
- public Instruction createAppend( Type type ) {
- byte t = type.getType();
- if (isString(type)) {
- return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL);
- }
- switch (t) {
- case Constants.T_BOOLEAN:
- case Constants.T_CHAR:
- case Constants.T_FLOAT:
- case Constants.T_DOUBLE:
- case Constants.T_BYTE:
- case Constants.T_SHORT:
- case Constants.T_INT:
- case Constants.T_LONG:
- return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL);
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL);
- default:
- throw new RuntimeException("Oops: No append for this type? " + type);
- }
- }
-
-
- /** Create a field instruction.
- *
- * @param class_name name of the accessed class
- * @param name name of the referenced field
- * @param type type of field
- * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
- * @see Constants
- */
- public FieldInstruction createFieldAccess( String class_name, String name, Type type, short kind ) {
- int index;
- String signature = type.getSignature();
- index = cp.addFieldref(class_name, name, signature);
- switch (kind) {
- case Constants.GETFIELD:
- return new GETFIELD(index);
- case Constants.PUTFIELD:
- return new PUTFIELD(index);
- case Constants.GETSTATIC:
- return new GETSTATIC(index);
- case Constants.PUTSTATIC:
- return new PUTSTATIC(index);
- default:
- throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
- }
- }
-
-
- /** Create reference to `this'
- */
- public static Instruction createThis() {
- return new ALOAD(0);
- }
-
-
- /** Create typed return
- */
- public static ReturnInstruction createReturn( Type type ) {
- switch (type.getType()) {
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return ARETURN;
- case Constants.T_INT:
- case Constants.T_SHORT:
- case Constants.T_BOOLEAN:
- case Constants.T_CHAR:
- case Constants.T_BYTE:
- return IRETURN;
- case Constants.T_FLOAT:
- return FRETURN;
- case Constants.T_DOUBLE:
- return DRETURN;
- case Constants.T_LONG:
- return LRETURN;
- case Constants.T_VOID:
- return RETURN;
- default:
- throw new RuntimeException("Invalid type: " + type);
- }
- }
-
-
- private static final ArithmeticInstruction createBinaryIntOp( char first, String op ) {
- switch (first) {
- case '-':
- return ISUB;
- case '+':
- return IADD;
- case '%':
- return IREM;
- case '*':
- return IMUL;
- case '/':
- return IDIV;
- case '&':
- return IAND;
- case '|':
- return IOR;
- case '^':
- return IXOR;
- case '<':
- return ISHL;
- case '>':
- return op.equals(">>>")
- ? (ArithmeticInstruction) IUSHR
- : (ArithmeticInstruction) ISHR;
- default:
- throw new RuntimeException("Invalid operand " + op);
- }
- }
-
-
- private static final ArithmeticInstruction createBinaryLongOp( char first, String op ) {
- switch (first) {
- case '-':
- return LSUB;
- case '+':
- return LADD;
- case '%':
- return LREM;
- case '*':
- return LMUL;
- case '/':
- return LDIV;
- case '&':
- return LAND;
- case '|':
- return LOR;
- case '^':
- return LXOR;
- case '<':
- return LSHL;
- case '>':
- return op.equals(">>>")
- ? (ArithmeticInstruction) LUSHR
- : (ArithmeticInstruction) LSHR;
- default:
- throw new RuntimeException("Invalid operand " + op);
- }
- }
-
-
- private static final ArithmeticInstruction createBinaryFloatOp( char op ) {
- switch (op) {
- case '-':
- return FSUB;
- case '+':
- return FADD;
- case '*':
- return FMUL;
- case '/':
- return FDIV;
- case '%':
- return FREM;
- default:
- throw new RuntimeException("Invalid operand " + op);
- }
- }
-
-
- private static final ArithmeticInstruction createBinaryDoubleOp( char op ) {
- switch (op) {
- case '-':
- return DSUB;
- case '+':
- return DADD;
- case '*':
- return DMUL;
- case '/':
- return DDIV;
- case '%':
- return DREM;
- default:
- throw new RuntimeException("Invalid operand " + op);
- }
- }
-
-
- /**
- * Create binary operation for simple basic types, such as int and float.
- *
- * @param op operation, such as "+", "*", "<<", etc.
- */
- public static ArithmeticInstruction createBinaryOperation( String op, Type type ) {
- char first = op.toCharArray()[0];
- switch (type.getType()) {
- case Constants.T_BYTE:
- case Constants.T_SHORT:
- case Constants.T_INT:
- case Constants.T_CHAR:
- return createBinaryIntOp(first, op);
- case Constants.T_LONG:
- return createBinaryLongOp(first, op);
- case Constants.T_FLOAT:
- return createBinaryFloatOp(first);
- case Constants.T_DOUBLE:
- return createBinaryDoubleOp(first);
- default:
- throw new RuntimeException("Invalid type " + type);
- }
- }
-
-
- /**
- * @param size size of operand, either 1 (int, e.g.) or 2 (double)
- */
- public static StackInstruction createPop( int size ) {
- return (size == 2) ? (StackInstruction) POP2 : (StackInstruction) POP;
- }
-
-
- /**
- * @param size size of operand, either 1 (int, e.g.) or 2 (double)
- */
- public static StackInstruction createDup( int size ) {
- return (size == 2) ? (StackInstruction) DUP2 : (StackInstruction) DUP;
- }
-
-
- /**
- * @param size size of operand, either 1 (int, e.g.) or 2 (double)
- */
- public static StackInstruction createDup_2( int size ) {
- return (size == 2) ? (StackInstruction) DUP2_X2 : (StackInstruction) DUP_X2;
- }
-
-
- /**
- * @param size size of operand, either 1 (int, e.g.) or 2 (double)
- */
- public static StackInstruction createDup_1( int size ) {
- return (size == 2) ? (StackInstruction) DUP2_X1 : (StackInstruction) DUP_X1;
- }
-
-
- /**
- * @param index index of local variable
- */
- public static LocalVariableInstruction createStore( Type type, int index ) {
- switch (type.getType()) {
- case Constants.T_BOOLEAN:
- case Constants.T_CHAR:
- case Constants.T_BYTE:
- case Constants.T_SHORT:
- case Constants.T_INT:
- return new ISTORE(index);
- case Constants.T_FLOAT:
- return new FSTORE(index);
- case Constants.T_DOUBLE:
- return new DSTORE(index);
- case Constants.T_LONG:
- return new LSTORE(index);
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return new ASTORE(index);
- default:
- throw new RuntimeException("Invalid type " + type);
- }
- }
-
-
- /**
- * @param index index of local variable
- */
- public static LocalVariableInstruction createLoad( Type type, int index ) {
- switch (type.getType()) {
- case Constants.T_BOOLEAN:
- case Constants.T_CHAR:
- case Constants.T_BYTE:
- case Constants.T_SHORT:
- case Constants.T_INT:
- return new ILOAD(index);
- case Constants.T_FLOAT:
- return new FLOAD(index);
- case Constants.T_DOUBLE:
- return new DLOAD(index);
- case Constants.T_LONG:
- return new LLOAD(index);
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return new ALOAD(index);
- default:
- throw new RuntimeException("Invalid type " + type);
- }
- }
-
-
- /**
- * @param type type of elements of array, i.e., array.getElementType()
- */
- public static ArrayInstruction createArrayLoad( Type type ) {
- switch (type.getType()) {
- case Constants.T_BOOLEAN:
- case Constants.T_BYTE:
- return BALOAD;
- case Constants.T_CHAR:
- return CALOAD;
- case Constants.T_SHORT:
- return SALOAD;
- case Constants.T_INT:
- return IALOAD;
- case Constants.T_FLOAT:
- return FALOAD;
- case Constants.T_DOUBLE:
- return DALOAD;
- case Constants.T_LONG:
- return LALOAD;
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return AALOAD;
- default:
- throw new RuntimeException("Invalid type " + type);
- }
- }
-
-
- /**
- * @param type type of elements of array, i.e., array.getElementType()
- */
- public static ArrayInstruction createArrayStore( Type type ) {
- switch (type.getType()) {
- case Constants.T_BOOLEAN:
- case Constants.T_BYTE:
- return BASTORE;
- case Constants.T_CHAR:
- return CASTORE;
- case Constants.T_SHORT:
- return SASTORE;
- case Constants.T_INT:
- return IASTORE;
- case Constants.T_FLOAT:
- return FASTORE;
- case Constants.T_DOUBLE:
- return DASTORE;
- case Constants.T_LONG:
- return LASTORE;
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return AASTORE;
- default:
- throw new RuntimeException("Invalid type " + type);
- }
- }
-
-
- /** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g.,
- * if the operands are basic types and CHECKCAST if they are reference types.
- */
- public Instruction createCast( Type src_type, Type dest_type ) {
- if ((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
- byte dest = dest_type.getType();
- byte src = src_type.getType();
- if (dest == Constants.T_LONG
- && (src == Constants.T_CHAR || src == Constants.T_BYTE || src == Constants.T_SHORT)) {
- src = Constants.T_INT;
- }
- String name = "org.apache.tomcat.util.bcel.generic." + short_names[src - Constants.T_CHAR] + "2"
- + short_names[dest - Constants.T_CHAR];
- Instruction i = null;
- try {
- i = (Instruction) java.lang.Class.forName(name).newInstance();
- } catch (Exception e) {
- throw new RuntimeException("Could not find instruction: " + name, e);
- }
- return i;
- } else if ((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
- if (dest_type instanceof ArrayType) {
- return new CHECKCAST(cp.addArrayClass((ArrayType) dest_type));
- } else {
- return new CHECKCAST(cp.addClass(((ObjectType) dest_type).getClassName()));
- }
- } else {
- throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
- }
- }
-
-
- public GETFIELD createGetField( String class_name, String name, Type t ) {
- return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
- }
-
-
- public GETSTATIC createGetStatic( String class_name, String name, Type t ) {
- return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
- }
-
-
- public PUTFIELD createPutField( String class_name, String name, Type t ) {
- return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
- }
-
-
- public PUTSTATIC createPutStatic( String class_name, String name, Type t ) {
- return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
- }
-
-
- public CHECKCAST createCheckCast( ReferenceType t ) {
- if (t instanceof ArrayType) {
- return new CHECKCAST(cp.addArrayClass((ArrayType) t));
- } else {
- return new CHECKCAST(cp.addClass((ObjectType) t));
- }
- }
-
-
- public INSTANCEOF createInstanceOf( ReferenceType t ) {
- if (t instanceof ArrayType) {
- return new INSTANCEOF(cp.addArrayClass((ArrayType) t));
- } else {
- return new INSTANCEOF(cp.addClass((ObjectType) t));
- }
- }
-
-
- public NEW createNew( ObjectType t ) {
- return new NEW(cp.addClass(t));
- }
-
-
- public NEW createNew( String s ) {
- return createNew(new ObjectType(s));
- }
-
-
- /** Create new array of given size and type.
- * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction
- */
- public Instruction createNewArray( Type t, short dim ) {
- if (dim == 1) {
- if (t instanceof ObjectType) {
- return new ANEWARRAY(cp.addClass((ObjectType) t));
- } else if (t instanceof ArrayType) {
- return new ANEWARRAY(cp.addArrayClass((ArrayType) t));
- } else {
- return new NEWARRAY(((BasicType) t).getType());
- }
- } else {
- ArrayType at;
- if (t instanceof ArrayType) {
- at = (ArrayType) t;
- } else {
- at = new ArrayType(t, dim);
- }
- return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
- }
- }
-
-
- /** Create "null" value for reference types, 0 for basic types like int
- */
- public static Instruction createNull( Type type ) {
- switch (type.getType()) {
- case Constants.T_ARRAY:
- case Constants.T_OBJECT:
- return ACONST_NULL;
- case Constants.T_INT:
- case Constants.T_SHORT:
- case Constants.T_BOOLEAN:
- case Constants.T_CHAR:
- case Constants.T_BYTE:
- return ICONST_0;
- case Constants.T_FLOAT:
- return FCONST_0;
- case Constants.T_DOUBLE:
- return DCONST_0;
- case Constants.T_LONG:
- return LCONST_0;
- case Constants.T_VOID:
- return NOP;
- default:
- throw new RuntimeException("Invalid type: " + type);
- }
- }
-
-
- /** Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH.
- * For those you should use the SWITCH compound instruction.
- */
- public static BranchInstruction createBranchInstruction( short opcode, InstructionHandle target ) {
- switch (opcode) {
- case Constants.IFEQ:
- return new IFEQ(target);
- case Constants.IFNE:
- return new IFNE(target);
- case Constants.IFLT:
- return new IFLT(target);
- case Constants.IFGE:
- return new IFGE(target);
- case Constants.IFGT:
- return new IFGT(target);
- case Constants.IFLE:
- return new IFLE(target);
- case Constants.IF_ICMPEQ:
- return new IF_ICMPEQ(target);
- case Constants.IF_ICMPNE:
- return new IF_ICMPNE(target);
- case Constants.IF_ICMPLT:
- return new IF_ICMPLT(target);
- case Constants.IF_ICMPGE:
- return new IF_ICMPGE(target);
- case Constants.IF_ICMPGT:
- return new IF_ICMPGT(target);
- case Constants.IF_ICMPLE:
- return new IF_ICMPLE(target);
- case Constants.IF_ACMPEQ:
- return new IF_ACMPEQ(target);
- case Constants.IF_ACMPNE:
- return new IF_ACMPNE(target);
- case Constants.GOTO:
- return new GOTO(target);
- case Constants.JSR:
- return new JSR(target);
- case Constants.IFNULL:
- return new IFNULL(target);
- case Constants.IFNONNULL:
- return new IFNONNULL(target);
- case Constants.GOTO_W:
- return new GOTO_W(target);
- case Constants.JSR_W:
- return new JSR_W(target);
- default:
- throw new RuntimeException("Invalid opcode: " + opcode);
- }
- }
-
-
- public void setClassGen( ClassGen c ) {
- cg = c;
- }
-
-
- public ClassGen getClassGen() {
- return cg;
- }
-
-
- public void setConstantPool( ConstantPoolGen c ) {
- cp = c;
- }
-
-
- public ConstantPoolGen getConstantPool() {
- return cp;
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.generic;
-
-/**
- * SWITCH - Branch depending on int value, generates either LOOKUPSWITCH or
- * TABLESWITCH instruction, depending on whether the match values (int[]) can be
- * sorted with no gaps between the numbers.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- */
-public final class SWITCH implements CompoundInstruction {
-
- private int[] match;
- private InstructionHandle[] targets;
- private Select instruction;
- private int match_length;
-
-
- /**
- * Template for switch() constructs. If the match array can be
- * sorted in ascending order with gaps no larger than max_gap
- * between the numbers, a TABLESWITCH instruction is generated, and
- * a LOOKUPSWITCH otherwise. The former may be more efficient, but
- * needs more space.
- *
- * Note, that the key array always will be sorted, though we leave
- * the original arrays unaltered.
- *
- * @param match array of match values (case 2: ... case 7: ..., etc.)
- * @param targets the instructions to be branched to for each case
- * @param target the default target
- * @param max_gap maximum gap that may between case branches
- */
- public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target, int max_gap) {
- this.match = (int[]) match.clone();
- this.targets = (InstructionHandle[]) targets.clone();
- if ((match_length = match.length) < 2) {
- instruction = new TABLESWITCH(match, targets, target);
- } else {
- sort(0, match_length - 1);
- if (matchIsOrdered(max_gap)) {
- fillup(max_gap, target);
- instruction = new TABLESWITCH(this.match, this.targets, target);
- } else {
- instruction = new LOOKUPSWITCH(this.match, this.targets, target);
- }
- }
- }
-
-
- public SWITCH(int[] match, InstructionHandle[] targets, InstructionHandle target) {
- this(match, targets, target, 1);
- }
-
-
- private final void fillup( int max_gap, InstructionHandle target ) {
- int max_size = match_length + match_length * max_gap;
- int[] m_vec = new int[max_size];
- InstructionHandle[] t_vec = new InstructionHandle[max_size];
- int count = 1;
- m_vec[0] = match[0];
- t_vec[0] = targets[0];
- for (int i = 1; i < match_length; i++) {
- int prev = match[i - 1];
- int gap = match[i] - prev;
- for (int j = 1; j < gap; j++) {
- m_vec[count] = prev + j;
- t_vec[count] = target;
- count++;
- }
- m_vec[count] = match[i];
- t_vec[count] = targets[i];
- count++;
- }
- match = new int[count];
- targets = new InstructionHandle[count];
- System.arraycopy(m_vec, 0, match, 0, count);
- System.arraycopy(t_vec, 0, targets, 0, count);
- }
-
-
- /**
- * Sort match and targets array with QuickSort.
- */
- private final void sort( int l, int r ) {
- int i = l, j = r;
- int h, m = match[(l + r) / 2];
- InstructionHandle h2;
- do {
- while (match[i] < m) {
- i++;
- }
- while (m < match[j]) {
- j--;
- }
- if (i <= j) {
- h = match[i];
- match[i] = match[j];
- match[j] = h; // Swap elements
- h2 = targets[i];
- targets[i] = targets[j];
- targets[j] = h2; // Swap instructions, too
- i++;
- j--;
- }
- } while (i <= j);
- if (l < j) {
- sort(l, j);
- }
- if (i < r) {
- sort(i, r);
- }
- }
-
-
- /**
- * @return match is sorted in ascending order with no gap bigger than max_gap?
- */
- private final boolean matchIsOrdered( int max_gap ) {
- for (int i = 1; i < match_length; i++) {
- if (match[i] - match[i - 1] > max_gap) {
- return false;
- }
- }
- return true;
- }
-
-
- public final InstructionList getInstructionList() {
- return new InstructionList(instruction);
- }
-
-
- public final Instruction getInstruction() {
- return instruction;
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import org.apache.tomcat.util.bcel.classfile.Attribute;
-import org.apache.tomcat.util.bcel.classfile.Code;
-import org.apache.tomcat.util.bcel.classfile.CodeException;
-import org.apache.tomcat.util.bcel.classfile.ConstantPool;
-import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
-import org.apache.tomcat.util.bcel.classfile.ConstantValue;
-import org.apache.tomcat.util.bcel.classfile.ExceptionTable;
-import org.apache.tomcat.util.bcel.classfile.InnerClass;
-import org.apache.tomcat.util.bcel.classfile.InnerClasses;
-import org.apache.tomcat.util.bcel.classfile.LineNumber;
-import org.apache.tomcat.util.bcel.classfile.LineNumberTable;
-import org.apache.tomcat.util.bcel.classfile.LocalVariable;
-import org.apache.tomcat.util.bcel.classfile.LocalVariableTable;
-import org.apache.tomcat.util.bcel.classfile.SourceFile;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * Convert found attributes into HTML file.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- *
- */
-final class AttributeHTML implements org.apache.tomcat.util.bcel.Constants {
-
- private String class_name; // name of current class
- private PrintWriter file; // file to write to
- private int attr_count = 0;
- private ConstantHTML constant_html;
- private ConstantPool constant_pool;
-
-
- AttributeHTML(String dir, String class_name, ConstantPool constant_pool,
- ConstantHTML constant_html) throws IOException {
- this.class_name = class_name;
- this.constant_pool = constant_pool;
- this.constant_html = constant_html;
- file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
- file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
- }
-
-
- private final String codeLink( int link, int method_number ) {
- return "<A HREF=\"" + class_name + "_code.html#code" + method_number + "@" + link
- + "\" TARGET=Code>" + link + "</A>";
- }
-
-
- final void close() {
- file.println("</TABLE></BODY></HTML>");
- file.close();
- }
-
-
- final void writeAttribute( Attribute attribute, String anchor ) throws IOException {
- writeAttribute(attribute, anchor, 0);
- }
-
-
- final void writeAttribute( Attribute attribute, String anchor, int method_number )
- throws IOException {
- byte tag = attribute.getTag();
- int index;
- if (tag == ATTR_UNKNOWN) {
- return;
- }
- attr_count++; // Increment number of attributes found so far
- if (attr_count % 2 == 0) {
- file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
- } else {
- file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
- }
- file.println("<H4><A NAME=\"" + anchor + "\">" + attr_count + " " + ATTRIBUTE_NAMES[tag]
- + "</A></H4>");
- /* Handle different attributes
- */
- switch (tag) {
- case ATTR_CODE:
- Code c = (Code) attribute;
- // Some directly printable values
- file.print("<UL><LI>Maximum stack size = " + c.getMaxStack()
- + "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
- + "</LI>\n<LI><A HREF=\"" + class_name + "_code.html#method"
- + method_number + "\" TARGET=Code>Byte code</A></LI></UL>\n");
- // Get handled exceptions and list them
- CodeException[] ce = c.getExceptionTable();
- int len = ce.length;
- if (len > 0) {
- file.print("<P><B>Exceptions handled</B><UL>");
- for (int i = 0; i < len; i++) {
- int catch_type = ce[i].getCatchType(); // Index in constant pool
- file.print("<LI>");
- if (catch_type != 0) {
- file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html
- } else {
- file.print("Any Exception");
- }
- file.print("<BR>(Ranging from lines "
- + codeLink(ce[i].getStartPC(), method_number) + " to "
- + codeLink(ce[i].getEndPC(), method_number) + ", handled at line "
- + codeLink(ce[i].getHandlerPC(), method_number) + ")</LI>");
- }
- file.print("</UL>");
- }
- break;
- case ATTR_CONSTANT_VALUE:
- index = ((ConstantValue) attribute).getConstantValueIndex();
- // Reference _cp.html
- file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
- + "\" TARGET=\"ConstantPool\">Constant value index(" + index
- + ")</A></UL>\n");
- break;
- case ATTR_SOURCE_FILE:
- index = ((SourceFile) attribute).getSourceFileIndex();
- // Reference _cp.html
- file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
- + "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
- break;
- case ATTR_EXCEPTIONS:
- // List thrown exceptions
- int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
- file.print("<UL>");
- for (int i = 0; i < indices.length; i++) {
- file.print("<LI><A HREF=\"" + class_name + "_cp.html#cp" + indices[i]
- + "\" TARGET=\"ConstantPool\">Exception class index(" + indices[i]
- + ")</A>\n");
- }
- file.print("</UL>\n");
- break;
- case ATTR_LINE_NUMBER_TABLE:
- LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable();
- // List line number pairs
- file.print("<P>");
- for (int i = 0; i < line_numbers.length; i++) {
- file.print("(" + line_numbers[i].getStartPC() + ", "
- + line_numbers[i].getLineNumber() + ")");
- if (i < line_numbers.length - 1) {
- file.print(", "); // breakable
- }
- }
- break;
- case ATTR_LOCAL_VARIABLE_TABLE:
- LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable();
- // List name, range and type
- file.print("<UL>");
- for (int i = 0; i < vars.length; i++) {
- index = vars[i].getSignatureIndex();
- String signature = ((ConstantUtf8) constant_pool.getConstant(index,
- CONSTANT_Utf8)).getBytes();
- signature = Utility.signatureToString(signature, false);
- int start = vars[i].getStartPC();
- int end = (start + vars[i].getLength());
- file.println("<LI>" + Class2HTML.referenceType(signature) + " <B>"
- + vars[i].getName() + "</B> in slot %" + vars[i].getIndex()
- + "<BR>Valid from lines " + "<A HREF=\"" + class_name
- + "_code.html#code" + method_number + "@" + start + "\" TARGET=Code>"
- + start + "</A> to " + "<A HREF=\"" + class_name + "_code.html#code"
- + method_number + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
- }
- file.print("</UL>\n");
- break;
- case ATTR_INNER_CLASSES:
- InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses();
- // List inner classes
- file.print("<UL>");
- for (int i = 0; i < classes.length; i++) {
- String name, access;
- index = classes[i].getInnerNameIndex();
- if (index > 0) {
- name = ((ConstantUtf8) constant_pool.getConstant(index, CONSTANT_Utf8))
- .getBytes();
- } else {
- name = "<anonymous>";
- }
- access = Utility.accessToString(classes[i].getInnerAccessFlags());
- file.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> "
- + constant_html.referenceConstant(classes[i].getInnerClassIndex())
- + " in class "
- + constant_html.referenceConstant(classes[i].getOuterClassIndex())
- + " named " + name + "</LI>\n");
- }
- file.print("</UL>\n");
- break;
- default: // Such as Unknown attribute or Deprecated
- file.print("<P>" + attribute.toString());
- }
- file.println("</TD></TR>");
- file.flush();
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import org.apache.tomcat.util.bcel.Constants;
-import org.apache.tomcat.util.bcel.classfile.Attribute;
-import org.apache.tomcat.util.bcel.classfile.ClassParser;
-import org.apache.tomcat.util.bcel.classfile.ConstantPool;
-import org.apache.tomcat.util.bcel.classfile.JavaClass;
-import org.apache.tomcat.util.bcel.classfile.Method;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * Read class file(s) and convert them into HTML files.
- *
- * Given a JavaClass object "class" that is in package "package" five files
- * will be created in the specified directory.
- *
- * <OL>
- * <LI> "package"."class".html as the main file which defines the frames for
- * the following subfiles.
- * <LI> "package"."class"_attributes.html contains all (known) attributes found in the file
- * <LI> "package"."class"_cp.html contains the constant pool
- * <LI> "package"."class"_code.html contains the byte code
- * <LI> "package"."class"_methods.html contains references to all methods and fields of the class
- * </OL>
- *
- * All subfiles reference each other appropiately, e.g. clicking on a
- * method in the Method's frame will jump to the appropiate method in
- * the Code frame.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- */
-public class Class2HTML implements Constants {
-
- private JavaClass java_class; // current class object
- private String dir;
- private static String class_package; // name of package, unclean to make it static, but ...
- private static String class_name; // name of current class, dito
- private static ConstantPool constant_pool;
-
-
- /**
- * Write contents of the given JavaClass into HTML files.
- *
- * @param java_class The class to write
- * @param dir The directory to put the files in
- */
- public Class2HTML(JavaClass java_class, String dir) throws IOException {
- Method[] methods = java_class.getMethods();
- this.java_class = java_class;
- this.dir = dir;
- class_name = java_class.getClassName(); // Remember full name
- constant_pool = java_class.getConstantPool();
- // Get package name by tacking off everything after the last `.'
- int index = class_name.lastIndexOf('.');
- if (index > -1) {
- class_package = class_name.substring(0, index);
- } else {
- class_package = ""; // default package
- }
- ConstantHTML constant_html = new ConstantHTML(dir, class_name, class_package, methods,
- constant_pool);
- /* Attributes can't be written in one step, so we just open a file
- * which will be written consequently.
- */
- AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool,
- constant_html);
-// MethodHTML method_html = new MethodHTML(dir, class_name, methods, java_class.getFields(),
-// constant_html, attribute_html);
- // Write main file (with frames, yuk)
- writeMainHTML(attribute_html);
- new CodeHTML(dir, class_name, methods, constant_pool, constant_html);
- attribute_html.close();
- }
-
-
- public static void main( String argv[] ) {
- String[] file_name = new String[argv.length];
- int files = 0;
- ClassParser parser = null;
- JavaClass java_class = null;
- String zip_file = null;
- char sep = System.getProperty("file.separator").toCharArray()[0];
- String dir = "." + sep; // Where to store HTML files
- try {
- /* Parse command line arguments.
- */
- for (int i = 0; i < argv.length; i++) {
- if (argv[i].charAt(0) == '-') { // command line switch
- if (argv[i].equals("-d")) { // Specify target directory, default `.�
- dir = argv[++i];
- if (!dir.endsWith("" + sep)) {
- dir = dir + sep;
- }
- new File(dir).mkdirs(); // Create target directory if necessary
- } else if (argv[i].equals("-zip")) {
- zip_file = argv[++i];
- } else {
- System.out.println("Unknown option " + argv[i]);
- }
- } else {
- file_name[files++] = argv[i];
- }
- }
- if (files == 0) {
- System.err.println("Class2HTML: No input files specified.");
- } else { // Loop through files ...
- for (int i = 0; i < files; i++) {
- System.out.print("Processing " + file_name[i] + "...");
- if (zip_file == null) {
- parser = new ClassParser(file_name[i]); // Create parser object from file
- } else {
- parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file
- }
- java_class = parser.parse();
- new Class2HTML(java_class, dir);
- System.out.println("Done.");
- }
- }
- } catch (Exception e) {
- System.out.println(e);
- e.printStackTrace(System.out);
- }
- }
-
-
- /**
- * Utility method that converts a class reference in the constant pool,
- * i.e., an index to a string.
- */
- static String referenceClass( int index ) {
- String str = constant_pool.getConstantString(index, CONSTANT_Class);
- str = Utility.compactClassName(str);
- str = Utility.compactClassName(str, class_package + ".", true);
- return "<A HREF=\"" + class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + str
- + "</A>";
- }
-
-
- static final String referenceType( String type ) {
- String short_type = Utility.compactClassName(type);
- short_type = Utility.compactClassName(short_type, class_package + ".", true);
- int index = type.indexOf('['); // Type is an array?
- String base_type = type;
- if (index > -1) {
- base_type = type.substring(0, index); // Tack of the `['
- }
- // test for basic type
- if (base_type.equals("int") || base_type.equals("short") || base_type.equals("boolean")
- || base_type.equals("void") || base_type.equals("char") || base_type.equals("byte")
- || base_type.equals("long") || base_type.equals("double")
- || base_type.equals("float")) {
- return "<FONT COLOR=\"#00FF00\">" + type + "</FONT>";
- } else {
- return "<A HREF=\"" + base_type + ".html\" TARGET=_top>" + short_type + "</A>";
- }
- }
-
-
- static String toHTML( String str ) {
- StringBuffer buf = new StringBuffer();
- try { // Filter any characters HTML doesn't like such as < and > in particular
- for (int i = 0; i < str.length(); i++) {
- char ch;
- switch (ch = str.charAt(i)) {
- case '<':
- buf.append("<");
- break;
- case '>':
- buf.append(">");
- break;
- case '\n':
- buf.append("\\n");
- break;
- case '\r':
- buf.append("\\r");
- break;
- default:
- buf.append(ch);
- }
- }
- } catch (StringIndexOutOfBoundsException e) {
- } // Never occurs
- return buf.toString();
- }
-
-
- private void writeMainHTML( AttributeHTML attribute_html ) throws IOException {
- PrintWriter file = new PrintWriter(new FileOutputStream(dir + class_name + ".html"));
- Attribute[] attributes = java_class.getAttributes();
- file.println("<HTML>\n" + "<HEAD><TITLE>Documentation for " + class_name + "</TITLE>"
- + "</HEAD>\n" + "<FRAMESET BORDER=1 cols=\"30%,*\">\n"
- + "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"ConstantPool\" SRC=\""
- + class_name + "_cp.html" + "\"\n MARGINWIDTH=\"0\" "
- + "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n"
- + "<FRAME NAME=\"Attributes\" SRC=\"" + class_name + "_attributes.html"
- + "\"\n MARGINWIDTH=\"0\" "
- + "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n" + "</FRAMESET>\n"
- + "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"Code\" SRC=\""
- + class_name + "_code.html\"\n MARGINWIDTH=0 "
- + "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
- + "<FRAME NAME=\"Methods\" SRC=\"" + class_name
- + "_methods.html\"\n MARGINWIDTH=0 "
- + "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
- + "</FRAMESET></FRAMESET></HTML>");
- file.close();
- for (int i = 0; i < attributes.length; i++) {
- attribute_html.writeAttribute(attributes[i], "class" + i);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.ByteArrayInputStream;
-import java.util.Hashtable;
-import org.apache.tomcat.util.bcel.Constants;
-import org.apache.tomcat.util.bcel.classfile.ClassParser;
-import org.apache.tomcat.util.bcel.classfile.ConstantClass;
-import org.apache.tomcat.util.bcel.classfile.ConstantPool;
-import org.apache.tomcat.util.bcel.classfile.ConstantUtf8;
-import org.apache.tomcat.util.bcel.classfile.JavaClass;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * <p>Drop in replacement for the standard class loader of the JVM. You can use it
- * in conjunction with the JavaWrapper to dynamically modify/create classes
- * as they're requested.</p>
- *
- * <p>This class loader recognizes special requests in a distinct
- * format, i.e., when the name of the requested class contains with
- * "$$BCEL$$" it calls the createClass() method with that name
- * (everything bevor the $$BCEL$$ is considered to be the package
- * name. You can subclass the class loader and override that
- * method. "Normal" classes class can be modified by overriding the
- * modifyClass() method which is called just before defineClass().</p>
- *
- * <p>There may be a number of packages where you have to use the
- * default class loader (which may also be faster). You can define the
- * set of packages where to use the system class loader in the
- * constructor. The default value contains "java.", "sun.",
- * "javax."</p>
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see JavaWrapper
- * @see ClassPath
- */
-public class ClassLoader extends java.lang.ClassLoader {
-
- public static final String[] DEFAULT_IGNORED_PACKAGES = {
- "java.", "javax.", "sun."
- };
- private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe
- private String[] ignored_packages;
- private Repository repository = SyntheticRepository.getInstance();
-
-
- /** Ignored packages are by default ( "java.", "sun.",
- * "javax."), i.e. loaded by system class loader
- */
- public ClassLoader() {
- this(DEFAULT_IGNORED_PACKAGES);
- }
-
-
- /** @param deferTo delegate class loader to use for ignored packages
- */
- public ClassLoader(java.lang.ClassLoader deferTo) {
- super(deferTo);
- this.ignored_packages = DEFAULT_IGNORED_PACKAGES;
- this.repository = new ClassLoaderRepository(deferTo);
- }
-
-
- /** @param ignored_packages classes contained in these packages will be loaded
- * with the system class loader
- */
- public ClassLoader(String[] ignored_packages) {
- this.ignored_packages = ignored_packages;
- }
-
-
- /** @param ignored_packages classes contained in these packages will be loaded
- * with the system class loader
- * @param deferTo delegate class loader to use for ignored packages
- */
- public ClassLoader(java.lang.ClassLoader deferTo, String[] ignored_packages) {
- this(ignored_packages);
- this.repository = new ClassLoaderRepository(deferTo);
- }
-
-
- protected Class loadClass( String class_name, boolean resolve ) throws ClassNotFoundException {
- Class cl = null;
- /* First try: lookup hash table.
- */
- if ((cl = (Class) classes.get(class_name)) == null) {
- /* Second try: Load system class using system class loader. You better
- * don't mess around with them.
- */
- for (int i = 0; i < ignored_packages.length; i++) {
- if (class_name.startsWith(ignored_packages[i])) {
- cl = getParent().loadClass(class_name);
- break;
- }
- }
- if (cl == null) {
- JavaClass clazz = null;
- /* Third try: Special request?
- */
- if (class_name.indexOf("$$BCEL$$") >= 0) {
- clazz = createClass(class_name);
- } else { // Fourth try: Load classes via repository
- if ((clazz = repository.loadClass(class_name)) != null) {
- clazz = modifyClass(clazz);
- } else {
- throw new ClassNotFoundException(class_name);
- }
- }
- if (clazz != null) {
- byte[] bytes = clazz.getBytes();
- cl = defineClass(class_name, bytes, 0, bytes.length);
- } else {
- cl = Class.forName(class_name);
- }
- }
- if (resolve) {
- resolveClass(cl);
- }
- }
- classes.put(class_name, cl);
- return cl;
- }
-
-
- /** Override this method if you want to alter a class before it gets actually
- * loaded. Does nothing by default.
- */
- protected JavaClass modifyClass( JavaClass clazz ) {
- return clazz;
- }
-
-
- /**
- * Override this method to create you own classes on the fly. The
- * name contains the special token $$BCEL$$. Everything before that
- * token is consddered to be a package name. You can encode you own
- * arguments into the subsequent string. You must regard however not
- * to use any "illegal" characters, i.e., characters that may not
- * appear in a Java class name too<br>
- *
- * The default implementation interprets the string as a encoded compressed
- * Java class, unpacks and decodes it with the Utility.decode() method, and
- * parses the resulting byte array and returns the resulting JavaClass object.
- *
- * @param class_name compressed byte code with "$$BCEL$$" in it
- */
- protected JavaClass createClass( String class_name ) {
- int index = class_name.indexOf("$$BCEL$$");
- String real_name = class_name.substring(index + 8);
- JavaClass clazz = null;
- try {
- byte[] bytes = Utility.decode(real_name, true);
- ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
- clazz = parser.parse();
- } catch (Throwable e) {
- e.printStackTrace();
- return null;
- }
- // Adapt the class name to the passed value
- ConstantPool cp = clazz.getConstantPool();
- ConstantClass cl = (ConstantClass) cp.getConstant(clazz.getClassNameIndex(),
- Constants.CONSTANT_Class);
- ConstantUtf8 name = (ConstantUtf8) cp.getConstant(cl.getNameIndex(),
- Constants.CONSTANT_Utf8);
- name.setBytes(class_name.replace('.', '/'));
- return clazz;
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import org.apache.tomcat.util.bcel.classfile.JavaClass;
-
-/**
- * Utility class implementing a (typesafe) set of JavaClass objects.
- * Since JavaClass has no equals() method, the name of the class is
- * used for comparison.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see ClassStack
- */
-public class ClassSet implements java.io.Serializable {
-
- private Map _map = new HashMap();
-
-
- public boolean add( JavaClass clazz ) {
- boolean result = false;
- if (!_map.containsKey(clazz.getClassName())) {
- result = true;
- _map.put(clazz.getClassName(), clazz);
- }
- return result;
- }
-
-
- public void remove( JavaClass clazz ) {
- _map.remove(clazz.getClassName());
- }
-
-
- public boolean empty() {
- return _map.isEmpty();
- }
-
-
- public JavaClass[] toArray() {
- Collection values = _map.values();
- JavaClass[] classes = new JavaClass[values.size()];
- values.toArray(classes);
- return classes;
- }
-
-
- public String[] getClassNames() {
- return (String[]) _map.keySet().toArray(new String[_map.keySet().size()]);
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.util.Stack;
-import org.apache.tomcat.util.bcel.classfile.JavaClass;
-
-/**
- * Utility class implementing a (typesafe) stack of JavaClass objects.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see Stack
- */
-public class ClassStack implements java.io.Serializable {
-
- private Stack stack = new Stack();
-
-
- public void push( JavaClass clazz ) {
- stack.push(clazz);
- }
-
-
- public JavaClass pop() {
- return (JavaClass) stack.pop();
- }
-
-
- public JavaClass top() {
- return (JavaClass) stack.peek();
- }
-
-
- public boolean empty() {
- return stack.empty();
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.tomcat.util.bcel.classfile.JavaClass;
-
-/**
- * Utility class implementing a (typesafe) collection of JavaClass
- * objects. Contains the most important methods of a Vector.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- *
- * @deprecated as of 5.1.1 - 7/17/2005
- */
-public class ClassVector implements java.io.Serializable {
-
- protected List vec = new ArrayList();
-
-
- public void addElement( JavaClass clazz ) {
- vec.add(clazz);
- }
-
-
- public JavaClass elementAt( int index ) {
- return (JavaClass) vec.get(index);
- }
-
-
- public void removeElementAt( int index ) {
- vec.remove(index);
- }
-
-
- public JavaClass[] toArray() {
- JavaClass[] classes = new JavaClass[vec.size()];
- vec.toArray(classes);
- return classes;
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.BitSet;
-import org.apache.tomcat.util.bcel.classfile.Attribute;
-import org.apache.tomcat.util.bcel.classfile.Code;
-import org.apache.tomcat.util.bcel.classfile.CodeException;
-import org.apache.tomcat.util.bcel.classfile.ConstantFieldref;
-import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref;
-import org.apache.tomcat.util.bcel.classfile.ConstantMethodref;
-import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
-import org.apache.tomcat.util.bcel.classfile.ConstantPool;
-import org.apache.tomcat.util.bcel.classfile.LocalVariable;
-import org.apache.tomcat.util.bcel.classfile.LocalVariableTable;
-import org.apache.tomcat.util.bcel.classfile.Method;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * Convert code into HTML file.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- *
- */
-final class CodeHTML implements org.apache.tomcat.util.bcel.Constants {
-
- private String class_name; // name of current class
-// private Method[] methods; // Methods to print
- private PrintWriter file; // file to write to
- private BitSet goto_set;
- private ConstantPool constant_pool;
- private ConstantHTML constant_html;
- private static boolean wide = false;
-
-
- CodeHTML(String dir, String class_name, Method[] methods, ConstantPool constant_pool,
- ConstantHTML constant_html) throws IOException {
- this.class_name = class_name;
-// this.methods = methods;
- this.constant_pool = constant_pool;
- this.constant_html = constant_html;
- file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html"));
- file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\">");
- for (int i = 0; i < methods.length; i++) {
- writeMethod(methods[i], i);
- }
- file.println("</BODY></HTML>");
- file.close();
- }
-
-
- /**
- * Disassemble a stream of byte codes and return the
- * string representation.
- *
- * @param stream data input stream
- * @return String representation of byte code
- */
- private final String codeToHTML( ByteSequence bytes, int method_number ) throws IOException {
- short opcode = (short) bytes.readUnsignedByte();
- StringBuffer buf;
- String name, signature;
- int default_offset = 0, low, high;
- int index, class_index, vindex, constant;
- int[] jump_table;
- int no_pad_bytes = 0, offset;
- buf = new StringBuffer(256);
- buf.append("<TT>").append(OPCODE_NAMES[opcode]).append("</TT></TD><TD>");
- /* Special case: Skip (0-3) padding bytes, i.e., the
- * following bytes are 4-byte-aligned
- */
- if ((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) {
- int remainder = bytes.getIndex() % 4;
- no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
- for (int i = 0; i < no_pad_bytes; i++) {
- bytes.readByte();
- }
- // Both cases have a field default_offset in common
- default_offset = bytes.readInt();
- }
- switch (opcode) {
- case TABLESWITCH:
- low = bytes.readInt();
- high = bytes.readInt();
- offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
- default_offset += offset;
- buf.append("<TABLE BORDER=1><TR>");
- // Print switch indices in first row (and default)
- jump_table = new int[high - low + 1];
- for (int i = 0; i < jump_table.length; i++) {
- jump_table[i] = offset + bytes.readInt();
- buf.append("<TH>").append(low + i).append("</TH>");
- }
- buf.append("<TH>default</TH></TR>\n<TR>");
- // Print target and default indices in second row
- for (int i = 0; i < jump_table.length; i++) {
- buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
- jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
- }
- buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
- default_offset).append("\">").append(default_offset).append(
- "</A></TD></TR>\n</TABLE>\n");
- break;
- /* Lookup switch has variable length arguments.
- */
- case LOOKUPSWITCH:
- int npairs = bytes.readInt();
- offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
- jump_table = new int[npairs];
- default_offset += offset;
- buf.append("<TABLE BORDER=1><TR>");
- // Print switch indices in first row (and default)
- for (int i = 0; i < npairs; i++) {
- int match = bytes.readInt();
- jump_table[i] = offset + bytes.readInt();
- buf.append("<TH>").append(match).append("</TH>");
- }
- buf.append("<TH>default</TH></TR>\n<TR>");
- // Print target and default indices in second row
- for (int i = 0; i < npairs; i++) {
- buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
- jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
- }
- buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
- default_offset).append("\">").append(default_offset).append(
- "</A></TD></TR>\n</TABLE>\n");
- break;
- /* Two address bytes + offset from start of byte stream form the
- * jump target.
- */
- case GOTO:
- case IFEQ:
- case IFGE:
- case IFGT:
- case IFLE:
- case IFLT:
- case IFNE:
- case IFNONNULL:
- case IFNULL:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- case IF_ICMPEQ:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ICMPLT:
- case IF_ICMPNE:
- case JSR:
- index = (int) (bytes.getIndex() + bytes.readShort() - 1);
- buf.append("<A HREF=\"#code").append(method_number).append("@").append(index)
- .append("\">").append(index).append("</A>");
- break;
- /* Same for 32-bit wide jumps
- */
- case GOTO_W:
- case JSR_W:
- int windex = bytes.getIndex() + bytes.readInt() - 1;
- buf.append("<A HREF=\"#code").append(method_number).append("@").append(windex)
- .append("\">").append(windex).append("</A>");
- break;
- /* Index byte references local variable (register)
- */
- case ALOAD:
- case ASTORE:
- case DLOAD:
- case DSTORE:
- case FLOAD:
- case FSTORE:
- case ILOAD:
- case ISTORE:
- case LLOAD:
- case LSTORE:
- case RET:
- if (wide) {
- vindex = bytes.readShort();
- wide = false; // Clear flag
- } else {
- vindex = bytes.readUnsignedByte();
- }
- buf.append("%").append(vindex);
- break;
- /*
- * Remember wide byte which is used to form a 16-bit address in the
- * following instruction. Relies on that the method is called again with
- * the following opcode.
- */
- case WIDE:
- wide = true;
- buf.append("(wide)");
- break;
- /* Array of basic type.
- */
- case NEWARRAY:
- buf.append("<FONT COLOR=\"#00FF00\">").append(TYPE_NAMES[bytes.readByte()]).append(
- "</FONT>");
- break;
- /* Access object/class fields.
- */
- case GETFIELD:
- case GETSTATIC:
- case PUTFIELD:
- case PUTSTATIC:
- index = bytes.readShort();
- ConstantFieldref c1 = (ConstantFieldref) constant_pool.getConstant(index,
- CONSTANT_Fieldref);
- class_index = c1.getClassIndex();
- name = constant_pool.getConstantString(class_index, CONSTANT_Class);
- name = Utility.compactClassName(name, false);
- index = c1.getNameAndTypeIndex();
- String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType);
- if (name.equals(class_name)) { // Local field
- buf.append("<A HREF=\"").append(class_name).append("_methods.html#field")
- .append(field_name).append("\" TARGET=Methods>").append(field_name)
- .append("</A>\n");
- } else {
- buf.append(constant_html.referenceConstant(class_index)).append(".").append(
- field_name);
- }
- break;
- /* Operands are references to classes in constant pool
- */
- case CHECKCAST:
- case INSTANCEOF:
- case NEW:
- index = bytes.readShort();
- buf.append(constant_html.referenceConstant(index));
- break;
- /* Operands are references to methods in constant pool
- */
- case INVOKESPECIAL:
- case INVOKESTATIC:
- case INVOKEVIRTUAL:
- case INVOKEINTERFACE:
- int m_index = bytes.readShort();
- String str;
- if (opcode == INVOKEINTERFACE) { // Special treatment needed
- bytes.readUnsignedByte(); // Redundant
- bytes.readUnsignedByte(); // Reserved
-// int nargs = bytes.readUnsignedByte(); // Redundant
-// int reserved = bytes.readUnsignedByte(); // Reserved
- ConstantInterfaceMethodref c = (ConstantInterfaceMethodref) constant_pool
- .getConstant(m_index, CONSTANT_InterfaceMethodref);
- class_index = c.getClassIndex();
- str = constant_pool.constantToString(c);
- index = c.getNameAndTypeIndex();
- } else {
- ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(m_index,
- CONSTANT_Methodref);
- class_index = c.getClassIndex();
- str = constant_pool.constantToString(c);
- index = c.getNameAndTypeIndex();
- }
- name = Class2HTML.referenceClass(class_index);
- str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant(
- index, CONSTANT_NameAndType)));
- // Get signature, i.e., types
- ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(index,
- CONSTANT_NameAndType);
- signature = constant_pool.constantToString(c2.getSignatureIndex(), CONSTANT_Utf8);
- String[] args = Utility.methodSignatureArgumentTypes(signature, false);
- String type = Utility.methodSignatureReturnType(signature, false);
- buf.append(name).append(".<A HREF=\"").append(class_name).append("_cp.html#cp")
- .append(m_index).append("\" TARGET=ConstantPool>").append(str).append(
- "</A>").append("(");
- // List arguments
- for (int i = 0; i < args.length; i++) {
- buf.append(Class2HTML.referenceType(args[i]));
- if (i < args.length - 1) {
- buf.append(", ");
- }
- }
- // Attach return type
- buf.append("):").append(Class2HTML.referenceType(type));
- break;
- /* Operands are references to items in constant pool
- */
- case LDC_W:
- case LDC2_W:
- index = bytes.readShort();
- buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
- .append("\" TARGET=\"ConstantPool\">").append(
- Class2HTML.toHTML(constant_pool.constantToString(index,
- constant_pool.getConstant(index).getTag()))).append("</a>");
- break;
- case LDC:
- index = bytes.readUnsignedByte();
- buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
- .append("\" TARGET=\"ConstantPool\">").append(
- Class2HTML.toHTML(constant_pool.constantToString(index,
- constant_pool.getConstant(index).getTag()))).append("</a>");
- break;
- /* Array of references.
- */
- case ANEWARRAY:
- index = bytes.readShort();
- buf.append(constant_html.referenceConstant(index));
- break;
- /* Multidimensional array of references.
- */
- case MULTIANEWARRAY:
- index = bytes.readShort();
- int dimensions = bytes.readByte();
- buf.append(constant_html.referenceConstant(index)).append(":").append(dimensions)
- .append("-dimensional");
- break;
- /* Increment local variable.
- */
- case IINC:
- if (wide) {
- vindex = bytes.readShort();
- constant = bytes.readShort();
- wide = false;
- } else {
- vindex = bytes.readUnsignedByte();
- constant = bytes.readByte();
- }
- buf.append("%").append(vindex).append(" ").append(constant);
- break;
- default:
- if (NO_OF_OPERANDS[opcode] > 0) {
- for (int i = 0; i < TYPE_OF_OPERANDS[opcode].length; i++) {
- switch (TYPE_OF_OPERANDS[opcode][i]) {
- case T_BYTE:
- buf.append(bytes.readUnsignedByte());
- break;
- case T_SHORT: // Either branch or index
- buf.append(bytes.readShort());
- break;
- case T_INT:
- buf.append(bytes.readInt());
- break;
- default: // Never reached
- System.err.println("Unreachable default case reached!");
- System.exit(-1);
- }
- buf.append(" ");
- }
- }
- }
- buf.append("</TD>");
- return buf.toString();
- }
-
-
- /**
- * Find all target addresses in code, so that they can be marked
- * with <A NAME = ...>. Target addresses are kept in an BitSet object.
- */
- private final void findGotos( ByteSequence bytes, Method method, Code code ) throws IOException {
- int index;
- goto_set = new BitSet(bytes.available());
- int opcode;
- /* First get Code attribute from method and the exceptions handled
- * (try .. catch) in this method. We only need the line number here.
- */
- if (code != null) {
- CodeException[] ce = code.getExceptionTable();
- int len = ce.length;
- for (int i = 0; i < len; i++) {
- goto_set.set(ce[i].getStartPC());
- goto_set.set(ce[i].getEndPC());
- goto_set.set(ce[i].getHandlerPC());
- }
- // Look for local variables and their range
- Attribute[] attributes = code.getAttributes();
- for (int i = 0; i < attributes.length; i++) {
- if (attributes[i].getTag() == ATTR_LOCAL_VARIABLE_TABLE) {
- LocalVariable[] vars = ((LocalVariableTable) attributes[i])
- .getLocalVariableTable();
- for (int j = 0; j < vars.length; j++) {
- int start = vars[j].getStartPC();
- int end = (int) (start + vars[j].getLength());
- goto_set.set(start);
- goto_set.set(end);
- }
- break;
- }
- }
- }
- // Get target addresses from GOTO, JSR, TABLESWITCH, etc.
- for (int i = 0; bytes.available() > 0; i++) {
- opcode = bytes.readUnsignedByte();
- //System.out.println(OPCODE_NAMES[opcode]);
- switch (opcode) {
- case TABLESWITCH:
- case LOOKUPSWITCH:
- //bytes.readByte(); // Skip already read byte
- int remainder = bytes.getIndex() % 4;
- int no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
- int default_offset,
- offset;
- for (int j = 0; j < no_pad_bytes; j++) {
- bytes.readByte();
- }
- // Both cases have a field default_offset in common
- default_offset = bytes.readInt();
- if (opcode == TABLESWITCH) {
- int low = bytes.readInt();
- int high = bytes.readInt();
- offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
- default_offset += offset;
- goto_set.set(default_offset);
- for (int j = 0; j < (high - low + 1); j++) {
- index = offset + bytes.readInt();
- goto_set.set(index);
- }
- } else { // LOOKUPSWITCH
- int npairs = bytes.readInt();
- offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
- default_offset += offset;
- goto_set.set(default_offset);
- for (int j = 0; j < npairs; j++) {
-// int match = bytes.readInt();
- bytes.readInt();
- index = offset + bytes.readInt();
- goto_set.set(index);
- }
- }
- break;
- case GOTO:
- case IFEQ:
- case IFGE:
- case IFGT:
- case IFLE:
- case IFLT:
- case IFNE:
- case IFNONNULL:
- case IFNULL:
- case IF_ACMPEQ:
- case IF_ACMPNE:
- case IF_ICMPEQ:
- case IF_ICMPGE:
- case IF_ICMPGT:
- case IF_ICMPLE:
- case IF_ICMPLT:
- case IF_ICMPNE:
- case JSR:
- //bytes.readByte(); // Skip already read byte
- index = bytes.getIndex() + bytes.readShort() - 1;
- goto_set.set(index);
- break;
- case GOTO_W:
- case JSR_W:
- //bytes.readByte(); // Skip already read byte
- index = bytes.getIndex() + bytes.readInt() - 1;
- goto_set.set(index);
- break;
- default:
- bytes.unreadByte();
- codeToHTML(bytes, 0); // Ignore output
- }
- }
- }
-
-
- /**
- * Write a single method with the byte code associated with it.
- */
- private void writeMethod( Method method, int method_number ) throws IOException {
- // Get raw signature
- String signature = method.getSignature();
- // Get array of strings containing the argument types
- String[] args = Utility.methodSignatureArgumentTypes(signature, false);
- // Get return type string
- String type = Utility.methodSignatureReturnType(signature, false);
- // Get method name
- String name = method.getName();
- String html_name = Class2HTML.toHTML(name);
- // Get method's access flags
- String access = Utility.accessToString(method.getAccessFlags());
- access = Utility.replace(access, " ", " ");
- // Get the method's attributes, the Code Attribute in particular
- Attribute[] attributes = method.getAttributes();
- file.print("<P><B><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + "<A NAME=method"
- + method_number + ">" + Class2HTML.referenceType(type) + "</A> <A HREF=\""
- + class_name + "_methods.html#method" + method_number + "\" TARGET=Methods>"
- + html_name + "</A>(");
- for (int i = 0; i < args.length; i++) {
- file.print(Class2HTML.referenceType(args[i]));
- if (i < args.length - 1) {
- file.print(", ");
- }
- }
- file.println(")</B></P>");
- Code c = null;
- byte[] code = null;
- if (attributes.length > 0) {
- file.print("<H4>Attributes</H4><UL>\n");
- for (int i = 0; i < attributes.length; i++) {
- byte tag = attributes[i].getTag();
- if (tag != ATTR_UNKNOWN) {
- file.print("<LI><A HREF=\"" + class_name + "_attributes.html#method"
- + method_number + "@" + i + "\" TARGET=Attributes>"
- + ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
- } else {
- file.print("<LI>" + attributes[i] + "</LI>");
- }
- if (tag == ATTR_CODE) {
- c = (Code) attributes[i];
- Attribute[] attributes2 = c.getAttributes();
- code = c.getCode();
- file.print("<UL>");
- for (int j = 0; j < attributes2.length; j++) {
- tag = attributes2[j].getTag();
- file.print("<LI><A HREF=\"" + class_name + "_attributes.html#" + "method"
- + method_number + "@" + i + "@" + j + "\" TARGET=Attributes>"
- + ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
- }
- file.print("</UL>");
- }
- }
- file.println("</UL>");
- }
- if (code != null) { // No code, an abstract method, e.g.
- //System.out.println(name + "\n" + Utility.codeToString(code, constant_pool, 0, -1));
- // Print the byte code
- ByteSequence stream = new ByteSequence(code);
- stream.mark(stream.available());
- findGotos(stream, method, c);
- stream.reset();
- file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Byte<BR>offset</TH>"
- + "<TH ALIGN=LEFT>Instruction</TH><TH ALIGN=LEFT>Argument</TH>");
- for (int i = 0; stream.available() > 0; i++) {
- int offset = stream.getIndex();
- String str = codeToHTML(stream, method_number);
- String anchor = "";
- /* Set an anchor mark if this line is targetted by a goto, jsr, etc.
- * Defining an anchor for every line is very inefficient!
- */
- if (goto_set.get(offset)) {
- anchor = "<A NAME=code" + method_number + "@" + offset + "></A>";
- }
- String anchor2;
- if (stream.getIndex() == code.length) {
- anchor2 = "<A NAME=code" + method_number + "@" + code.length + ">" + offset
- + "</A>";
- } else {
- anchor2 = "" + offset;
- }
- file
- .println("<TR VALIGN=TOP><TD>" + anchor2 + "</TD><TD>" + anchor + str
- + "</TR>");
- }
- // Mark last line, may be targetted from Attributes window
- file.println("<TR><TD> </A></TD></TR>");
- file.println("</TABLE>");
- }
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import org.apache.tomcat.util.bcel.classfile.Constant;
-import org.apache.tomcat.util.bcel.classfile.ConstantClass;
-import org.apache.tomcat.util.bcel.classfile.ConstantFieldref;
-import org.apache.tomcat.util.bcel.classfile.ConstantInterfaceMethodref;
-import org.apache.tomcat.util.bcel.classfile.ConstantMethodref;
-import org.apache.tomcat.util.bcel.classfile.ConstantNameAndType;
-import org.apache.tomcat.util.bcel.classfile.ConstantPool;
-import org.apache.tomcat.util.bcel.classfile.ConstantString;
-import org.apache.tomcat.util.bcel.classfile.Method;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * Convert constant pool into HTML file.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- *
- */
-final class ConstantHTML implements org.apache.tomcat.util.bcel.Constants {
-
- private String class_name; // name of current class
- private String class_package; // name of package
- private ConstantPool constant_pool; // reference to constant pool
- private PrintWriter file; // file to write to
- private String[] constant_ref; // String to return for cp[i]
- private Constant[] constants; // The constants in the cp
- private Method[] methods;
-
-
- ConstantHTML(String dir, String class_name, String class_package, Method[] methods,
- ConstantPool constant_pool) throws IOException {
- this.class_name = class_name;
- this.class_package = class_package;
- this.constant_pool = constant_pool;
- this.methods = methods;
- constants = constant_pool.getConstantPool();
- file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html"));
- constant_ref = new String[constants.length];
- constant_ref[0] = "<unknown>";
- file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
- // Loop through constants, constants[0] is reserved
- for (int i = 1; i < constants.length; i++) {
- if (i % 2 == 0) {
- file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
- } else {
- file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
- }
- if (constants[i] != null) {
- writeConstant(i);
- }
- file.print("</TD></TR>\n");
- }
- file.println("</TABLE></BODY></HTML>");
- file.close();
- }
-
-
- String referenceConstant( int index ) {
- return constant_ref[index];
- }
-
-
- private void writeConstant( int index ) {
- byte tag = constants[index].getTag();
- int class_index, name_index;
- String ref;
- // The header is always the same
- file.println("<H4> <A NAME=cp" + index + ">" + index + "</A> " + CONSTANT_NAMES[tag]
- + "</H4>");
- /* For every constant type get the needed parameters and print them appropiately
- */
- switch (tag) {
- case CONSTANT_InterfaceMethodref:
- case CONSTANT_Methodref:
- // Get class_index and name_and_type_index, depending on type
- if (tag == CONSTANT_Methodref) {
- ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(index,
- CONSTANT_Methodref);
- class_index = c.getClassIndex();
- name_index = c.getNameAndTypeIndex();
- } else {
- ConstantInterfaceMethodref c1 = (ConstantInterfaceMethodref) constant_pool
- .getConstant(index, CONSTANT_InterfaceMethodref);
- class_index = c1.getClassIndex();
- name_index = c1.getNameAndTypeIndex();
- }
- // Get method name and its class
- String method_name = constant_pool.constantToString(name_index,
- CONSTANT_NameAndType);
- String html_method_name = Class2HTML.toHTML(method_name);
- // Partially compacted class name, i.e., / -> .
- String method_class = constant_pool.constantToString(class_index, CONSTANT_Class);
- String short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang.
- short_method_class = Utility.compactClassName(short_method_class, class_package
- + ".", true); // Remove class package prefix
- // Get method signature
- ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(
- name_index, CONSTANT_NameAndType);
- String signature = constant_pool.constantToString(c2.getSignatureIndex(),
- CONSTANT_Utf8);
- // Get array of strings containing the argument types
- String[] args = Utility.methodSignatureArgumentTypes(signature, false);
- // Get return type string
- String type = Utility.methodSignatureReturnType(signature, false);
- String ret_type = Class2HTML.referenceType(type);
- StringBuffer buf = new StringBuffer("(");
- for (int i = 0; i < args.length; i++) {
- buf.append(Class2HTML.referenceType(args[i]));
- if (i < args.length - 1) {
- buf.append(", ");
- }
- }
- buf.append(")");
- String arg_types = buf.toString();
- if (method_class.equals(class_name)) {
- ref = "<A HREF=\"" + class_name + "_code.html#method"
- + getMethodNumber(method_name + signature) + "\" TARGET=Code>"
- + html_method_name + "</A>";
- } else {
- ref = "<A HREF=\"" + method_class + ".html" + "\" TARGET=_top>"
- + short_method_class + "</A>." + html_method_name;
- }
- constant_ref[index] = ret_type + " <A HREF=\"" + class_name + "_cp.html#cp"
- + class_index + "\" TARGET=Constants>" + short_method_class
- + "</A>.<A HREF=\"" + class_name + "_cp.html#cp" + index
- + "\" TARGET=ConstantPool>" + html_method_name + "</A> " + arg_types;
- file.println("<P><TT>" + ret_type + " " + ref + arg_types
- + " </TT>\n<UL>" + "<LI><A HREF=\"#cp" + class_index
- + "\">Class index(" + class_index + ")</A>\n" + "<LI><A HREF=\"#cp"
- + name_index + "\">NameAndType index(" + name_index + ")</A></UL>");
- break;
- case CONSTANT_Fieldref:
- // Get class_index and name_and_type_index
- ConstantFieldref c3 = (ConstantFieldref) constant_pool.getConstant(index,
- CONSTANT_Fieldref);
- class_index = c3.getClassIndex();
- name_index = c3.getNameAndTypeIndex();
- // Get method name and its class (compacted)
- String field_class = constant_pool.constantToString(class_index, CONSTANT_Class);
- String short_field_class = Utility.compactClassName(field_class); // I.e., remove java.lang.
- short_field_class = Utility.compactClassName(short_field_class,
- class_package + ".", true); // Remove class package prefix
- String field_name = constant_pool
- .constantToString(name_index, CONSTANT_NameAndType);
- if (field_class.equals(class_name)) {
- ref = "<A HREF=\"" + field_class + "_methods.html#field" + field_name
- + "\" TARGET=Methods>" + field_name + "</A>";
- } else {
- ref = "<A HREF=\"" + field_class + ".html\" TARGET=_top>" + short_field_class
- + "</A>." + field_name + "\n";
- }
- constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + class_index
- + "\" TARGET=Constants>" + short_field_class + "</A>.<A HREF=\""
- + class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>"
- + field_name + "</A>";
- file.println("<P><TT>" + ref + "</TT><BR>\n" + "<UL>" + "<LI><A HREF=\"#cp"
- + class_index + "\">Class(" + class_index + ")</A><BR>\n"
- + "<LI><A HREF=\"#cp" + name_index + "\">NameAndType(" + name_index
- + ")</A></UL>");
- break;
- case CONSTANT_Class:
- ConstantClass c4 = (ConstantClass) constant_pool.getConstant(index, CONSTANT_Class);
- name_index = c4.getNameIndex();
- String class_name2 = constant_pool.constantToString(index, tag); // / -> .
- String short_class_name = Utility.compactClassName(class_name2); // I.e., remove java.lang.
- short_class_name = Utility.compactClassName(short_class_name, class_package + ".",
- true); // Remove class package prefix
- ref = "<A HREF=\"" + class_name2 + ".html\" TARGET=_top>" + short_class_name
- + "</A>";
- constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + index
- + "\" TARGET=ConstantPool>" + short_class_name + "</A>";
- file.println("<P><TT>" + ref + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
- + "\">Name index(" + name_index + ")</A></UL>\n");
- break;
- case CONSTANT_String:
- ConstantString c5 = (ConstantString) constant_pool.getConstant(index,
- CONSTANT_String);
- name_index = c5.getStringIndex();
- String str = Class2HTML.toHTML(constant_pool.constantToString(index, tag));
- file.println("<P><TT>" + str + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
- + "\">Name index(" + name_index + ")</A></UL>\n");
- break;
- case CONSTANT_NameAndType:
- ConstantNameAndType c6 = (ConstantNameAndType) constant_pool.getConstant(index,
- CONSTANT_NameAndType);
- name_index = c6.getNameIndex();
- int signature_index = c6.getSignatureIndex();
- file.println("<P><TT>"
- + Class2HTML.toHTML(constant_pool.constantToString(index, tag))
- + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index + "\">Name index("
- + name_index + ")</A>\n" + "<LI><A HREF=\"#cp" + signature_index
- + "\">Signature index(" + signature_index + ")</A></UL>\n");
- break;
- default:
- file
- .println("<P><TT>"
- + Class2HTML.toHTML(constant_pool.constantToString(index, tag))
- + "</TT>\n");
- } // switch
- }
-
-
- private final int getMethodNumber( String str ) {
- for (int i = 0; i < methods.length; i++) {
- String cmp = methods[i].getName() + methods[i].getSignature();
- if (cmp.equals(str)) {
- return i;
- }
- }
- return -1;
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.tomcat.util.bcel.Constants;
-import org.apache.tomcat.util.bcel.generic.ClassGenException;
-import org.apache.tomcat.util.bcel.generic.Instruction;
-import org.apache.tomcat.util.bcel.generic.InstructionHandle;
-import org.apache.tomcat.util.bcel.generic.InstructionList;
-
-/**
- * InstructionFinder is a tool to search for given instructions patterns, i.e.,
- * match sequences of instructions in an instruction list via regular
- * expressions. This can be used, e.g., in order to implement a peep hole
- * optimizer that looks for code patterns and replaces them with faster
- * equivalents.
- *
- * <p>
- * This class internally uses the java.util.regex
- * package to search for regular expressions.
- *
- * A typical application would look like this:
- *
- * <pre>
- *
- *
- * InstructionFinder f = new InstructionFinder(il);
- * String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP (IFEQ|IFNE)";
- *
- * for(Iterator i = f.search(pat, constraint); i.hasNext(); ) {
- * InstructionHandle[] match = (InstructionHandle[])i.next();
- * ...
- * il.delete(match[1], match[5]);
- * ...
- * }
- *
- *
- * </pre>
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see Instruction
- * @see InstructionList
- */
-public class InstructionFinder {
-
- private static final int OFFSET = 32767; // char + OFFSET is
- // outside of
- // LATIN-1
- private static final int NO_OPCODES = 256; // Potential number,
- // some are not used
- private static final Map map = new HashMap(); // Map<String,Pattern>
- private InstructionList il;
- private String il_string; // instruction list
- // as string
- private InstructionHandle[] handles; // map instruction
-
-
- // list to array
- /**
- * @param il
- * instruction list to search for given patterns
- */
- public InstructionFinder(InstructionList il) {
- this.il = il;
- reread();
- }
-
-
- /**
- * Reread the instruction list, e.g., after you've altered the list upon a
- * match.
- */
- public final void reread() {
- int size = il.getLength();
- char[] buf = new char[size]; // Create a string with length equal to il
- // length
- handles = il.getInstructionHandles();
- // Map opcodes to characters
- for (int i = 0; i < size; i++) {
- buf[i] = makeChar(handles[i].getInstruction().getOpcode());
- }
- il_string = new String(buf);
- }
-
-
- /**
- * Map symbolic instruction names like "getfield" to a single character.
- *
- * @param pattern
- * instruction pattern in lower case
- * @return encoded string for a pattern such as "BranchInstruction".
- */
- private static final String mapName( String pattern ) {
- String result = (String) map.get(pattern);
- if (result != null) {
- return result;
- }
- for (short i = 0; i < NO_OPCODES; i++) {
- if (pattern.equals(Constants.OPCODE_NAMES[i])) {
- return "" + makeChar(i);
- }
- }
- throw new RuntimeException("Instruction unknown: " + pattern);
- }
-
-
- /**
- * Replace symbolic names of instructions with the appropiate character and
- * remove all white space from string. Meta characters such as +, * are
- * ignored.
- *
- * @param pattern
- * The pattern to compile
- * @return translated regular expression string
- */
- private static final String compilePattern( String pattern ) {
- //Bug: 38787 - Instructions are assumed to be english, to avoid odd Locale issues
- String lower = pattern.toLowerCase(Locale.ENGLISH);
- StringBuffer buf = new StringBuffer();
- int size = pattern.length();
- for (int i = 0; i < size; i++) {
- char ch = lower.charAt(i);
- if (Character.isLetterOrDigit(ch)) {
- StringBuffer name = new StringBuffer();
- while ((Character.isLetterOrDigit(ch) || ch == '_') && i < size) {
- name.append(ch);
- if (++i < size) {
- ch = lower.charAt(i);
- } else {
- break;
- }
- }
- i--;
- buf.append(mapName(name.toString()));
- } else if (!Character.isWhitespace(ch)) {
- buf.append(ch);
- }
- }
- return buf.toString();
- }
-
-
- /**
- * @return the matched piece of code as an array of instruction (handles)
- */
- private InstructionHandle[] getMatch( int matched_from, int match_length ) {
- InstructionHandle[] match = new InstructionHandle[match_length];
- System.arraycopy(handles, matched_from, match, 0, match_length);
- return match;
- }
-
-
- /**
- * Search for the given pattern in the instruction list. You can search for
- * any valid opcode via its symbolic name, e.g. "istore". You can also use a
- * super class or an interface name to match a whole set of instructions, e.g.
- * "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all
- * "istore_x" instructions. Additional aliases are "if" for "ifxx", "if_icmp"
- * for "if_icmpxx", "if_acmp" for "if_acmpxx".
- *
- * Consecutive instruction names must be separated by white space which will
- * be removed during the compilation of the pattern.
- *
- * For the rest the usual pattern matching rules for regular expressions
- * apply.
- * <P>
- * Example pattern:
- *
- * <pre>
- * search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
- * </pre>
- *
- * <p>
- * If you alter the instruction list upon a match such that other matching
- * areas are affected, you should call reread() to update the finder and call
- * search() again, because the matches are cached.
- *
- * @param pattern
- * the instruction pattern to search for, where case is ignored
- * @param from
- * where to start the search in the instruction list
- * @param constraint
- * optional CodeConstraint to check the found code pattern for
- * user-defined constraints
- * @return iterator of matches where e.nextElement() returns an array of
- * instruction handles describing the matched area
- */
- public final Iterator search( String pattern, InstructionHandle from, CodeConstraint constraint ) {
- String search = compilePattern(pattern);
- int start = -1;
- for (int i = 0; i < handles.length; i++) {
- if (handles[i] == from) {
- start = i; // Where to start search from (index)
- break;
- }
- }
- if (start == -1) {
- throw new ClassGenException("Instruction handle " + from
- + " not found in instruction list.");
- }
- Pattern regex = Pattern.compile(search);
- List matches = new ArrayList();
- Matcher matcher = regex.matcher(il_string);
- while (start < il_string.length() && matcher.find(start)) {
- int startExpr = matcher.start();
- int endExpr = matcher.end();
- int lenExpr = (endExpr - startExpr);
- InstructionHandle[] match = getMatch(startExpr, lenExpr);
- if ((constraint == null) || constraint.checkCode(match)) {
- matches.add(match);
- }
- start = endExpr;
- }
- return matches.iterator();
- }
-
-
- /**
- * Start search beginning from the start of the given instruction list.
- *
- * @param pattern
- * the instruction pattern to search for, where case is ignored
- * @return iterator of matches where e.nextElement() returns an array of
- * instruction handles describing the matched area
- */
- public final Iterator search( String pattern ) {
- return search(pattern, il.getStart(), null);
- }
-
-
- /**
- * Start search beginning from `from'.
- *
- * @param pattern
- * the instruction pattern to search for, where case is ignored
- * @param from
- * where to start the search in the instruction list
- * @return iterator of matches where e.nextElement() returns an array of
- * instruction handles describing the matched area
- */
- public final Iterator search( String pattern, InstructionHandle from ) {
- return search(pattern, from, null);
- }
-
-
- /**
- * Start search beginning from the start of the given instruction list. Check
- * found matches with the constraint object.
- *
- * @param pattern
- * the instruction pattern to search for, case is ignored
- * @param constraint
- * constraints to be checked on matching code
- * @return instruction handle or `null' if the match failed
- */
- public final Iterator search( String pattern, CodeConstraint constraint ) {
- return search(pattern, il.getStart(), constraint);
- }
-
-
- /**
- * Convert opcode number to char.
- */
- private static final char makeChar( short opcode ) {
- return (char) (opcode + OFFSET);
- }
-
-
- /**
- * @return the inquired instruction list
- */
- public final InstructionList getInstructionList() {
- return il;
- }
-
- /**
- * Code patterns found may be checked using an additional user-defined
- * constraint object whether they really match the needed criterion. I.e.,
- * check constraints that can not expressed with regular expressions.
- *
- */
- public static interface CodeConstraint {
-
- /**
- * @param match
- * array of instructions matching the requested pattern
- * @return true if the matched area is really useful
- */
- public boolean checkCode( InstructionHandle[] match );
- }
-
- // Initialize pattern map
- static {
- map.put("arithmeticinstruction","(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)");
- map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial)");
- map.put("arrayinstruction", "(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)");
- map.put("gotoinstruction", "(goto|goto_w)");
- map.put("conversioninstruction", "(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)");
- map.put("localvariableinstruction","(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)");
- map.put("loadinstruction", "(fload|dload|lload|iload|aload)");
- map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)");
- map.put("cpinstruction", "(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)");
- map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)");
- map.put("branchinstruction", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
- map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)");
- map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)");
- map.put("select", "(tableswitch|lookupswitch)");
- map.put("ifinstruction", "(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)");
- map.put("jsrinstruction", "(jsr|jsr_w)");
- map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)");
- map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)");
- map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)");
- map.put("typedinstruction", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)");
- map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)");
- map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)");
- map.put("indexedinstruction", "(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)");
- map.put("pushinstruction", "(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)");
- map.put("stackproducer", "(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)");
- map.put("stackconsumer", "(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)");
- map.put("exceptionthrower","(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)");
- map.put("loadclass", "(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)");
- map.put("instructiontargeter", "(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
- // Some aliases
- map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)");
- map.put("if_acmp", "(if_acmpeq|if_acmpne)");
- map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)");
- // Precompile some aliases first
- map.put("iconst", precompile(Constants.ICONST_0, Constants.ICONST_5, Constants.ICONST_M1));
- map.put("lconst", new String(new char[] { '(', makeChar(Constants.LCONST_0), '|', makeChar(Constants.LCONST_1), ')' }));
- map.put("dconst", new String(new char[] { '(', makeChar(Constants.DCONST_0), '|', makeChar(Constants.DCONST_1), ')' }));
- map.put("fconst", new String(new char[] { '(', makeChar(Constants.FCONST_0), '|', makeChar(Constants.FCONST_1), ')' }));
- map.put("iload", precompile(Constants.ILOAD_0, Constants.ILOAD_3, Constants.ILOAD));
- map.put("dload", precompile(Constants.DLOAD_0, Constants.DLOAD_3, Constants.DLOAD));
- map.put("fload", precompile(Constants.FLOAD_0, Constants.FLOAD_3, Constants.FLOAD));
- map.put("aload", precompile(Constants.ALOAD_0, Constants.ALOAD_3, Constants.ALOAD));
- map.put("istore", precompile(Constants.ISTORE_0, Constants.ISTORE_3, Constants.ISTORE));
- map.put("dstore", precompile(Constants.DSTORE_0, Constants.DSTORE_3, Constants.DSTORE));
- map.put("fstore", precompile(Constants.FSTORE_0, Constants.FSTORE_3, Constants.FSTORE));
- map.put("astore", precompile(Constants.ASTORE_0, Constants.ASTORE_3, Constants.ASTORE));
- // Compile strings
- for (Iterator i = map.keySet().iterator(); i.hasNext();) {
- String key = (String) i.next();
- String value = (String) map.get(key);
- char ch = value.charAt(1); // Omit already precompiled patterns
- if (ch < OFFSET) {
- map.put(key, compilePattern(value)); // precompile all
- // patterns
- }
- }
- // Add instruction alias to match anything
- StringBuffer buf = new StringBuffer("(");
- for (short i = 0; i < NO_OPCODES; i++) {
- if (Constants.NO_OF_OPERANDS[i] != Constants.UNDEFINED) { // Not
- // an
- // invalid
- // opcode
- buf.append(makeChar(i));
- if (i < NO_OPCODES - 1) {
- buf.append('|');
- }
- }
- }
- buf.append(')');
- map.put("instruction", buf.toString());
- }
-
-
- private static String precompile( short from, short to, short extra ) {
- StringBuffer buf = new StringBuffer("(");
- for (short i = from; i <= to; i++) {
- buf.append(makeChar(i));
- buf.append('|');
- }
- buf.append(makeChar(extra));
- buf.append(")");
- return buf.toString();
- }
-
-
- /*
- * Internal debugging routines.
- */
-// private static final String pattern2string( String pattern ) {
-// return pattern2string(pattern, true);
-// }
-
-
-// private static final String pattern2string( String pattern, boolean make_string ) {
-// StringBuffer buf = new StringBuffer();
-// for (int i = 0; i < pattern.length(); i++) {
-// char ch = pattern.charAt(i);
-// if (ch >= OFFSET) {
-// if (make_string) {
-// buf.append(Constants.OPCODE_NAMES[ch - OFFSET]);
-// } else {
-// buf.append((ch - OFFSET));
-// }
-// } else {
-// buf.append(ch);
-// }
-// }
-// return buf.toString();
-// }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/**
- * Java interpreter replacement, i.e., wrapper that uses its own ClassLoader
- * to modify/generate classes as they're requested. You can take this as a template
- * for your own applications.<br>
- * Call this wrapper with
- * <pre>java org.apache.tomcat.util.bcel.util.JavaWrapper <real.class.name> [arguments]</pre>
- * <p>
- * To use your own class loader you can set the "bcel.classloader" system property
- * which defaults to "org.apache.tomcat.util.bcel.util.ClassLoader", e.g., with
- * <pre>java org.apache.tomcat.util.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments]</pre>
- * </p>
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- * @see ClassLoader
- */
-public class JavaWrapper {
-
- private java.lang.ClassLoader loader;
-
-
- private static java.lang.ClassLoader getClassLoader() {
- String s = System.getProperty("bcel.classloader");
- if ((s == null) || "".equals(s)) {
- s = "org.apache.tomcat.util.bcel.util.ClassLoader";
- }
- try {
- return (java.lang.ClassLoader) Class.forName(s).newInstance();
- } catch (Exception e) {
- throw new RuntimeException(e.toString(), e);
- }
- }
-
-
- public JavaWrapper(java.lang.ClassLoader loader) {
- this.loader = loader;
- }
-
-
- public JavaWrapper() {
- this(getClassLoader());
- }
-
-
- /** Runs the main method of the given class with the arguments passed in argv
- *
- * @param class_name the fully qualified class name
- * @param argv the arguments just as you would pass them directly
- */
- public void runMain( String class_name, String[] argv ) throws ClassNotFoundException {
- Class cl = loader.loadClass(class_name);
- Method method = null;
- try {
- method = cl.getMethod("main", new Class[] {
- argv.getClass()
- });
- /* Method main is sane ?
- */
- int m = method.getModifiers();
- Class r = method.getReturnType();
- if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m)
- || (r != Void.TYPE)) {
- throw new NoSuchMethodException();
- }
- } catch (NoSuchMethodException no) {
- System.out.println("In class " + class_name
- + ": public static void main(String[] argv) is not defined");
- return;
- }
- try {
- method.invoke(null, new Object[] {
- argv
- });
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
-
-
- /** Default main method used as wrapper, expects the fully qualified class name
- * of the real class as the first argument.
- */
- public static void main( String[] argv ) throws Exception {
- /* Expects class name as first argument, other arguments are by-passed.
- */
- if (argv.length == 0) {
- System.out.println("Missing class name.");
- return;
- }
- String class_name = argv[0];
- String[] new_argv = new String[argv.length - 1];
- System.arraycopy(argv, 1, new_argv, 0, new_argv.length);
- JavaWrapper wrapper = new JavaWrapper();
- wrapper.runMain(class_name, new_argv);
- }
-}
+++ /dev/null
-/*
- * Copyright 2000-2009 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package org.apache.tomcat.util.bcel.util;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import org.apache.tomcat.util.bcel.classfile.Attribute;
-import org.apache.tomcat.util.bcel.classfile.Code;
-import org.apache.tomcat.util.bcel.classfile.ConstantValue;
-import org.apache.tomcat.util.bcel.classfile.ExceptionTable;
-import org.apache.tomcat.util.bcel.classfile.Field;
-import org.apache.tomcat.util.bcel.classfile.Method;
-import org.apache.tomcat.util.bcel.classfile.Utility;
-
-/**
- * Convert methods and fields into HTML file.
- *
- * @version $Id$
- * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
- *
- */
-final class MethodHTML implements org.apache.tomcat.util.bcel.Constants {
-
- private String class_name; // name of current class
- private PrintWriter file; // file to write to
- private ConstantHTML constant_html;
- private AttributeHTML attribute_html;
-
-
- MethodHTML(String dir, String class_name, Method[] methods, Field[] fields,
- ConstantHTML constant_html, AttributeHTML attribute_html) throws IOException {
- this.class_name = class_name;
- this.attribute_html = attribute_html;
- this.constant_html = constant_html;
- file = new PrintWriter(new FileOutputStream(dir + class_name + "_methods.html"));
- file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
- file.println("<TR><TH ALIGN=LEFT>Access flags</TH><TH ALIGN=LEFT>Type</TH>"
- + "<TH ALIGN=LEFT>Field name</TH></TR>");
- for (int i = 0; i < fields.length; i++) {
- writeField(fields[i]);
- }
- file.println("</TABLE>");
- file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Access flags</TH>"
- + "<TH ALIGN=LEFT>Return type</TH><TH ALIGN=LEFT>Method name</TH>"
- + "<TH ALIGN=LEFT>Arguments</TH></TR>");
- for (int i = 0; i < methods.length; i++) {
- writeMethod(methods[i], i);
- }
- file.println("</TABLE></BODY></HTML>");
- file.close();
- }
-
-
- /**
- * Print field of class.
- *
- * @param field field to print
- * @exception java.io.IOException
- */
- private void writeField( Field field ) throws IOException {
- String type = Utility.signatureToString(field.getSignature());
- String name = field.getName();
- String access = Utility.accessToString(field.getAccessFlags());
- Attribute[] attributes;
- access = Utility.replace(access, " ", " ");
- file.print("<TR><TD><FONT COLOR=\"#FF0000\">" + access + "</FONT></TD>\n<TD>"
- + Class2HTML.referenceType(type) + "</TD><TD><A NAME=\"field" + name + "\">" + name
- + "</A></TD>");
- attributes = field.getAttributes();
- // Write them to the Attributes.html file with anchor "<name>[<i>]"
- for (int i = 0; i < attributes.length; i++) {
- attribute_html.writeAttribute(attributes[i], name + "@" + i);
- }
- for (int i = 0; i < attributes.length; i++) {
- if (attributes[i].getTag() == ATTR_CONSTANT_VALUE) { // Default value
- String str = ((ConstantValue) attributes[i]).toString();
- // Reference attribute in _attributes.html
- file.print("<TD>= <A HREF=\"" + class_name + "_attributes.html#" + name + "@" + i
- + "\" TARGET=\"Attributes\">" + str + "</TD>\n");
- break;
- }
- }
- file.println("</TR>");
- }
-
-
- private final void writeMethod( Method method, int method_number ) throws IOException {
- // Get raw signature
- String signature = method.getSignature();
- // Get array of strings containing the argument types
- String[] args = Utility.methodSignatureArgumentTypes(signature, false);
- // Get return type string
- String type = Utility.methodSignatureReturnType(signature, false);
- // Get method name
- String name = method.getName(), html_name;
- // Get method's access flags
- String access = Utility.accessToString(method.getAccessFlags());
- // Get the method's attributes, the Code Attribute in particular
- Attribute[] attributes = method.getAttributes();
- /* HTML doesn't like names like <clinit> and spaces are places to break
- * lines. Both we don't want...
- */
- access = Utility.replace(access, " ", " ");
- html_name = Class2HTML.toHTML(name);
- file.print("<TR VALIGN=TOP><TD><FONT COLOR=\"#FF0000\"><A NAME=method" + method_number
- + ">" + access + "</A></FONT></TD>");
- file.print("<TD>" + Class2HTML.referenceType(type) + "</TD><TD>" + "<A HREF=" + class_name
- + "_code.html#method" + method_number + " TARGET=Code>" + html_name
- + "</A></TD>\n<TD>(");
- for (int i = 0; i < args.length; i++) {
- file.print(Class2HTML.referenceType(args[i]));
- if (i < args.length - 1) {
- file.print(", ");
- }
- }
- file.print(")</TD></TR>");
- // Check for thrown exceptions
- for (int i = 0; i < attributes.length; i++) {
- attribute_html.writeAttribute(attributes[i], "method" + method_number + "@" + i,
- method_number);
- byte tag = attributes[i].getTag();
- if (tag == ATTR_EXCEPTIONS) {
- file.print("<TR VALIGN=TOP><TD COLSPAN=2></TD><TH ALIGN=LEFT>throws</TH><TD>");
- int[] exceptions = ((ExceptionTable) attributes[i]).getExceptionIndexTable();
- for (int j = 0; j < exceptions.length; j++) {
- file.print(constant_html.referenceConstant(exceptions[j]));
- if (j < exceptions.length - 1) {
- file.print(", ");
- }
- }
- file.println("</TD></TR>");
- } else if (tag == ATTR_CODE) {
- Attribute[] c_a = ((Code) attributes[i]).getAttributes();
- for (int j = 0; j < c_a.length; j++) {
- attribute_html.writeAttribute(c_a[j], "method" + method_number + "@" + i + "@"
- + j, method_number);
- }
- }
- }
- }
-}