--- a/Constants.java +++ a/Constants.java @@ -20,6 +20,7 @@ package org.apache.tomcat.util.bcel; /** * Constants for the project, mostly defined in the JVM specification. * + * @version $Id$ * @author M. Dahm */ public interface Constants { @@ -511,17 +512,15 @@ public interface Constants { public static final byte ATTR_SIGNATURE = 10; public static final byte ATTR_STACK_MAP = 11; public static final byte ATTR_RUNTIME_VISIBLE_ANNOTATIONS = 12; - public static final byte ATTR_RUNTIME_INVISIBLE_ANNOTATIONS = 13; + public static final byte ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS = 13; public static final byte ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = 14; - public static final byte ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = 15; + public static final byte ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS = 15; public static final byte ATTR_ANNOTATION_DEFAULT = 16; public static final byte ATTR_LOCAL_VARIABLE_TYPE_TABLE = 17; public static final byte ATTR_ENCLOSING_METHOD = 18; public static final byte ATTR_STACK_MAP_TABLE = 19; - public static final byte ATTR_BOOTSTRAP_METHODS = 20; - public static final byte ATTR_METHOD_PARAMETERS = 21; - public static final short KNOWN_ATTRIBUTES = 22; + public static final short KNOWN_ATTRIBUTES = 20; // TOFO: FIXXXXX public static final String[] ATTRIBUTE_NAMES = { @@ -531,8 +530,7 @@ public interface Constants { "PMGClass", "Signature", "StackMap", "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", - "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", "StackMapTable", - "BootstrapMethods", "MethodParameters" + "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", "StackMapTable" }; /** Constants used in the StackMap attribute. --- a/classfile/AccessFlags.java +++ a/classfile/AccessFlags.java @@ -21,6 +21,7 @@ package org.apache.tomcat.util.bcel.classfile; * Super class for all objects that have modifiers like private, final, ... * I.e. classes, fields, and methods. * + * @version $Id$ * @author M. Dahm */ public abstract class AccessFlags implements java.io.Serializable { --- a/classfile/AnnotationDefault.java +++ a/classfile/AnnotationDefault.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,8 +25,9 @@ import org.apache.tomcat.util.bcel.Constants; /** * represents the default value of a annotation for a method info * + * @version $Id: AnnotationDefault 1 2005-02-13 03:15:08Z dbrosius $ * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class AnnotationDefault extends Attribute { @@ -44,13 +45,21 @@ public class AnnotationDefault extends Attribute * Array of constants */ public AnnotationDefault(int name_index, int length, - DataInputStream file, ConstantPool constant_pool) + DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (ElementValue) null, constant_pool); default_value = ElementValue.readElementValue(file, constant_pool); } + + public static void skip(int name_index, int length, + DataInput file, ConstantPool constant_pool) + throws IOException + { + ElementValue.skipElementValue(file, constant_pool); + } + /** * @param name_index --- a/classfile/AnnotationElementValue.java +++ a/classfile/AnnotationElementValue.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; public class AnnotationElementValue extends ElementValue @@ -29,15 +29,14 @@ public class AnnotationElementValue extends ElementValue ConstantPool cpool) { super(type, cpool); - if (type != ANNOTATION) { + if (type != ANNOTATION) throw new RuntimeException( "Only element values of type annotation can be built with this ctor - type specified: " + type); - } this.annotationEntry = annotationEntry; } @Override - public void dump(DataOutputStream dos) throws IOException + public void dump(DataOutput dos) throws IOException { dos.writeByte(type); // u1 type of value (ANNOTATION == '@') annotationEntry.dump(dos); --- a/classfile/AnnotationEntry.java +++ a/classfile/AnnotationEntry.java @@ -17,10 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.Serializable; +import java.io.*; import java.util.ArrayList; import java.util.List; @@ -29,8 +26,9 @@ import org.apache.tomcat.util.bcel.Constants; /** * represents one annotation in the annotation table * + * @version $Id: AnnotationEntry * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class AnnotationEntry implements Constants, Serializable { @@ -42,14 +40,14 @@ public class AnnotationEntry implements Constants, Serializable { private List element_value_pairs; /** - * Factory method to create an AnnotionEntry from a DataInputStream + * Factory method to create an AnnotionEntry from a DataInput * * @param file * @param constant_pool * @return the entry * @throws IOException */ - public static AnnotationEntry read(DataInputStream file, ConstantPool constant_pool) throws IOException { + public static AnnotationEntry read(DataInput file, ConstantPool constant_pool) throws IOException { final AnnotationEntry annotationEntry = new AnnotationEntry(file.readUnsignedShort(), constant_pool); final int num_element_value_pairs = (file.readUnsignedShort()); @@ -60,6 +58,16 @@ public class AnnotationEntry implements Constants, Serializable { } return annotationEntry; } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { +// final AnnotationEntry annotationEntry = new AnnotationEntry(file.readUnsignedShort(), constant_pool); + file.skipBytes(2); + int num_element_value_pairs = (file.readUnsignedShort()); + for (int i = 0; i < num_element_value_pairs; i++) { + file.skipBytes(2); + ElementValue.skipElementValue(file, constant_pool); + } + } public AnnotationEntry(int type_index, ConstantPool constant_pool) { this.type_index = type_index; @@ -82,7 +90,7 @@ public class AnnotationEntry implements Constants, Serializable { return element_value_pairs.toArray(new ElementValuePair[element_value_pairs.size()]); } - public void dump(DataOutputStream dos) throws IOException { + public void dump(DataOutput dos) throws IOException { dos.writeShort(type_index); // u2 index of type name in cpool dos.writeShort(element_value_pairs.size()); // u2 element_value pair // count --- a/classfile/Annotations.java +++ a/classfile/Annotations.java @@ -17,15 +17,16 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; /** * base class for annotations * + * @version $Id: Annotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public abstract class Annotations extends Attribute { @@ -40,7 +41,7 @@ public abstract class Annotations extends Attribute { * @param file Input stream * @param constant_pool Array of constants */ - public Annotations(byte annotation_type, int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException { + public Annotations(byte annotation_type, int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(annotation_type, name_index, length, (AnnotationEntry[]) null, constant_pool); final int annotation_table_length = (file.readUnsignedShort()); annotation_table = new AnnotationEntry[annotation_table_length]; @@ -48,6 +49,13 @@ public abstract class Annotations extends Attribute { annotation_table[i] = AnnotationEntry.read(file, constant_pool); } } + + public static void skip(byte annotation_type, int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { + int annotation_table_length = (file.readUnsignedShort()); + for (int i = 0; i < annotation_table_length; i++) { + AnnotationEntry.skip(file, constant_pool); + } + } /** @@ -76,7 +84,7 @@ public abstract class Annotations extends Attribute { return annotation_table; } - protected void writeAnnotations(DataOutputStream dos) throws IOException { + protected void writeAnnotations(DataOutput dos) throws IOException { if (annotation_table == null) { return; } --- a/classfile/ArrayElementValue.java +++ a/classfile/ArrayElementValue.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; public class ArrayElementValue extends ElementValue @@ -43,15 +43,14 @@ public class ArrayElementValue extends ElementValue public ArrayElementValue(int type, ElementValue[] datums, ConstantPool cpool) { super(type, cpool); - if (type != ARRAY) { + if (type != ARRAY) throw new RuntimeException( "Only element values of type array can be built with this ctor - type specified: " + type); - } this.evalues = datums; } @Override - public void dump(DataOutputStream dos) throws IOException + public void dump(DataOutput dos) throws IOException { dos.writeByte(type); // u1 type of value (ARRAY == '[') dos.writeShort(evalues.length); @@ -69,9 +68,8 @@ public class ArrayElementValue extends ElementValue for (int i = 0; i < evalues.length; i++) { sb.append(evalues[i].stringifyValue()); - if ((i + 1) < evalues.length) { + if ((i + 1) < evalues.length) sb.append(","); - } } sb.append("]"); return sb.toString(); --- a/classfile/Attribute.java +++ a/classfile/Attribute.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; @@ -33,6 +33,7 @@ import org.apache.tomcat.util.bcel.Constants; * Synthetic attributes are supported. The Unknown * attribute stands for non-standard-attributes. * + * @version $Id$ * @author M. Dahm * @see ConstantValue * @see SourceFile @@ -80,7 +81,7 @@ public abstract class Attribute implements Cloneable, Serializable * constants @return Attribute @throws IOException @throws * ClassFormatException */ - public static final Attribute readAttribute(DataInputStream file, + public static final Attribute readAttribute(DataInput file, ConstantPool constant_pool) throws IOException, ClassFormatException { @@ -145,13 +146,13 @@ public abstract class Attribute implements Cloneable, Serializable case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: return new RuntimeVisibleAnnotations(name_index, length, file, constant_pool); - case Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS: + case Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS: return new RuntimeInvisibleAnnotations(name_index, length, file, constant_pool); case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: return new RuntimeVisibleParameterAnnotations(name_index, length, file, constant_pool); - case Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS: + case Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS: return new RuntimeInvisibleParameterAnnotations(name_index, length, file, constant_pool); case Constants.ATTR_ANNOTATION_DEFAULT: @@ -164,12 +165,6 @@ public abstract class Attribute implements Cloneable, Serializable return new EnclosingMethod(name_index, length, file, constant_pool); case Constants.ATTR_STACK_MAP_TABLE: return new StackMapTable(name_index, length, file, constant_pool); - case Constants.ATTR_BOOTSTRAP_METHODS: - Utility.swallowBootstrapMethods(file); - return null; - case Constants.ATTR_METHOD_PARAMETERS: - Utility.swallowMethodParameters(file); - return null; default: // Never reached throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); } @@ -230,4 +225,143 @@ public abstract class Attribute implements Cloneable, Serializable { return Constants.ATTRIBUTE_NAMES[tag]; } + + public static final void skipAttribute(DataInput file, + ConstantPool constant_pool) throws IOException, + ClassFormatException + { + ConstantUtf8 c; + String name; + int name_index; + int length; + byte tag = Constants.ATTR_UNKNOWN; // Unknown attribute + // Get class name from constant pool via `name_index' indirection + name_index = file.readUnsignedShort(); + c = (ConstantUtf8) constant_pool.getConstant(name_index, + Constants.CONSTANT_Utf8); + name = c.getBytes(); + // Length of data in bytes + length = file.readInt(); + // Compare strings to find known attribute + // System.out.println(name); + for (byte i = 0; i < Constants.KNOWN_ATTRIBUTES; i++) + { + if (name.equals(Constants.ATTRIBUTE_NAMES[i])) + { + tag = i; // found! + break; + } + } + // Call proper constructor, depending on `tag' + switch (tag) + { + case Constants.ATTR_UNKNOWN: +// AttributeReader r = readers.get(name); +// if (r != null) +// { +// return r.createAttribute(name_index, length, file, +// constant_pool); +// } +// return new Unknown(name_index, length, file, constant_pool); + AttributeReader r = readers.get(name); + if (r != null) + { + // how to skip this case??????????????????????????? + r.createAttribute(name_index, length, file, + constant_pool); + return; + } + Unknown.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_CONSTANT_VALUE: +// return new ConstantValue(name_index, length, file, constant_pool); + ConstantValue.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_SOURCE_FILE: +// return new SourceFile(name_index, length, file, constant_pool); + SourceFile.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_CODE: +// return new Code(name_index, length, file, constant_pool); + Code.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_EXCEPTIONS: +// return new ExceptionTable(name_index, length, file, constant_pool); + ExceptionTable.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_LINE_NUMBER_TABLE: +// return new LineNumberTable(name_index, length, file, constant_pool); + LineNumberTable.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_LOCAL_VARIABLE_TABLE: +// return new LocalVariableTable(name_index, length, file, +// constant_pool); + LocalVariableTable.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_INNER_CLASSES: +// return new InnerClasses(name_index, length, file, constant_pool); + InnerClasses.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_SYNTHETIC: +// return new Synthetic(name_index, length, file, constant_pool); + Synthetic.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_DEPRECATED: +// return new Deprecated(name_index, length, file, constant_pool); + Deprecated.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_PMG: +// return new PMGClass(name_index, length, file, constant_pool); + PMGClass.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_SIGNATURE: +// return new Signature(name_index, length, file, constant_pool); + Signature.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_STACK_MAP: +// return new StackMap(name_index, length, file, constant_pool); + StackMap.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS: +// return new RuntimeVisibleAnnotations(name_index, length, file, +// constant_pool); + RuntimeVisibleAnnotations.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS: +// return new RuntimeInvisibleAnnotations(name_index, length, file, +// constant_pool); + RuntimeInvisibleAnnotations.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS: +// return new RuntimeVisibleParameterAnnotations(name_index, length, +// file, constant_pool); + RuntimeVisibleParameterAnnotations.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS: +// return new RuntimeInvisibleParameterAnnotations(name_index, length, +// file, constant_pool); + RuntimeInvisibleParameterAnnotations.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_ANNOTATION_DEFAULT: +// return new AnnotationDefault(name_index, length, file, +// constant_pool); + AnnotationDefault.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_LOCAL_VARIABLE_TYPE_TABLE: +// return new LocalVariableTypeTable(name_index, length, file, +// constant_pool); + LocalVariableTypeTable.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_ENCLOSING_METHOD: +// return new EnclosingMethod(name_index, length, file, constant_pool); + EnclosingMethod.skip(name_index, length, file, constant_pool); + return; + case Constants.ATTR_STACK_MAP_TABLE: +// return new StackMapTable(name_index, length, file, constant_pool); + StackMapTable.skip(name_index, length, file, constant_pool); + return; + default: // Never reached + throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag); + } + } } --- a/classfile/AttributeReader.java +++ a/classfile/AttributeReader.java @@ -23,6 +23,7 @@ package org.apache.tomcat.util.bcel.classfile; * method. These factory objects should implement this interface. * @see Attribute + * @version $Id$ * @author M. Dahm */ public interface AttributeReader { @@ -51,6 +52,6 @@ public interface AttributeReader { it to construct an attribute. In the case of errors, a null can be returned which will cause the parsing of the class file to fail. */ - Attribute createAttribute( int name_index, int length, java.io.DataInputStream file, + Attribute createAttribute( int name_index, int length, java.io.DataInput file, ConstantPool constant_pool ); } --- a/classfile/ClassElementValue.java +++ a/classfile/ClassElementValue.java @@ -17,6 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; @@ -45,7 +46,7 @@ public class ClassElementValue extends ElementValue } @Override - public void dump(DataOutputStream dos) throws IOException + public void dump(DataOutput dos) throws IOException { dos.writeByte(type); // u1 kind of value dos.writeShort(idx); --- a/classfile/ClassFormatException.java +++ a/classfile/ClassFormatException.java @@ -22,6 +22,7 @@ package org.apache.tomcat.util.bcel.classfile; * that the file is malformed or otherwise cannot be interpreted as a * class file. * + * @version $Id$ * @author M. Dahm */ public class ClassFormatException extends RuntimeException { --- a/classfile/ClassParser.java +++ a/classfile/ClassParser.java @@ -17,15 +17,13 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; +import java.util.Arrays; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.tomcat.util.bcel.Constants; +import org.apache.tomcat.util.bcel.util.FastDataInputStream; /** * Wrapper class that parses a given Java .class file. The method . See this paper for * further details about the structure of a bytecode file. * + * @version $Id$ * @author M. Dahm */ public final class ClassParser { + + //switch for parse model + public static boolean isSkip = false; - private DataInputStream file; + private DataInput file; private boolean fileOwned; private String file_name; private String zip_file; @@ -70,96 +72,88 @@ public final class ClassParser { fileOwned = false; String clazz = file.getClass().getName(); // Not a very clean solution ... is_zip = clazz.startsWith("java.util.zip.") || clazz.startsWith("java.util.jar."); - if (file instanceof DataInputStream) { - this.file = (DataInputStream) file; + if (file instanceof FastDataInputStream) { + this.file = (FastDataInputStream) file; } else { - this.file = new DataInputStream(new BufferedInputStream(file, BUFSIZE)); + this.file = new FastDataInputStream(file, BUFSIZE); } } + public JavaClass parse() throws IOException, ClassFormatException { + ZipFile zip = null; + try { + if (fileOwned) { + if (is_zip) { + zip = new ZipFile(zip_file); + ZipEntry entry = zip.getEntry(file_name); + + if (entry == null) { + throw new IOException("File " + file_name + " not found"); + } + + file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), + BUFSIZE)); + } else { + file = new DataInputStream(new BufferedInputStream(new FileInputStream( + file_name), BUFSIZE)); + } + } + /****************** Read headers ********************************/ + // Check magic tag of class file + readID(); + // Get compiler version + if(!isSkip) readVersion(); + else skipVersion(); + /****************** Read constant pool and related **************/ + // Read constant pool entries + readConstantPool(); + // Get class information + readClassInfo(); + // Get interface information, i.e., implemented interfaces + readInterfaces(); + /****************** Read class fields and methods ***************/ + // Read class fields, i.e., the variables of the class + if(!isSkip) readFields(); + else skipFields(); + // Read class methods, i.e., the functions in the class + if(!isSkip) readMethods(); + else skipMethods(); + // Read class attributes + readAttributes(); + // Check for unknown variables + //Unknown[] u = Unknown.getUnknownAttributes(); + //for(int i=0; i < u.length; i++) + // System.err.println("WARNING: " + u[i]); + // Everything should have been read now + // if(file.available() > 0) { + // int bytes = file.available(); + // byte[] buf = new byte[bytes]; + // file.read(buf); + // if(!(is_zip && (buf.length == 1))) { + // System.err.println("WARNING: Trailing garbage at end of " + file_name); + // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); + // } + // } + } finally { + // Read everything of interest, so close the file + if (fileOwned) { + try { + if (file != null && file instanceof Closeable) { + ((Closeable)file).close(); + } + if (zip != null) { + zip.close(); + } + } catch (IOException ioe) { + //ignore close exceptions + } + } + } + // Return the information we have gathered in a new object + return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, + access_flags, constant_pool, interfaces, fields, methods, attributes); +} - /** - * Parse the given Java class file and return an object that represents - * the contained data, i.e., constants, methods, fields and commands. - * A ClassFormatException is raised, if the file is not a valid - * .class file. (This does not include verification of the byte code as it - * is performed by the java interpreter). - * - * @return Class object representing the parsed class file - * @throws IOException - * @throws ClassFormatException - */ - public JavaClass parse() throws IOException, ClassFormatException { - ZipFile zip = null; - try { - if (fileOwned) { - if (is_zip) { - zip = new ZipFile(zip_file); - ZipEntry entry = zip.getEntry(file_name); - - if (entry == null) { - throw new IOException("File " + file_name + " not found"); - } - - file = new DataInputStream(new BufferedInputStream(zip.getInputStream(entry), - BUFSIZE)); - } else { - file = new DataInputStream(new BufferedInputStream(new FileInputStream( - file_name), BUFSIZE)); - } - } - /****************** Read headers ********************************/ - // Check magic tag of class file - readID(); - // Get compiler version - readVersion(); - /****************** Read constant pool and related **************/ - // Read constant pool entries - readConstantPool(); - // Get class information - readClassInfo(); - // Get interface information, i.e., implemented interfaces - readInterfaces(); - /****************** Read class fields and methods ***************/ - // Read class fields, i.e., the variables of the class - readFields(); - // Read class methods, i.e., the functions in the class - readMethods(); - // Read class attributes - readAttributes(); - // Check for unknown variables - //Unknown[] u = Unknown.getUnknownAttributes(); - //for(int i=0; i < u.length; i++) - // System.err.println("WARNING: " + u[i]); - // Everything should have been read now - // if(file.available() > 0) { - // int bytes = file.available(); - // byte[] buf = new byte[bytes]; - // file.read(buf); - // if(!(is_zip && (buf.length == 1))) { - // System.err.println("WARNING: Trailing garbage at end of " + file_name); - // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); - // } - // } - } finally { - // Read everything of interest, so close the file - if (fileOwned) { - try { - if (file != null) { - file.close(); - } - if (zip != null) { - zip.close(); - } - } catch (IOException ioe) { - //ignore close exceptions - } - } - } - // Return the information we have gathered in a new object - return new JavaClass(class_name_index, superclass_name_index, file_name, major, minor, - access_flags, constant_pool, interfaces, fields, methods, attributes); - } /** @@ -167,7 +161,7 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readAttributes() throws IOException, ClassFormatException { + private final void readAttributes() throws IOException, ClassFormatException { int attributes_count; attributes_count = file.readUnsignedShort(); attributes = new Attribute[attributes_count]; @@ -182,7 +176,7 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readClassInfo() throws IOException, ClassFormatException { + private final void readClassInfo() throws IOException, ClassFormatException { access_flags = file.readUnsignedShort(); /* Interfaces are implicitely abstract, the flag should be set * according to the JVM specification. @@ -204,7 +198,7 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readConstantPool() throws IOException, ClassFormatException { + private final void readConstantPool() throws IOException, ClassFormatException { constant_pool = new ConstantPool(file); } @@ -214,7 +208,7 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readFields() throws IOException, ClassFormatException { + private final void readFields() throws IOException, ClassFormatException { int fields_count; fields_count = file.readUnsignedShort(); fields = new Field[fields_count]; @@ -222,6 +216,16 @@ public final class ClassParser { fields[i] = new Field(file, constant_pool); } } + + private final void skipFields() throws IOException, ClassFormatException { + int fields_count; + fields_count = file.readUnsignedShort(); + for (int i = 0; i < fields_count; i++) { + Field.skip(file, constant_pool); + } + } + + private static final byte[] MAGIC_ID = new byte[] { (byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE}; /******************** Private utility methods **********************/ @@ -231,12 +235,21 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readID() throws IOException, ClassFormatException { - int magic = 0xCAFEBABE; - if (file.readInt() != magic) { + private final void readID() throws IOException, ClassFormatException { + byte[] bytes = new byte[4]; + file.readFully(bytes); + if (!Arrays.equals(bytes, MAGIC_ID)) { throw new ClassFormatException(file_name + " is not a Java .class file"); } +// int magic = 0xCAFEBABE; +// if (file.readInt() != magic) { +// throw new ClassFormatException(file_name + " is not a Java .class file"); +// } } + +// private final void skipID() throws IOException, ClassFormatException{ +// file.skipBytes(4); +// } /** @@ -244,7 +257,7 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readInterfaces() throws IOException, ClassFormatException { + private final void readInterfaces() throws IOException, ClassFormatException { int interfaces_count; interfaces_count = file.readUnsignedShort(); interfaces = new int[interfaces_count]; @@ -253,13 +266,12 @@ public final class ClassParser { } } - /** * Read information about the methods of the class. * @throws IOException * @throws ClassFormatException */ - private void readMethods() throws IOException, ClassFormatException { + private final void readMethods() throws IOException, ClassFormatException { int methods_count; methods_count = file.readUnsignedShort(); methods = new Method[methods_count]; @@ -267,6 +279,14 @@ public final class ClassParser { methods[i] = new Method(file, constant_pool); } } + + private final void skipMethods() throws IOException, ClassFormatException { + int methods_count; + methods_count = file.readUnsignedShort(); + for (int i = 0; i < methods_count; i++) { + Method.skip(file, constant_pool); + } + } /** @@ -274,8 +294,12 @@ public final class ClassParser { * @throws IOException * @throws ClassFormatException */ - private void readVersion() throws IOException, ClassFormatException { + private final void readVersion() throws IOException, ClassFormatException { minor = file.readUnsignedShort(); major = file.readUnsignedShort(); } + + private final void skipVersion() throws IOException, ClassFormatException { + file.skipBytes(4); + } } --- a/classfile/Code.java +++ a/classfile/Code.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -34,6 +34,7 @@ import org.apache.tomcat.util.bcel.Constants; * is used for debugging purposes and LocalVariableTable which * contains information about the local variables. * + * @version $Id$ * @author M. Dahm * @see Attribute * @see CodeException @@ -59,14 +60,20 @@ public final class Code extends Attribute { * @param file Input stream * @param constant_pool Array of constants */ - Code(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + Code(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { - // Initialize with some default values which will be overwritten later + // Initialize with some default values which will be overwritten later this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, (CodeException[]) null, (Attribute[]) null, constant_pool); +// System.out.println("init"); code_length = file.readInt(); +// System.out.println("readInt"); + +// System.out.println("+++++++++++++++++"+code_length+"+++++++++++++++++"); + code = new byte[code_length]; // Read byte code file.readFully(code); + /* Read exception table that contains all regions where an exception * handler is active, i.e., a try { ... } catch() block. */ @@ -89,6 +96,21 @@ public final class Code extends Attribute { */ this.length = length; } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + file.skipBytes(4); + int code_length = file.readInt(); + file.skipBytes(code_length); + int exception_table_length = file.readUnsignedShort(); + for (int i = 0; i < exception_table_length; i++) { + file.skipBytes(8); + } + int attributes_count = file.readUnsignedShort(); + for (int i = 0; i < attributes_count; i++) { + Attribute.skipAttribute(file, constant_pool); + } + } /** @@ -103,7 +125,7 @@ public final class Code extends Attribute { */ public Code(int name_index, int length, int max_stack, int max_locals, byte[] code, CodeException[] exception_table, Attribute[] attributes, ConstantPool constant_pool) { - super(Constants.ATTR_CODE, name_index, length, constant_pool); + super(Constants.ATTR_CODE, name_index, length, constant_pool); this.max_stack = max_stack; this.max_locals = max_locals; setCode(code); @@ -129,7 +151,7 @@ public final class Code extends Attribute { * @return the internal length of this code attribute (minus the first 6 bytes) * and excluding all its attributes */ - private int getInternalLength() { + private final int getInternalLength() { return 2 /*max_stack*/+ 2 /*max_locals*/+ 4 /*code length*/ + code_length /*byte-code*/ + 2 /*exception-table length*/ @@ -142,7 +164,7 @@ public final class Code extends Attribute { * @return the full size of this code attribute, minus its first 6 bytes, * including the size of all its contained attributes */ - private int calculateLength() { + private final int calculateLength() { int len = 0; for (int i = 0; i < attributes_count; i++) { len += attributes[i].length + 6 /*attribute header size*/; --- a/classfile/CodeException.java +++ a/classfile/CodeException.java @@ -29,6 +29,7 @@ import org.apache.tomcat.util.bcel.Constants; * attribute and is used only there. It contains a range in which a * particular exception handler is active. * + * @version $Id$ * @author M. Dahm * @see Code */ --- a/classfile/Constant.java +++ a/classfile/Constant.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import java.io.Serializable; @@ -29,6 +29,7 @@ import org.apache.tomcat.util.bcel.util.BCELComparator; * in the constant pool of a class file. The classes keep closely to * the JVM specification. * + * @version $Id$ * @author M. Dahm */ public abstract class Constant implements Cloneable, Serializable { @@ -85,9 +86,9 @@ public abstract class Constant implements Cloneable, Serializable { @Override - public Object clone() { + public Constant clone() { try { - return super.clone(); + return (Constant) super.clone(); } catch (CloneNotSupportedException e) { throw new Error("Clone Not Supported"); // never happens } @@ -100,7 +101,7 @@ public abstract class Constant implements Cloneable, Serializable { * @param file Input stream * @return Constant object */ - static Constant readConstant( DataInputStream file ) throws IOException, + static final Constant readConstant( DataInput file ) throws IOException, ClassFormatException { byte b = file.readByte(); // Read tag byte switch (b) { --- a/classfile/ConstantCP.java +++ a/classfile/ConstantCP.java @@ -23,6 +23,7 @@ import java.io.IOException; /** * Abstract super class for Fieldref and Methodref constants. * + * @version $Id$ * @author M. Dahm * @see ConstantFieldref * @see ConstantMethodref --- a/classfile/ConstantClass.java +++ a/classfile/ConstantClass.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a (external) class. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantDouble.java +++ a/classfile/ConstantDouble.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a Double object. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantFieldref.java +++ a/classfile/ConstantFieldref.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,6 +25,7 @@ import org.apache.tomcat.util.bcel.Constants; /** * This class represents a constant pool reference to a field. * + * @version $Id$ * @author M. Dahm */ public final class ConstantFieldref extends ConstantCP { @@ -38,7 +39,7 @@ public final class ConstantFieldref extends ConstantCP { * @param file input stream * @throws IOException */ - ConstantFieldref(DataInputStream file) throws IOException { + ConstantFieldref(DataInput file) throws IOException { super(Constants.CONSTANT_Fieldref, file); } } --- a/classfile/ConstantFloat.java +++ a/classfile/ConstantFloat.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a float object. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantInteger.java +++ a/classfile/ConstantInteger.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to an int object. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantInterfaceMethodref.java +++ a/classfile/ConstantInterfaceMethodref.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,6 +25,7 @@ import org.apache.tomcat.util.bcel.Constants; /** * This class represents a constant pool reference to an interface method. * + * @version $Id$ * @author M. Dahm */ public final class ConstantInterfaceMethodref extends ConstantCP { @@ -38,7 +39,8 @@ public final class ConstantInterfaceMethodref extends ConstantCP { * @param file input stream * @throws IOException */ - ConstantInterfaceMethodref(DataInputStream file) throws IOException { + ConstantInterfaceMethodref(DataInput file) throws IOException { super(Constants.CONSTANT_InterfaceMethodref, file); } + } --- a/classfile/ConstantLong.java +++ a/classfile/ConstantLong.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a long object. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantMethodref.java +++ a/classfile/ConstantMethodref.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,6 +25,7 @@ import org.apache.tomcat.util.bcel.Constants; /** * This class represents a constant pool reference to a method. * + * @version $Id$ * @author M. Dahm */ public final class ConstantMethodref extends ConstantCP { @@ -38,7 +39,7 @@ public final class ConstantMethodref extends ConstantCP { * @param file input stream * @throws IOException */ - ConstantMethodref(DataInputStream file) throws IOException { + ConstantMethodref(DataInput file) throws IOException { super(Constants.CONSTANT_Methodref, file); } } --- a/classfile/ConstantNameAndType.java +++ a/classfile/ConstantNameAndType.java @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.Constants; * and represents a reference to the name and signature * of a field or method. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantPool.java +++ a/classfile/ConstantPool.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import java.io.Serializable; @@ -31,6 +31,7 @@ import org.apache.tomcat.util.bcel.Constants; * programatically should see * ConstantPoolGen. + * @version $Id$ * @see Constant * @author M. Dahm */ @@ -48,7 +49,7 @@ public class ConstantPool implements Cloneable, Serializable { * @throws IOException * @throws ClassFormatException */ - ConstantPool(DataInputStream file) throws IOException, ClassFormatException { + ConstantPool(DataInput file) throws IOException, ClassFormatException { byte tag; constant_pool_count = file.readUnsignedShort(); constant_pool = new Constant[constant_pool_count]; @@ -128,7 +129,7 @@ public class ConstantPool implements Cloneable, Serializable { } - private static String escape( String str ) { + private static final String escape( String str ) { int len = str.length(); StringBuilder buf = new StringBuilder(len + 5); char[] ch = str.toCharArray(); --- a/classfile/ConstantString.java +++ a/classfile/ConstantString.java @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a String object. * + * @version $Id$ * @author M. Dahm * @see Constant */ --- a/classfile/ConstantUtf8.java +++ a/classfile/ConstantUtf8.java @@ -17,7 +17,6 @@ package org.apache.tomcat.util.bcel.classfile; import java.io.DataInput; -import java.io.DataInputStream; import java.io.IOException; import java.util.HashMap; import java.util.LinkedHashMap; @@ -30,6 +29,7 @@ import org.apache.tomcat.util.bcel.Constants; * Constant class * and represents a reference to a Utf8 encoded string. * + * @version $Id$ * @author M. Dahm * @see Constant */ @@ -69,7 +69,7 @@ public final class ConstantUtf8 extends Constant { return getCachedInstance(s); } - static ConstantUtf8 getInstance(DataInputStream file) throws IOException { + static ConstantUtf8 getInstance(DataInput file) throws IOException { return getInstance(file.readUTF()); } --- a/classfile/ConstantValue.java +++ a/classfile/ConstantValue.java @@ -26,6 +26,7 @@ import org.apache.tomcat.util.bcel.Constants; * value, i.e., a default value for initializing a class field. * This class is instantiated by the Attribute.readAttribute() method. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -47,6 +48,11 @@ public final class ConstantValue extends Attribute { throws IOException { this(name_index, length, file.readUnsignedShort(), constant_pool); } + // could the process of "constant_pool" can be skip????????????????????????????? + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + file.skipBytes(2); + } /** --- a/classfile/Deprecated.java +++ a/classfile/Deprecated.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * deprecated method. * It is instantiated from the Attribute.readAttribute() method. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -56,7 +57,7 @@ public final class Deprecated extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - Deprecated(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + Deprecated(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (byte[]) null, constant_pool); if (length > 0) { @@ -65,6 +66,14 @@ public final class Deprecated extends Attribute { System.err.println("Deprecated attribute with length > 0"); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + if(length > 0) { + file.skipBytes(length); + System.err.println("Deprecated attribute with length > 0"); + } + } /** --- a/classfile/ElementValue.java +++ a/classfile/ElementValue.java @@ -17,13 +17,14 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; /** + * @version $Id: ElementValue * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public abstract class ElementValue { @@ -46,7 +47,7 @@ public abstract class ElementValue public abstract String stringifyValue(); - public abstract void dump(DataOutputStream dos) throws IOException; + public abstract void dump(DataOutput dos) throws IOException; public static final int STRING = 's'; @@ -74,7 +75,7 @@ public abstract class ElementValue public static final int PRIMITIVE_BOOLEAN = 'Z'; - public static ElementValue readElementValue(DataInputStream dis, + public static ElementValue readElementValue(DataInput dis, ConstantPool cpool) throws IOException { byte type = dis.readByte(); @@ -129,4 +130,88 @@ public abstract class ElementValue "Unexpected element value kind in annotation: " + type); } } + public static void skipElementValue(DataInput dis, + ConstantPool cpool) throws IOException + { + byte type = dis.readByte(); + switch (type) + { + case 'B': // byte +// return new SimpleElementValue(PRIMITIVE_BYTE, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'C': // char +// return new SimpleElementValue(PRIMITIVE_CHAR, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'D': // double +// return new SimpleElementValue(PRIMITIVE_DOUBLE, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'F': // float +// return new SimpleElementValue(PRIMITIVE_FLOAT, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'I': // int +// return new SimpleElementValue(PRIMITIVE_INT, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'J': // long +// return new SimpleElementValue(PRIMITIVE_LONG, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'S': // short +// return new SimpleElementValue(PRIMITIVE_SHORT, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 'Z': // boolean +// return new SimpleElementValue(PRIMITIVE_BOOLEAN, dis +// .readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case 's': // String +// return new SimpleElementValue(STRING, dis.readUnsignedShort(), +// cpool); + dis.skipBytes(2); + return; + case 'e': // Enum constant +// return new EnumElementValue(ENUM_CONSTANT, dis.readUnsignedShort(), +// dis.readUnsignedShort(), cpool); + dis.skipBytes(4); + return; + case 'c': // Class +// return new ClassElementValue(CLASS, dis.readUnsignedShort(), cpool); + dis.skipBytes(2); + return; + case '@': // Annotation + // TODO isRuntimeVisible +// return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read( +// dis, cpool), cpool); + AnnotationEntry.skip(dis, cpool); + return; + case '[': // Array +// int numArrayVals = dis.readUnsignedShort(); +// ElementValue[] evalues = new ElementValue[numArrayVals]; +// for (int j = 0; j < numArrayVals; j++) +// { +// evalues[j] = ElementValue.readElementValue(dis, cpool); +// } +// return new ArrayElementValue(ARRAY, evalues, cpool); + int numArrayVals = dis.readUnsignedShort(); + for (int j = 0; j < numArrayVals; j++){ + ElementValue.skipElementValue(dis, cpool); + } + return; + default: + throw new RuntimeException( + "Unexpected element value kind in annotation: " + type); + } + } } --- a/classfile/ElementValuePair.java +++ a/classfile/ElementValuePair.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,8 +25,9 @@ import org.apache.tomcat.util.bcel.Constants; /** * an annotation's element value pair * + * @version $Id: ElementValuePair * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class ElementValuePair { @@ -56,7 +57,7 @@ public class ElementValuePair return elementValue; } - protected void dump(DataOutputStream dos) throws IOException { + protected void dump(DataOutput dos) throws IOException { dos.writeShort(elementNameIndex); // u2 name of the element elementValue.dump(dos); } --- a/classfile/EnclosingMethod.java +++ a/classfile/EnclosingMethod.java @@ -16,7 +16,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -30,7 +30,7 @@ public class EnclosingMethod extends Attribute { private static final long serialVersionUID = 6755214228300933233L; // Ctors - and code to read an attribute in. - public EnclosingMethod(int nameIndex, int len, DataInputStream dis, + public EnclosingMethod(int nameIndex, int len, DataInput dis, ConstantPool cpool) throws IOException { super(Constants.ATTR_ENCLOSING_METHOD, nameIndex, len, cpool); // Unused class index @@ -38,6 +38,11 @@ public class EnclosingMethod extends Attribute { // Unused method index dis.readUnsignedShort(); } + + public static void skip(int nameIndex, int len, DataInput dis, + ConstantPool cpool) throws IOException { + dis.skipBytes(4); + } @Override public Attribute copy(ConstantPool constant_pool) { --- a/classfile/EnumElementValue.java +++ a/classfile/EnumElementValue.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -41,7 +41,7 @@ public class EnumElementValue extends ElementValue } @Override - public void dump(DataOutputStream dos) throws IOException + public void dump(DataOutput dos) throws IOException { dos.writeByte(type); // u1 type of value (ENUM_CONSTANT == 'e') dos.writeShort(typeIdx); // u2 --- a/classfile/ExceptionTable.java +++ a/classfile/ExceptionTable.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -30,6 +30,7 @@ import org.apache.tomcat.util.bcel.Constants; * attribute using the name Exceptions (which is inconsistent * with the other classes). * + * @version $Id$ * @author M. Dahm * @see Code */ @@ -61,7 +62,7 @@ public final class ExceptionTable extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - ExceptionTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + ExceptionTable(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (int[]) null, constant_pool); number_of_exceptions = file.readUnsignedShort(); @@ -70,6 +71,14 @@ public final class ExceptionTable extends Attribute { exception_index_table[i] = file.readUnsignedShort(); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int number_of_exceptions = file.readUnsignedShort(); + for (int i = 0; i < number_of_exceptions; i++) { + file.skipBytes(2); + } + } /** --- a/classfile/Field.java +++ a/classfile/Field.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.util.BCELComparator; * This class represents the field info structure, i.e., the representation * for a variable in the class. See JVM specification for details. * + * @version $Id$ * @author M. Dahm */ public final class Field extends FieldOrMethod { @@ -55,10 +56,14 @@ public final class Field extends FieldOrMethod { * Construct object from file stream. * @param file Input stream */ - Field(DataInputStream file, ConstantPool constant_pool) throws IOException, + Field(DataInput file, ConstantPool constant_pool) throws IOException, ClassFormatException { super(file, constant_pool); } + + public static void skip(DataInput file, ConstantPool constant_pool) throws ClassFormatException, IOException{ + FieldOrMethod.skip(file, constant_pool); + } /** --- a/classfile/FieldOrMethod.java +++ a/classfile/FieldOrMethod.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,6 +25,7 @@ import org.apache.tomcat.util.bcel.Constants; /** * Abstract super class for fields and methods. * + * @version $Id$ * @author M. Dahm */ public abstract class FieldOrMethod extends AccessFlags implements Cloneable { @@ -47,7 +48,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable { * @throws IOException * @throws ClassFormatException */ - protected FieldOrMethod(DataInputStream file, ConstantPool constant_pool) throws IOException, + protected FieldOrMethod(DataInput file, ConstantPool constant_pool) throws IOException, ClassFormatException { this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null, constant_pool); @@ -57,6 +58,16 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable { attributes[i] = Attribute.readAttribute(file, constant_pool); } } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException, + ClassFormatException { + file.skipBytes(6); + int attributes_count = file.readUnsignedShort(); + for (int j = 0; j < attributes_count; j++) { + Attribute.skipAttribute(file, constant_pool); + } + + } /** --- a/classfile/InnerClass.java +++ a/classfile/InnerClass.java @@ -29,6 +29,7 @@ import org.apache.tomcat.util.bcel.Constants; * indices of the inner and outer classes, the name and the attributes * of the inner class. * + * @version $Id$ * @author M. Dahm * @see InnerClasses */ @@ -50,6 +51,10 @@ public final class InnerClass implements Cloneable, Serializable { this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file .readUnsignedShort()); } + + public static void skip(DataInput file) throws IOException { + file.skipBytes(8); + } /** --- a/classfile/InnerClasses.java +++ a/classfile/InnerClasses.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.Constants; * to the source file of this class. * It is instantiated from the Attribute.readAttribute() method. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -60,7 +61,7 @@ public final class InnerClasses extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - InnerClasses(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + InnerClasses(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (InnerClass[]) null, constant_pool); number_of_classes = file.readUnsignedShort(); @@ -69,6 +70,14 @@ public final class InnerClasses extends Attribute { inner_classes[i] = new InnerClass(file); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int number_of_classes = file.readUnsignedShort(); + for (int i = 0; i < number_of_classes; i++) { + InnerClass.skip(file); + } + } /** --- a/classfile/JavaClass.java +++ a/classfile/JavaClass.java @@ -32,6 +32,7 @@ import org.apache.tomcat.util.bcel.util.BCELComparator; * class file. Those interested in programatically generating classes * should see the ClassGen class. + * @version $Id$ * @author M. Dahm */ public class JavaClass extends AccessFlags @@ -156,7 +157,8 @@ public class JavaClass extends AccessFlags // Find attributes that contain annotation data Attribute[] attrs = getAttributes(); List accumulatedAnnotations = new ArrayList(); - for (Attribute attribute : attrs) { + for (int i = 0; i < attrs.length; i++) { + Attribute attribute = attrs[i]; if (attribute instanceof Annotations) { Annotations runtimeAnnotations = (Annotations)attribute; for(int j = 0; j < runtimeAnnotations.getAnnotationEntries().length; j++) --- a/classfile/LineNumber.java +++ a/classfile/LineNumber.java @@ -27,6 +27,7 @@ import java.io.Serializable; * the source that corresponds to a relative address in the byte code. This * is used for debugging purposes. * + * @version $Id$ * @author M. Dahm * @see LineNumberTable */ @@ -45,6 +46,10 @@ public final class LineNumber implements Cloneable, Serializable { LineNumber(DataInput file) throws IOException { this(file.readUnsignedShort(), file.readUnsignedShort()); } + + public static void skip(DataInput file) throws IOException{ + file.skipBytes(4); + } /** --- a/classfile/LineNumberTable.java +++ a/classfile/LineNumberTable.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -27,6 +27,7 @@ import org.apache.tomcat.util.bcel.Constants; * purposes. This attribute is used by the Code attribute. It * contains pairs of PCs and line numbers. * + * @version $Id$ * @author M. Dahm * @see Code * @see LineNumber @@ -59,7 +60,7 @@ public final class LineNumberTable extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - LineNumberTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + LineNumberTable(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (LineNumber[]) null, constant_pool); line_number_table_length = (file.readUnsignedShort()); @@ -68,6 +69,15 @@ public final class LineNumberTable extends Attribute { line_number_table[i] = new LineNumber(file); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int line_number_table_length = (file.readUnsignedShort()); + for (int i = 0; i < line_number_table_length; i++) { + LineNumber.skip(file); + } + + } /** --- a/classfile/LocalVariable.java +++ a/classfile/LocalVariable.java @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.Constants; * This class represents a local variable within a method. It contains its * scope, name, signature and index on the method's frame. * + * @version $Id$ * @author M. Dahm * @see LocalVariableTable */ @@ -53,6 +54,10 @@ public final class LocalVariable implements Constants, Cloneable, Serializable { this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file .readUnsignedShort(), file.readUnsignedShort(), constant_pool); } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { + file.skipBytes(10); + } /** --- a/classfile/LocalVariableTable.java +++ a/classfile/LocalVariableTable.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,6 +26,7 @@ import org.apache.tomcat.util.bcel.Constants; * This class represents colection of local variables in a * method. This attribute is contained in the Code attribute. * + * @version $Id$ * @author M. Dahm * @see Code * @see LocalVariable @@ -58,7 +59,7 @@ public class LocalVariableTable extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + LocalVariableTable(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (LocalVariable[]) null, constant_pool); local_variable_table_length = (file.readUnsignedShort()); @@ -67,6 +68,14 @@ public class LocalVariableTable extends Attribute { local_variable_table[i] = new LocalVariable(file, constant_pool); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int local_variable_table_length = (file.readUnsignedShort()); + for (int i = 0; i < local_variable_table_length; i++) { + LocalVariable.skip(file, constant_pool); + } + } /** --- a/classfile/LocalVariableTypeTable.java +++ a/classfile/LocalVariableTypeTable.java @@ -16,7 +16,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -61,7 +61,7 @@ private int local_variable_type_table_length; // Table of local setLocalVariableTable(local_variable_table); } - LocalVariableTypeTable(int nameIdx, int len, DataInputStream dis,ConstantPool cpool) throws IOException { + LocalVariableTypeTable(int nameIdx, int len, DataInput dis,ConstantPool cpool) throws IOException { this(nameIdx, len, (LocalVariable[])null, cpool); local_variable_type_table_length = (dis.readUnsignedShort()); @@ -70,6 +70,15 @@ private int local_variable_type_table_length; // Table of local for(int i=0; i < local_variable_type_table_length; i++) local_variable_type_table[i] = new LocalVariable(dis, cpool); } + + public static void skip(int nameIdx, int len, DataInput dis,ConstantPool cpool) throws IOException { + int local_variable_type_table_length = (dis.readUnsignedShort()); + for(int i=0; i < local_variable_type_table_length; i++){ + LocalVariable.skip(dis, cpool); + } + + + } public final void setLocalVariableTable(LocalVariable[] local_variable_table) { --- a/classfile/Method.java +++ a/classfile/Method.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.util.BCELComparator; * for a method in the class. See JVM specification for details. * A method has access flags, a name, a signature and a number of attributes. * + * @version $Id$ * @author M. Dahm */ public final class Method extends FieldOrMethod { @@ -66,10 +67,15 @@ public final class Method extends FieldOrMethod { * @throws IOException * @throws ClassFormatException */ - Method(DataInputStream file, ConstantPool constant_pool) throws IOException, + Method(DataInput file, ConstantPool constant_pool) throws IOException, ClassFormatException { super(file, constant_pool); } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException, + ClassFormatException { + FieldOrMethod.skip(file, constant_pool); + } /** --- a/classfile/PMGClass.java +++ a/classfile/PMGClass.java @@ -26,6 +26,7 @@ import org.apache.tomcat.util.bcel.Constants; * This class is derived from Attribute and represents a reference * to a PMG attribute. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -47,6 +48,11 @@ public final class PMGClass extends Attribute { throws IOException { this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), constant_pool); } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + file.skipBytes(4); + } /** --- a/classfile/ParameterAnnotationEntry.java +++ a/classfile/ParameterAnnotationEntry.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -25,8 +25,9 @@ import org.apache.tomcat.util.bcel.Constants; /** * represents one parameter annotation in the parameter annotation table * + * @version $Id: ParameterAnnotationEntry * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class ParameterAnnotationEntry implements Constants { @@ -39,7 +40,7 @@ public class ParameterAnnotationEntry implements Constants { * @param file Input stream * @throws IOException */ - ParameterAnnotationEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { + ParameterAnnotationEntry(DataInput file, ConstantPool constant_pool) throws IOException { annotation_table_length = (file.readUnsignedShort()); annotation_table = new AnnotationEntry[annotation_table_length]; for (int i = 0; i < annotation_table_length; i++) { @@ -47,4 +48,10 @@ public class ParameterAnnotationEntry implements Constants { } } + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { + int annotation_table_length = (file.readUnsignedShort()); + for (int i = 0; i < annotation_table_length; i++) { + AnnotationEntry.skip(file, constant_pool); + } + } } --- a/classfile/ParameterAnnotations.java +++ a/classfile/ParameterAnnotations.java @@ -17,14 +17,15 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; /** * base class for parameter annotations * + * @version $Id: ParameterAnnotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public abstract class ParameterAnnotations extends Attribute { @@ -41,7 +42,7 @@ public abstract class ParameterAnnotations extends Attribute { * @param constant_pool Array of constants */ ParameterAnnotations(byte parameter_annotation_type, int name_index, int length, - DataInputStream file, ConstantPool constant_pool) throws IOException { + DataInput file, ConstantPool constant_pool) throws IOException { this(parameter_annotation_type, name_index, length, (ParameterAnnotationEntry[]) null, constant_pool); num_parameters = (file.readUnsignedByte()); @@ -50,6 +51,14 @@ public abstract class ParameterAnnotations extends Attribute { parameter_annotation_table[i] = new ParameterAnnotationEntry(file, constant_pool); } } + + public static void skip(byte parameter_annotation_type, int name_index, int length, + DataInput file, ConstantPool constant_pool) throws IOException { + int num_parameters = (file.readUnsignedByte()); + for (int i = 0; i < num_parameters; i++) { + ParameterAnnotationEntry.skip(file, constant_pool); + } + } /** --- a/classfile/RuntimeInvisibleAnnotations.java +++ a/classfile/RuntimeInvisibleAnnotations.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,8 +26,9 @@ import org.apache.tomcat.util.bcel.Constants; * represents an annotation that is represented in the class file but is not * provided to the JVM. * + * @version $Id: RuntimeInvisibleAnnotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class RuntimeInvisibleAnnotations extends Annotations { @@ -44,12 +45,20 @@ public class RuntimeInvisibleAnnotations extends Annotations * Array of constants */ RuntimeInvisibleAnnotations(int name_index, int length, - DataInputStream file, ConstantPool constant_pool) + DataInput file, ConstantPool constant_pool) throws IOException { - super(Constants.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS, name_index, length, + super(Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, name_index, length, file, constant_pool); } + + public static void skip(int name_index, int length, + DataInput file, ConstantPool constant_pool) + throws IOException + { + Annotations.skip(Constants.ATTR_RUNTIMEIN_VISIBLE_ANNOTATIONS, name_index, length, + file, constant_pool); + } /** * @return deep copy of this attribute --- a/classfile/RuntimeInvisibleParameterAnnotations.java +++ a/classfile/RuntimeInvisibleParameterAnnotations.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,8 +26,9 @@ import org.apache.tomcat.util.bcel.Constants; * represents a parameter annotation that is represented in the class file * but is not provided to the JVM. * + * @version $Id: RuntimeInvisibleParameterAnnotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { @@ -40,11 +41,16 @@ public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { * @param file Input stream * @param constant_pool Array of constants */ - RuntimeInvisibleParameterAnnotations(int name_index, int length, DataInputStream file, + RuntimeInvisibleParameterAnnotations(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { - super(Constants.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, + super(Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, constant_pool); } + + public static void skip(int name_index, int length, DataInput file, + ConstantPool constant_pool) throws IOException { + ParameterAnnotations.skip(Constants.ATTR_RUNTIMEIN_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, constant_pool); + } /** --- a/classfile/RuntimeVisibleAnnotations.java +++ a/classfile/RuntimeVisibleAnnotations.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,8 +26,9 @@ import org.apache.tomcat.util.bcel.Constants; * represents an annotation that is represented in the class file and is * provided to the JVM. * + * @version $Id: RuntimeVisibleAnnotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class RuntimeVisibleAnnotations extends Annotations { @@ -44,12 +45,19 @@ public class RuntimeVisibleAnnotations extends Annotations * Array of constants */ public RuntimeVisibleAnnotations(int name_index, int length, - DataInputStream file, ConstantPool constant_pool) + DataInput file, ConstantPool constant_pool) throws IOException { super(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length, file, constant_pool); } + + public static void skip(int name_index, int length, + DataInput file, ConstantPool constant_pool) + throws IOException + { + Annotations.skip(Constants.ATTR_RUNTIME_VISIBLE_ANNOTATIONS, name_index, length, file, constant_pool); + } /** * @return deep copy of this attribute --- a/classfile/RuntimeVisibleParameterAnnotations.java +++ a/classfile/RuntimeVisibleParameterAnnotations.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,8 +26,9 @@ import org.apache.tomcat.util.bcel.Constants; * represents a parameter annotation that is represented in the class file * and is provided to the JVM. * + * @version $Id: RuntimeVisibleParameterAnnotations * @author D. Brosius - * @since 6.0 + * @since 5.3 */ public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { @@ -40,11 +41,16 @@ public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { * @param file Input stream * @param constant_pool Array of constants */ - RuntimeVisibleParameterAnnotations(int name_index, int length, DataInputStream file, + RuntimeVisibleParameterAnnotations(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { super(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, constant_pool); } + + public static void skip(int name_index, int length, DataInput file, + ConstantPool constant_pool) throws IOException { + ParameterAnnotations.skip(Constants.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, name_index, length, file, constant_pool); + } /** --- a/classfile/Signature.java +++ a/classfile/Signature.java @@ -26,6 +26,7 @@ import org.apache.tomcat.util.bcel.Constants; * This class is derived from Attribute and represents a reference * to a GJ attribute. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -47,6 +48,11 @@ public final class Signature extends Attribute { throws IOException { this(name_index, length, file.readUnsignedShort(), constant_pool); } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + file.skipBytes(2); + } /** --- a/classfile/SimpleElementValue.java +++ a/classfile/SimpleElementValue.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataOutputStream; +import java.io.DataOutput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -100,7 +100,7 @@ public class SimpleElementValue extends ElementValue } @Override - public void dump(DataOutputStream dos) throws IOException + public void dump(DataOutput dos) throws IOException { dos.writeByte(type); // u1 kind of value switch (type) --- a/classfile/SourceFile.java +++ a/classfile/SourceFile.java @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.Constants; * should appear per classfile. The intention of this class is that it is * instantiated from the Attribute.readAttribute() method. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -49,6 +50,11 @@ public final class SourceFile extends Attribute { throws IOException { this(name_index, length, file.readUnsignedShort(), constant_pool); } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + file.skipBytes(2); + } /** --- a/classfile/StackMap.java +++ a/classfile/StackMap.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -31,6 +31,7 @@ import org.apache.tomcat.util.bcel.Constants; * within the Code attribute of a method. See CLDC specification * §5.3.1.2 * + * @version $Id$ * @author M. Dahm * @see Code * @see StackMapEntry @@ -63,7 +64,7 @@ public final class StackMap extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - StackMap(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + StackMap(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (StackMapEntry[]) null, constant_pool); map_length = file.readUnsignedShort(); @@ -72,6 +73,14 @@ public final class StackMap extends Attribute { map[i] = new StackMapEntry(file, constant_pool); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int map_length = file.readUnsignedShort(); + for (int i = 0; i < map_length; i++) { + StackMapEntry.skip(file, constant_pool); + } + } /** --- a/classfile/StackMapEntry.java +++ a/classfile/StackMapEntry.java @@ -17,16 +17,14 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.Serializable; +import java.io.*; /** * This class represents a stack map entry recording the types of * local variables and the the of stack items at a given byte code offset. * See CLDC specification §5.3.1.2 * + * @version $Id$ * @author M. Dahm * @see StackMap * @see StackMapType @@ -47,7 +45,7 @@ public final class StackMapEntry implements Cloneable, Serializable { * @param file Input stream * @throws IOException */ - StackMapEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { + StackMapEntry(DataInput file, ConstantPool constant_pool) throws IOException { this(file.readShort(), file.readShort(), null, -1, null); types_of_locals = new StackMapType[number_of_locals]; for (int i = 0; i < number_of_locals; i++) { @@ -59,6 +57,19 @@ public final class StackMapEntry implements Cloneable, Serializable { types_of_stack_items[i] = new StackMapType(file, constant_pool); } } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { +// int byte_code_offset = file.readShort(); + file.skipBytes(2); + int number_of_locals = file.readShort(); + for (int i = 0; i < number_of_locals; i++) { + StackMapType.skip(file, constant_pool); + } + int number_of_stack_items = file.readShort(); + for (int i = 0; i < number_of_stack_items; i++) { + StackMapType.skip(file, constant_pool); + } + } public StackMapEntry(int byte_code_offset, int number_of_locals, --- a/classfile/StackMapTable.java +++ a/classfile/StackMapTable.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -31,6 +31,7 @@ import org.apache.tomcat.util.bcel.Constants; * within the Code attribute of a method. See CLDC specification * §5.3.1.2 * + * @version $Id$ * @author M. Dahm * @see Code * @see StackMapEntry @@ -63,7 +64,7 @@ public final class StackMapTable extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - StackMapTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + StackMapTable(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (StackMapTableEntry[]) null, constant_pool); map_length = file.readUnsignedShort(); @@ -72,6 +73,14 @@ public final class StackMapTable extends Attribute { map[i] = new StackMapTableEntry(file, constant_pool); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + int map_length = file.readUnsignedShort(); + for (int i = 0; i < map_length; i++) { + StackMapTableEntry.skip(file, constant_pool); + } + } /** --- a/classfile/StackMapTableEntry.java +++ a/classfile/StackMapTableEntry.java @@ -17,10 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.Serializable; +import java.io.*; import org.apache.tomcat.util.bcel.Constants; @@ -29,6 +26,7 @@ import org.apache.tomcat.util.bcel.Constants; * local variables and the the of stack items at a given byte code offset. * See CLDC specification §5.3.1.2 * + * @version $Id$ * @author M. Dahm * @see StackMap * @see StackMapType @@ -50,8 +48,8 @@ public final class StackMapTableEntry implements Cloneable, Serializable { * @param file Input stream * @throws IOException */ - StackMapTableEntry(DataInputStream file, ConstantPool constant_pool) throws IOException { - this(file.read(), -1, -1, null, -1, null); + StackMapTableEntry(DataInput file, ConstantPool constant_pool) throws IOException { + this(file.readUnsignedByte(), -1, -1, null, -1, null); if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) { byte_code_offset_delta = frame_type - Constants.SAME_FRAME; @@ -93,6 +91,40 @@ public final class StackMapTableEntry implements Cloneable, Serializable { throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frame_type); } } + + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { + int frame_type = file.readUnsignedByte(); + if (frame_type >= Constants.SAME_FRAME && frame_type <= Constants.SAME_FRAME_MAX) { + }else if(frame_type >= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME && frame_type <= Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX){ + StackMapType.skip(file, constant_pool); + }else if (frame_type == Constants.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { + file.skipBytes(2); + StackMapType.skip(file, constant_pool); + }else if (frame_type >= Constants.CHOP_FRAME && frame_type <= Constants.CHOP_FRAME_MAX){ + file.skipBytes(2); + }else if (frame_type == Constants.SAME_FRAME_EXTENDED) { + file.skipBytes(2); + }else if (frame_type >= Constants.APPEND_FRAME && frame_type <= Constants.APPEND_FRAME_MAX) { + file.skipBytes(2); + int number_of_locals = frame_type - 251; + for (int i = 0; i < number_of_locals; i++) { + StackMapType.skip(file, constant_pool); + } + }else if (frame_type == Constants.FULL_FRAME) { + file.skipBytes(2); + int number_of_locals = file.readShort(); + for (int i = 0; i < number_of_locals; i++) { + StackMapType.skip(file, constant_pool); + } + int number_of_stack_items = file.readShort(); + for (int i = 0; i < number_of_stack_items; i++) { + StackMapType.skip(file, constant_pool); + } + }else { + /* Can't happen */ + throw new ClassFormatException ("Invalid frame type found while parsing stack map table: " + frame_type); + } + } public StackMapTableEntry(int tag, int byte_code_offset_delta, int number_of_locals, --- a/classfile/StackMapType.java +++ a/classfile/StackMapType.java @@ -28,6 +28,7 @@ import org.apache.tomcat.util.bcel.Constants; * This class represents the type of a local variable or item on stack * used in the StackMap entries. * + * @version $Id$ * @author M. Dahm * @see StackMapEntry * @see StackMap @@ -54,6 +55,14 @@ public final class StackMapType implements Cloneable, Serializable { } setConstantPool(constant_pool); } + + // logic may be false?????????????????????????????????????? + public static void skip(DataInput file, ConstantPool constant_pool) throws IOException { + byte type = file.readByte(); + if ((type == Constants.ITEM_Object) || (type == Constants.ITEM_NewObject)) { + file.skipBytes(2); + } + } /** --- a/classfile/Synthetic.java +++ a/classfile/Synthetic.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -31,6 +31,7 @@ import org.apache.tomcat.util.bcel.Constants; * is intended to be instantiated from the * Attribute.readAttribute() method. * + * @version $Id$ * @author M. Dahm * @see Attribute */ @@ -62,7 +63,7 @@ public final class Synthetic extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - Synthetic(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + Synthetic(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (byte[]) null, constant_pool); if (length > 0) { @@ -71,6 +72,14 @@ public final class Synthetic extends Attribute { System.err.println("Synthetic attribute with length > 0"); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + if(length > 0){ + file.skipBytes(length); + System.err.println("Synthetic attribute with length > 0"); + } + } /** --- a/classfile/Unknown.java +++ a/classfile/Unknown.java @@ -17,7 +17,7 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -35,6 +35,7 @@ import org.apache.tomcat.util.bcel.Constants; * org.apache.tomcat.util.bcel.classfile.AttributeReader)">Attribute.addAttributeReader. * + * @version $Id$ * @see org.apache.tomcat.util.bcel.classfile.Attribute * @see org.apache.tomcat.util.bcel.classfile.AttributeReader * @author M. Dahm @@ -73,7 +74,7 @@ public final class Unknown extends Attribute { * @param constant_pool Array of constants * @throws IOException */ - Unknown(int name_index, int length, DataInputStream file, ConstantPool constant_pool) + Unknown(int name_index, int length, DataInput file, ConstantPool constant_pool) throws IOException { this(name_index, length, (byte[]) null, constant_pool); if (length > 0) { @@ -81,6 +82,12 @@ public final class Unknown extends Attribute { file.readFully(bytes); } } + + public static void skip(int name_index, int length, DataInput file, ConstantPool constant_pool) + throws IOException { + if(length > 0) file.skipBytes(length); + + } /** --- a/classfile/Utility.java +++ a/classfile/Utility.java @@ -17,7 +17,6 @@ */ package org.apache.tomcat.util.bcel.classfile; -import java.io.DataInput; import java.io.IOException; import org.apache.tomcat.util.bcel.Constants; @@ -26,6 +25,7 @@ import org.apache.tomcat.util.bcel.util.ByteSequence; /** * Utility functions that do not really belong to any class in particular. * + * @version $Id$ * @author M. Dahm */ public abstract class Utility { @@ -778,23 +778,4 @@ public abstract class Utility { } return buf.toString(); } - - static void swallowBootstrapMethods(DataInput file) throws IOException { - int num_bootstrap_methods = file.readUnsignedShort(); - for (int i = 0; i < num_bootstrap_methods; i++) { - file.readUnsignedShort(); // Unused bootstrap_method_ref - int num_bootstrap_args = file.readUnsignedShort(); - for (int j = 0; j < num_bootstrap_args; j++) { - file.readUnsignedShort(); // Unused bootstrap method argument - } - } - } - - static void swallowMethodParameters(DataInput file) throws IOException { - int parameters_count = file.readUnsignedByte(); - for (int i = 0; i < parameters_count; i++) { - file.readUnsignedShort(); // Unused name_index - file.readUnsignedShort(); // Unused access_flags - } - } } --- a/classfile/package.html +++ a/classfile/package.html @@ -17,6 +17,9 @@ +

--- a/util/BCELComparator.java +++ a/util/BCELComparator.java @@ -21,6 +21,7 @@ package org.apache.tomcat.util.bcel.util; * Used for BCEL comparison strategy * * @author M. Dahm + * @version $Id$ * @since 5.2 */ public interface BCELComparator { --- a/util/ByteSequence.java +++ a/util/ByteSequence.java @@ -25,6 +25,7 @@ import java.io.DataInputStream; * via the `readByte()' method. This is used to implement a wrapper for the * Java byte code stream to gain some more readability. * + * @version $Id$ * @author M. Dahm */ public final class ByteSequence extends DataInputStream { --- a/util/FastDataInputStream.java +++ a/util/FastDataInputStream.java @@ -0,0 +1,372 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.DataInput; +import java.io.EOFException; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UTFDataFormatException; + + +/** + * Created by xshao on 7/31/14. + */ +public class FastDataInputStream extends FilterInputStream implements DataInput { + /** + * Creates a DataInputStream that uses the specified + * underlying InputStream. + * + * @param in the specified input stream + * @throws IOException + */ + + //Buff + private static int defaultBufferSize = 8192; + protected volatile byte buf[]; + protected int cnt; + protected int pos; + + //Constructor + public FastDataInputStream(InputStream in) { + super(in); + buf = new byte[defaultBufferSize]; + } + + public FastDataInputStream(InputStream in, int size) { + super(in); + if (size <= 0) { + throw new IllegalArgumentException("Buffer size <= 0"); + } + buf = new byte[size]; + } + + public final int read(byte b[]) throws IOException { + return this.read(b, 0, b.length); + } + + public int read(byte b[], int off, int len) + throws IOException + { + if ((off | len | (off + len) | (b.length - (off + len))) < 0) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + int n = 0; + for (;;) { + int nread = read1(b, off + n, len - n); + if (nread <= 0) + return (n == 0) ? nread : n; + n += nread; + if (n >= len) + return n; + // if not closed but no bytes available, return + InputStream input = in; + if (input != null && input.available() <= 0) + return n; + } + } + + private int read1(byte[] b, int off, int len) throws IOException { + int avail = cnt - pos; + if (avail <= 0) { + /* If the requested length is at least as large as the buffer, and + if there is no mark/reset activity, do not bother to copy the + bytes into the local buffer. In this way buffered streams will + cascade harmlessly. */ + if (len >= this.buf.length) { + return this.in.read(b, off, len); + } + fill(); + avail = cnt - pos; + if (avail <= 0) return -1; + } + int inc = (avail < len) ? avail : len; + System.arraycopy(this.buf, pos, b, off, inc); + pos += inc; + return inc; + } + + public final void readFully(byte b[]) throws IOException { +// System.out.println("readFully"); + + readFully(b, 0, b.length); + } + + @Override + public final void readFully(byte b[], int off, int len) throws IOException { + if (len < 0) + throw new IndexOutOfBoundsException(); + int n = 0; + while (n < len) { + int count = this.read(b, off + n, len - n); + if (count < 0) + throw new EOFException(); + n += count; + } + } + + @Override + public boolean readBoolean() throws IOException { + if (pos >= cnt) { + fill(); + if (pos >= cnt) + throw new EOFException(); + } + int ch = this.buf[pos++] & 0xff; + return (ch != 0); + } + + public final byte readByte() throws IOException { +// System.out.println("readByte"); + + if (pos >= cnt) { + fill(); + if (pos >= cnt) + throw new EOFException(); + } + return this.buf[pos++]; +// int ch = this.buf[pos++] & 0xff; +// return (byte)(ch); + } + + @Override + public int readUnsignedByte() throws IOException { + if (pos >= cnt) { + fill(); + if (pos >= cnt) + throw new EOFException(); + } + int ch = this.buf[pos++] & 0xff; + return ch; + } + + public final short readShort() throws IOException { +// System.out.println("readShort"); + + if(pos + 1 >= cnt){ + fill(); + if(pos + 1 >= cnt) throw new EOFException(); + } + int ch1 = this.buf[pos++] & 0xff; + int ch2 = this.buf[pos++] & 0xff; + return (short)((ch1 << 8) + (ch2 << 0)); + } + + public int readUnsignedShort() throws IOException{ +// System.out.println("readUnsignedShort"); + + if(pos + 1 >= cnt) { + fill(); + if(pos + 1 >= cnt) throw new EOFException(); + } + + int ch1 = this.buf[pos++] & 0xff; + int ch2 = this.buf[pos++] & 0xff; + return (ch1 << 8) + (ch2 << 0); + } + + public final char readChar() throws IOException { +// System.out.println("readChar"); + + if(pos + 1 >= cnt) { + fill(); + if(pos + 1 >= cnt) throw new EOFException(); + } + int ch1 = this.buf[pos++] & 0xff; + int ch2 = this.buf[pos++] & 0xff; + return (char)((ch1 << 8) + (ch2 << 0)); + } + + public final int readInt() throws IOException { +// System.out.println("readInt"); + + if(pos + 3 >= cnt){ + fill(); + if(pos + 3 >= cnt) throw new EOFException(); + } + int ch1 = this.buf[pos++] & 0xff; + int ch2 = this.buf[pos++] & 0xff; + int ch3 = this.buf[pos++] & 0xff; + int ch4 = this.buf[pos++] & 0xff; + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); + } + + private byte readBuffer[] = new byte[8]; + + public final long readLong() throws IOException { + readFully(readBuffer, 0, 8); + return (((long)readBuffer[0] << 56) + + ((long)(readBuffer[1] & 255) << 48) + + ((long)(readBuffer[2] & 255) << 40) + + ((long)(readBuffer[3] & 255) << 32) + + ((long)(readBuffer[4] & 255) << 24) + + ((readBuffer[5] & 255) << 16) + + ((readBuffer[6] & 255) << 8) + + ((readBuffer[7] & 255) << 0)); + } + + public final float readFloat() throws IOException { + return Float.intBitsToFloat(readInt()); + } + + @Override + public double readDouble() throws IOException { + return Double.longBitsToDouble(readLong()); + } + + public final String readUTF() throws IOException { +// System.out.println("readUTF"); + + return readUTF(this); + } + + private byte bytearr[] = new byte[80]; + private char chararr[] = new char[80]; + + public final String readUTF(DataInput in) throws IOException { + int utflen = this.readUnsignedShort(); + byte[] bytearr = null; + char[] chararr = null; + if (in instanceof FastDataInputStream) { + FastDataInputStream dis = (FastDataInputStream)in; + if (dis.bytearr.length < utflen){ + dis.bytearr = new byte[utflen*2]; + dis.chararr = new char[utflen*2]; + } + chararr = dis.chararr; + bytearr = dis.bytearr; + } else { + bytearr = new byte[utflen]; + chararr = new char[utflen]; + } + + int c, char2, char3; + int count = 0; + int chararr_count=0; + + this.readFully(bytearr, 0, utflen); + + while (count < utflen) { + c = (int) bytearr[count] & 0xff; + if (c > 127) break; + count++; + chararr[chararr_count++]=(char)c; + } + + while (count < utflen) { + c = (int) bytearr[count] & 0xff; + switch (c >> 4) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + /* 0xxxxxxx*/ + count++; + chararr[chararr_count++]=(char)c; + break; + case 12: case 13: + /* 110x xxxx 10xx xxxx*/ + count += 2; + if (count > utflen) + throw new UTFDataFormatException( + "malformed input: partial character at end"); + char2 = (int) bytearr[count-1]; + if ((char2 & 0xC0) != 0x80) + throw new UTFDataFormatException( + "malformed input around byte " + count); + chararr[chararr_count++]=(char)(((c & 0x1F) << 6) | + (char2 & 0x3F)); + break; + case 14: + /* 1110 xxxx 10xx xxxx 10xx xxxx */ + count += 3; + if (count > utflen) + throw new UTFDataFormatException( + "malformed input: partial character at end"); + char2 = (int) bytearr[count-2]; + char3 = (int) bytearr[count-1]; + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) + throw new UTFDataFormatException( + "malformed input around byte " + (count-1)); + chararr[chararr_count++]=(char)(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + default: + /* 10xx xxxx, 1111 xxxx */ + throw new UTFDataFormatException( + "malformed input around byte " + count); + } + } + // The number of chars produced may be less than utflen + return new String(chararr, 0, chararr_count); + } + + private void fill() throws IOException { +// System.out.println("fill"); + int remain = 0; + if(pos < cnt){ + remain = cnt - pos; + System.arraycopy(buf, cnt - remain, buf, 0, remain); + } + pos = 0; + int n = this.in.read(buf, remain, defaultBufferSize - remain); + cnt = pos + n + remain; + } + +// unimplemented + @Override + public int skipBytes(int n) throws IOException { + int avail = cnt - pos; + // total skipped + int total = 0; + // current skipped + int cur = 0; + if (avail <= 0) { + /* If the requested length is at least as large as the buffer, and + if there is no mark/reset activity, do not bother to copy the + bytes into the local buffer. In this way buffered streams will + cascade harmlessly. */ + while ((total 0)) { + total += cur; + } + fill(); + return total; + } + //num in the buffer is not enough + if(n > avail){ + pos += avail; + total += avail; + while ((total 0)) { + total += cur; + } + fill(); + return total; + } + //num in the buffer is + pos += n; + return n; + } + + @Override + public String readLine() throws IOException { + // TODO Auto-generated method stub + throw new IOException(); + } +}