Remove unused parts of apache bcel lib
This commit is contained in:
parent
8ef5f5655a
commit
6548caeddb
@ -26,51 +26,51 @@ public interface ExceptionConstants {
|
|||||||
|
|
||||||
/** The mother of all exceptions
|
/** The mother of all exceptions
|
||||||
*/
|
*/
|
||||||
public static final Class THROWABLE = Throwable.class;
|
public static final Class<Throwable> THROWABLE = Throwable.class;
|
||||||
/** Super class of any run-time exception
|
/** Super class of any run-time exception
|
||||||
*/
|
*/
|
||||||
public static final Class RUNTIME_EXCEPTION = RuntimeException.class;
|
public static final Class<RuntimeException> RUNTIME_EXCEPTION = RuntimeException.class;
|
||||||
/** Super class of any linking exception (aka Linkage Error)
|
/** Super class of any linking exception (aka Linkage Error)
|
||||||
*/
|
*/
|
||||||
public static final Class LINKING_EXCEPTION = LinkageError.class;
|
public static final Class<LinkageError> LINKING_EXCEPTION = LinkageError.class;
|
||||||
/** Linking Exceptions
|
/** Linking Exceptions
|
||||||
*/
|
*/
|
||||||
public static final Class CLASS_CIRCULARITY_ERROR = ClassCircularityError.class;
|
public static final Class<ClassCircularityError> CLASS_CIRCULARITY_ERROR = ClassCircularityError.class;
|
||||||
public static final Class CLASS_FORMAT_ERROR = ClassFormatError.class;
|
public static final Class<ClassFormatError> CLASS_FORMAT_ERROR = ClassFormatError.class;
|
||||||
public static final Class EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class;
|
public static final Class<ExceptionInInitializerError> EXCEPTION_IN_INITIALIZER_ERROR = ExceptionInInitializerError.class;
|
||||||
public static final Class INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class;
|
public static final Class<IncompatibleClassChangeError> INCOMPATIBLE_CLASS_CHANGE_ERROR = IncompatibleClassChangeError.class;
|
||||||
public static final Class ABSTRACT_METHOD_ERROR = AbstractMethodError.class;
|
public static final Class<AbstractMethodError> ABSTRACT_METHOD_ERROR = AbstractMethodError.class;
|
||||||
public static final Class ILLEGAL_ACCESS_ERROR = IllegalAccessError.class;
|
public static final Class<IllegalAccessError> ILLEGAL_ACCESS_ERROR = IllegalAccessError.class;
|
||||||
public static final Class INSTANTIATION_ERROR = InstantiationError.class;
|
public static final Class<InstantiationError> INSTANTIATION_ERROR = InstantiationError.class;
|
||||||
public static final Class NO_SUCH_FIELD_ERROR = NoSuchFieldError.class;
|
public static final Class<NoSuchFieldError> NO_SUCH_FIELD_ERROR = NoSuchFieldError.class;
|
||||||
public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class;
|
public static final Class<NoSuchMethodError> NO_SUCH_METHOD_ERROR = NoSuchMethodError.class;
|
||||||
public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class;
|
public static final Class<NoClassDefFoundError> NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class;
|
||||||
public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class;
|
public static final Class<UnsatisfiedLinkError> UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class;
|
||||||
public static final Class VERIFY_ERROR = VerifyError.class;
|
public static final Class<VerifyError> VERIFY_ERROR = VerifyError.class;
|
||||||
/* UnsupportedClassVersionError is new in JDK 1.2 */
|
/* UnsupportedClassVersionError is new in JDK 1.2 */
|
||||||
//public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class;
|
//public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class;
|
||||||
/** Run-Time Exceptions
|
/** Run-Time Exceptions
|
||||||
*/
|
*/
|
||||||
public static final Class NULL_POINTER_EXCEPTION = NullPointerException.class;
|
public static final Class<NullPointerException> NULL_POINTER_EXCEPTION = NullPointerException.class;
|
||||||
public static final Class ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
|
public static final Class<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
|
||||||
public static final Class ARITHMETIC_EXCEPTION = ArithmeticException.class;
|
public static final Class<ArithmeticException> ARITHMETIC_EXCEPTION = ArithmeticException.class;
|
||||||
public static final Class NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
|
public static final Class<NegativeArraySizeException> NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
|
||||||
public static final Class CLASS_CAST_EXCEPTION = ClassCastException.class;
|
public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class;
|
||||||
public static final Class ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
|
public static final Class<IllegalMonitorStateException> ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
|
||||||
/** Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual
|
/** Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual
|
||||||
* Machine Specification
|
* Machine Specification
|
||||||
*/
|
*/
|
||||||
public static final Class[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {
|
public static final Class<?>[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {
|
||||||
NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
|
NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
|
||||||
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR
|
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR
|
||||||
}; // Chapter 5.1
|
}; // Chapter 5.1
|
||||||
public static final Class[] EXCS_FIELD_AND_METHOD_RESOLUTION = {
|
public static final Class<?>[] EXCS_FIELD_AND_METHOD_RESOLUTION = {
|
||||||
NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR
|
NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR
|
||||||
}; // Chapter 5.2
|
}; // Chapter 5.2
|
||||||
public static final Class[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
|
public static final Class<?>[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
|
||||||
public static final Class[] EXCS_STRING_RESOLUTION = new Class[0];
|
public static final Class<?>[] EXCS_STRING_RESOLUTION = new Class[0];
|
||||||
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
||||||
public static final Class[] EXCS_ARRAY_EXCEPTION = {
|
public static final Class<?>[] EXCS_ARRAY_EXCEPTION = {
|
||||||
NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
|
NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ public abstract class Repository {
|
|||||||
* @throws ClassNotFoundException if the class could not be found or
|
* @throws ClassNotFoundException if the class could not be found or
|
||||||
* parsed correctly
|
* parsed correctly
|
||||||
*/
|
*/
|
||||||
public static JavaClass lookupClass( Class clazz ) throws ClassNotFoundException {
|
public static JavaClass lookupClass( Class<?> clazz ) throws ClassNotFoundException {
|
||||||
return _repository.loadClass(clazz);
|
return _repository.loadClass(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
import org.apache.bcel.Constants;
|
import org.apache.bcel.Constants;
|
||||||
import org.apache.bcel.generic.Type;
|
import org.apache.bcel.generic.Type;
|
||||||
import org.apache.bcel.util.BCELComparator;
|
import org.apache.bcel.util.BCELComparator;
|
||||||
@ -45,8 +46,12 @@ import org.apache.bcel.util.SyntheticRepository;
|
|||||||
* @see org.apache.bcel.generic.ClassGen
|
* @see org.apache.bcel.generic.ClassGen
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
||||||
*/
|
*/
|
||||||
public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable {
|
public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable<Object> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
private String file_name;
|
private String file_name;
|
||||||
private String package_name;
|
private String package_name;
|
||||||
private String source_file_name = "<Unknown>";
|
private String source_file_name = "<Unknown>";
|
||||||
@ -770,7 +775,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
*/
|
*/
|
||||||
public JavaClass[] getSuperClasses() throws ClassNotFoundException {
|
public JavaClass[] getSuperClasses() throws ClassNotFoundException {
|
||||||
JavaClass clazz = this;
|
JavaClass clazz = this;
|
||||||
List allSuperClasses = new ArrayList();
|
List<JavaClass> allSuperClasses = new ArrayList<JavaClass>();
|
||||||
for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
|
for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
|
||||||
allSuperClasses.add(clazz);
|
allSuperClasses.add(clazz);
|
||||||
}
|
}
|
||||||
@ -796,7 +801,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
*/
|
*/
|
||||||
public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
|
public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
|
||||||
ClassQueue queue = new ClassQueue();
|
ClassQueue queue = new ClassQueue();
|
||||||
Set allInterfaces = new TreeSet();
|
Set<JavaClass> allInterfaces = new TreeSet<JavaClass>();
|
||||||
queue.enqueue(this);
|
queue.enqueue(this);
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
JavaClass clazz = queue.dequeue();
|
JavaClass clazz = queue.dequeue();
|
||||||
|
@ -1,211 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import org.apache.bcel.classfile.Attribute;
|
|
||||||
import org.apache.bcel.classfile.Code;
|
|
||||||
import org.apache.bcel.classfile.CodeException;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.ConstantUtf8;
|
|
||||||
import org.apache.bcel.classfile.ConstantValue;
|
|
||||||
import org.apache.bcel.classfile.ExceptionTable;
|
|
||||||
import org.apache.bcel.classfile.InnerClass;
|
|
||||||
import org.apache.bcel.classfile.InnerClasses;
|
|
||||||
import org.apache.bcel.classfile.LineNumber;
|
|
||||||
import org.apache.bcel.classfile.LineNumberTable;
|
|
||||||
import org.apache.bcel.classfile.LocalVariable;
|
|
||||||
import org.apache.bcel.classfile.LocalVariableTable;
|
|
||||||
import org.apache.bcel.classfile.SourceFile;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert found attributes into HTML file.
|
|
||||||
*
|
|
||||||
* @version $Id: AttributeHTML.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
final class AttributeHTML implements org.apache.bcel.Constants {
|
|
||||||
|
|
||||||
private String class_name; // name of current class
|
|
||||||
private PrintWriter file; // file to write to
|
|
||||||
private int attr_count = 0;
|
|
||||||
private ConstantHTML constant_html;
|
|
||||||
private ConstantPool constant_pool;
|
|
||||||
|
|
||||||
|
|
||||||
AttributeHTML(String dir, String class_name, ConstantPool constant_pool,
|
|
||||||
ConstantHTML constant_html) throws IOException {
|
|
||||||
this.class_name = class_name;
|
|
||||||
this.constant_pool = constant_pool;
|
|
||||||
this.constant_html = constant_html;
|
|
||||||
file = new PrintWriter(new FileOutputStream(dir + class_name + "_attributes.html"));
|
|
||||||
file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private final String codeLink( int link, int method_number ) {
|
|
||||||
return "<A HREF=\"" + class_name + "_code.html#code" + method_number + "@" + link
|
|
||||||
+ "\" TARGET=Code>" + link + "</A>";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final void close() {
|
|
||||||
file.println("</TABLE></BODY></HTML>");
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final void writeAttribute( Attribute attribute, String anchor ) throws IOException {
|
|
||||||
writeAttribute(attribute, anchor, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
final void writeAttribute( Attribute attribute, String anchor, int method_number )
|
|
||||||
throws IOException {
|
|
||||||
byte tag = attribute.getTag();
|
|
||||||
int index;
|
|
||||||
if (tag == ATTR_UNKNOWN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
attr_count++; // Increment number of attributes found so far
|
|
||||||
if (attr_count % 2 == 0) {
|
|
||||||
file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
|
|
||||||
} else {
|
|
||||||
file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
|
|
||||||
}
|
|
||||||
file.println("<H4><A NAME=\"" + anchor + "\">" + attr_count + " " + ATTRIBUTE_NAMES[tag]
|
|
||||||
+ "</A></H4>");
|
|
||||||
/* Handle different attributes
|
|
||||||
*/
|
|
||||||
switch (tag) {
|
|
||||||
case ATTR_CODE:
|
|
||||||
Code c = (Code) attribute;
|
|
||||||
// Some directly printable values
|
|
||||||
file.print("<UL><LI>Maximum stack size = " + c.getMaxStack()
|
|
||||||
+ "</LI>\n<LI>Number of local variables = " + c.getMaxLocals()
|
|
||||||
+ "</LI>\n<LI><A HREF=\"" + class_name + "_code.html#method"
|
|
||||||
+ method_number + "\" TARGET=Code>Byte code</A></LI></UL>\n");
|
|
||||||
// Get handled exceptions and list them
|
|
||||||
CodeException[] ce = c.getExceptionTable();
|
|
||||||
int len = ce.length;
|
|
||||||
if (len > 0) {
|
|
||||||
file.print("<P><B>Exceptions handled</B><UL>");
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
int catch_type = ce[i].getCatchType(); // Index in constant pool
|
|
||||||
file.print("<LI>");
|
|
||||||
if (catch_type != 0) {
|
|
||||||
file.print(constant_html.referenceConstant(catch_type)); // Create Link to _cp.html
|
|
||||||
} else {
|
|
||||||
file.print("Any Exception");
|
|
||||||
}
|
|
||||||
file.print("<BR>(Ranging from lines "
|
|
||||||
+ codeLink(ce[i].getStartPC(), method_number) + " to "
|
|
||||||
+ codeLink(ce[i].getEndPC(), method_number) + ", handled at line "
|
|
||||||
+ codeLink(ce[i].getHandlerPC(), method_number) + ")</LI>");
|
|
||||||
}
|
|
||||||
file.print("</UL>");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ATTR_CONSTANT_VALUE:
|
|
||||||
index = ((ConstantValue) attribute).getConstantValueIndex();
|
|
||||||
// Reference _cp.html
|
|
||||||
file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
|
|
||||||
+ "\" TARGET=\"ConstantPool\">Constant value index(" + index
|
|
||||||
+ ")</A></UL>\n");
|
|
||||||
break;
|
|
||||||
case ATTR_SOURCE_FILE:
|
|
||||||
index = ((SourceFile) attribute).getSourceFileIndex();
|
|
||||||
// Reference _cp.html
|
|
||||||
file.print("<UL><LI><A HREF=\"" + class_name + "_cp.html#cp" + index
|
|
||||||
+ "\" TARGET=\"ConstantPool\">Source file index(" + index + ")</A></UL>\n");
|
|
||||||
break;
|
|
||||||
case ATTR_EXCEPTIONS:
|
|
||||||
// List thrown exceptions
|
|
||||||
int[] indices = ((ExceptionTable) attribute).getExceptionIndexTable();
|
|
||||||
file.print("<UL>");
|
|
||||||
for (int i = 0; i < indices.length; i++) {
|
|
||||||
file.print("<LI><A HREF=\"" + class_name + "_cp.html#cp" + indices[i]
|
|
||||||
+ "\" TARGET=\"ConstantPool\">Exception class index(" + indices[i]
|
|
||||||
+ ")</A>\n");
|
|
||||||
}
|
|
||||||
file.print("</UL>\n");
|
|
||||||
break;
|
|
||||||
case ATTR_LINE_NUMBER_TABLE:
|
|
||||||
LineNumber[] line_numbers = ((LineNumberTable) attribute).getLineNumberTable();
|
|
||||||
// List line number pairs
|
|
||||||
file.print("<P>");
|
|
||||||
for (int i = 0; i < line_numbers.length; i++) {
|
|
||||||
file.print("(" + line_numbers[i].getStartPC() + ", "
|
|
||||||
+ line_numbers[i].getLineNumber() + ")");
|
|
||||||
if (i < line_numbers.length - 1) {
|
|
||||||
file.print(", "); // breakable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ATTR_LOCAL_VARIABLE_TABLE:
|
|
||||||
LocalVariable[] vars = ((LocalVariableTable) attribute).getLocalVariableTable();
|
|
||||||
// List name, range and type
|
|
||||||
file.print("<UL>");
|
|
||||||
for (int i = 0; i < vars.length; i++) {
|
|
||||||
index = vars[i].getSignatureIndex();
|
|
||||||
String signature = ((ConstantUtf8) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_Utf8)).getBytes();
|
|
||||||
signature = Utility.signatureToString(signature, false);
|
|
||||||
int start = vars[i].getStartPC();
|
|
||||||
int end = (start + vars[i].getLength());
|
|
||||||
file.println("<LI>" + Class2HTML.referenceType(signature) + " <B>"
|
|
||||||
+ vars[i].getName() + "</B> in slot %" + vars[i].getIndex()
|
|
||||||
+ "<BR>Valid from lines " + "<A HREF=\"" + class_name
|
|
||||||
+ "_code.html#code" + method_number + "@" + start + "\" TARGET=Code>"
|
|
||||||
+ start + "</A> to " + "<A HREF=\"" + class_name + "_code.html#code"
|
|
||||||
+ method_number + "@" + end + "\" TARGET=Code>" + end + "</A></LI>");
|
|
||||||
}
|
|
||||||
file.print("</UL>\n");
|
|
||||||
break;
|
|
||||||
case ATTR_INNER_CLASSES:
|
|
||||||
InnerClass[] classes = ((InnerClasses) attribute).getInnerClasses();
|
|
||||||
// List inner classes
|
|
||||||
file.print("<UL>");
|
|
||||||
for (int i = 0; i < classes.length; i++) {
|
|
||||||
String name, access;
|
|
||||||
index = classes[i].getInnerNameIndex();
|
|
||||||
if (index > 0) {
|
|
||||||
name = ((ConstantUtf8) constant_pool.getConstant(index, CONSTANT_Utf8))
|
|
||||||
.getBytes();
|
|
||||||
} else {
|
|
||||||
name = "<anonymous>";
|
|
||||||
}
|
|
||||||
access = Utility.accessToString(classes[i].getInnerAccessFlags());
|
|
||||||
file.print("<LI><FONT COLOR=\"#FF0000\">" + access + "</FONT> "
|
|
||||||
+ constant_html.referenceConstant(classes[i].getInnerClassIndex())
|
|
||||||
+ " in class "
|
|
||||||
+ constant_html.referenceConstant(classes[i].getOuterClassIndex())
|
|
||||||
+ " named " + name + "</LI>\n");
|
|
||||||
}
|
|
||||||
file.print("</UL>\n");
|
|
||||||
break;
|
|
||||||
default: // Such as Unknown attribute or Deprecated
|
|
||||||
file.print("<P>" + attribute.toString());
|
|
||||||
}
|
|
||||||
file.println("</TD></TR>");
|
|
||||||
file.flush();
|
|
||||||
}
|
|
||||||
}
|
|
@ -76,7 +76,7 @@ class BCELFactory extends EmptyVisitor {
|
|||||||
_out = out;
|
_out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map branch_map = new HashMap(); // Map<Instruction, InstructionHandle>
|
private Map<Instruction, InstructionHandle> branch_map = new HashMap<Instruction, InstructionHandle>(); // Map<Instruction, InstructionHandle>
|
||||||
|
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
@ -239,7 +239,7 @@ class BCELFactory extends EmptyVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Memorize BranchInstructions that need an update
|
// Memorize BranchInstructions that need an update
|
||||||
private List branches = new ArrayList();
|
private List<BranchInstruction> branches = new ArrayList<BranchInstruction>();
|
||||||
|
|
||||||
|
|
||||||
public void visitBranchInstruction( BranchInstruction bi ) {
|
public void visitBranchInstruction( BranchInstruction bi ) {
|
||||||
@ -294,7 +294,7 @@ class BCELFactory extends EmptyVisitor {
|
|||||||
|
|
||||||
|
|
||||||
private void updateBranchTargets() {
|
private void updateBranchTargets() {
|
||||||
for (Iterator i = branches.iterator(); i.hasNext();) {
|
for (Iterator<BranchInstruction> i = branches.iterator(); i.hasNext();) {
|
||||||
BranchInstruction bi = (BranchInstruction) i.next();
|
BranchInstruction bi = (BranchInstruction) i.next();
|
||||||
BranchHandle bh = (BranchHandle) branch_map.get(bi);
|
BranchHandle bh = (BranchHandle) branch_map.get(bi);
|
||||||
int pos = bh.getPosition();
|
int pos = bh.getPosition();
|
||||||
|
@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.classfile.Attribute;
|
|
||||||
import org.apache.bcel.classfile.ClassParser;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read class file(s) and convert them into HTML files.
|
|
||||||
*
|
|
||||||
* Given a JavaClass object "class" that is in package "package" five files
|
|
||||||
* will be created in the specified directory.
|
|
||||||
*
|
|
||||||
* <OL>
|
|
||||||
* <LI> "package"."class".html as the main file which defines the frames for
|
|
||||||
* the following subfiles.
|
|
||||||
* <LI> "package"."class"_attributes.html contains all (known) attributes found in the file
|
|
||||||
* <LI> "package"."class"_cp.html contains the constant pool
|
|
||||||
* <LI> "package"."class"_code.html contains the byte code
|
|
||||||
* <LI> "package"."class"_methods.html contains references to all methods and fields of the class
|
|
||||||
* </OL>
|
|
||||||
*
|
|
||||||
* All subfiles reference each other appropiately, e.g. clicking on a
|
|
||||||
* method in the Method's frame will jump to the appropiate method in
|
|
||||||
* the Code frame.
|
|
||||||
*
|
|
||||||
* @version $Id: Class2HTML.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*/
|
|
||||||
public class Class2HTML implements Constants {
|
|
||||||
|
|
||||||
private JavaClass java_class; // current class object
|
|
||||||
private String dir;
|
|
||||||
private static String class_package; // name of package, unclean to make it static, but ...
|
|
||||||
private static String class_name; // name of current class, dito
|
|
||||||
private static ConstantPool constant_pool;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write contents of the given JavaClass into HTML files.
|
|
||||||
*
|
|
||||||
* @param java_class The class to write
|
|
||||||
* @param dir The directory to put the files in
|
|
||||||
*/
|
|
||||||
public Class2HTML(JavaClass java_class, String dir) throws IOException {
|
|
||||||
Method[] methods = java_class.getMethods();
|
|
||||||
this.java_class = java_class;
|
|
||||||
this.dir = dir;
|
|
||||||
class_name = java_class.getClassName(); // Remember full name
|
|
||||||
constant_pool = java_class.getConstantPool();
|
|
||||||
// Get package name by tacking off everything after the last `.'
|
|
||||||
int index = class_name.lastIndexOf('.');
|
|
||||||
if (index > -1) {
|
|
||||||
class_package = class_name.substring(0, index);
|
|
||||||
} else {
|
|
||||||
class_package = ""; // default package
|
|
||||||
}
|
|
||||||
ConstantHTML constant_html = new ConstantHTML(dir, class_name, class_package, methods,
|
|
||||||
constant_pool);
|
|
||||||
/* Attributes can't be written in one step, so we just open a file
|
|
||||||
* which will be written consequently.
|
|
||||||
*/
|
|
||||||
AttributeHTML attribute_html = new AttributeHTML(dir, class_name, constant_pool,
|
|
||||||
constant_html);
|
|
||||||
MethodHTML method_html = new MethodHTML(dir, class_name, methods, java_class.getFields(),
|
|
||||||
constant_html, attribute_html);
|
|
||||||
// Write main file (with frames, yuk)
|
|
||||||
writeMainHTML(attribute_html);
|
|
||||||
new CodeHTML(dir, class_name, methods, constant_pool, constant_html);
|
|
||||||
attribute_html.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main( String argv[] ) {
|
|
||||||
String[] file_name = new String[argv.length];
|
|
||||||
int files = 0;
|
|
||||||
ClassParser parser = null;
|
|
||||||
JavaClass java_class = null;
|
|
||||||
String zip_file = null;
|
|
||||||
char sep = System.getProperty("file.separator").toCharArray()[0];
|
|
||||||
String dir = "." + sep; // Where to store HTML files
|
|
||||||
try {
|
|
||||||
/* Parse command line arguments.
|
|
||||||
*/
|
|
||||||
for (int i = 0; i < argv.length; i++) {
|
|
||||||
if (argv[i].charAt(0) == '-') { // command line switch
|
|
||||||
if (argv[i].equals("-d")) { // Specify target directory, default `.
|
|
||||||
dir = argv[++i];
|
|
||||||
if (!dir.endsWith("" + sep)) {
|
|
||||||
dir = dir + sep;
|
|
||||||
}
|
|
||||||
new File(dir).mkdirs(); // Create target directory if necessary
|
|
||||||
} else if (argv[i].equals("-zip")) {
|
|
||||||
zip_file = argv[++i];
|
|
||||||
} else {
|
|
||||||
System.out.println("Unknown option " + argv[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
file_name[files++] = argv[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (files == 0) {
|
|
||||||
System.err.println("Class2HTML: No input files specified.");
|
|
||||||
} else { // Loop through files ...
|
|
||||||
for (int i = 0; i < files; i++) {
|
|
||||||
System.out.print("Processing " + file_name[i] + "...");
|
|
||||||
if (zip_file == null) {
|
|
||||||
parser = new ClassParser(file_name[i]); // Create parser object from file
|
|
||||||
} else {
|
|
||||||
parser = new ClassParser(zip_file, file_name[i]); // Create parser object from zip file
|
|
||||||
}
|
|
||||||
java_class = parser.parse();
|
|
||||||
new Class2HTML(java_class, dir);
|
|
||||||
System.out.println("Done.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println(e);
|
|
||||||
e.printStackTrace(System.out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility method that converts a class reference in the constant pool,
|
|
||||||
* i.e., an index to a string.
|
|
||||||
*/
|
|
||||||
static String referenceClass( int index ) {
|
|
||||||
String str = constant_pool.getConstantString(index, CONSTANT_Class);
|
|
||||||
str = Utility.compactClassName(str);
|
|
||||||
str = Utility.compactClassName(str, class_package + ".", true);
|
|
||||||
return "<A HREF=\"" + class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>" + str
|
|
||||||
+ "</A>";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static final String referenceType( String type ) {
|
|
||||||
String short_type = Utility.compactClassName(type);
|
|
||||||
short_type = Utility.compactClassName(short_type, class_package + ".", true);
|
|
||||||
int index = type.indexOf('['); // Type is an array?
|
|
||||||
String base_type = type;
|
|
||||||
if (index > -1) {
|
|
||||||
base_type = type.substring(0, index); // Tack of the `['
|
|
||||||
}
|
|
||||||
// test for basic type
|
|
||||||
if (base_type.equals("int") || base_type.equals("short") || base_type.equals("boolean")
|
|
||||||
|| base_type.equals("void") || base_type.equals("char") || base_type.equals("byte")
|
|
||||||
|| base_type.equals("long") || base_type.equals("double")
|
|
||||||
|| base_type.equals("float")) {
|
|
||||||
return "<FONT COLOR=\"#00FF00\">" + type + "</FONT>";
|
|
||||||
} else {
|
|
||||||
return "<A HREF=\"" + base_type + ".html\" TARGET=_top>" + short_type + "</A>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static String toHTML( String str ) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
try { // Filter any characters HTML doesn't like such as < and > in particular
|
|
||||||
for (int i = 0; i < str.length(); i++) {
|
|
||||||
char ch;
|
|
||||||
switch (ch = str.charAt(i)) {
|
|
||||||
case '<':
|
|
||||||
buf.append("<");
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
buf.append(">");
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
buf.append("\\n");
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
buf.append("\\r");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
buf.append(ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (StringIndexOutOfBoundsException e) {
|
|
||||||
} // Never occurs
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void writeMainHTML( AttributeHTML attribute_html ) throws IOException {
|
|
||||||
PrintWriter file = new PrintWriter(new FileOutputStream(dir + class_name + ".html"));
|
|
||||||
Attribute[] attributes = java_class.getAttributes();
|
|
||||||
file.println("<HTML>\n" + "<HEAD><TITLE>Documentation for " + class_name + "</TITLE>"
|
|
||||||
+ "</HEAD>\n" + "<FRAMESET BORDER=1 cols=\"30%,*\">\n"
|
|
||||||
+ "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"ConstantPool\" SRC=\""
|
|
||||||
+ class_name + "_cp.html" + "\"\n MARGINWIDTH=\"0\" "
|
|
||||||
+ "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n"
|
|
||||||
+ "<FRAME NAME=\"Attributes\" SRC=\"" + class_name + "_attributes.html"
|
|
||||||
+ "\"\n MARGINWIDTH=\"0\" "
|
|
||||||
+ "MARGINHEIGHT=\"0\" FRAMEBORDER=\"1\" SCROLLING=\"AUTO\">\n" + "</FRAMESET>\n"
|
|
||||||
+ "<FRAMESET BORDER=1 rows=\"80%,*\">\n" + "<FRAME NAME=\"Code\" SRC=\""
|
|
||||||
+ class_name + "_code.html\"\n MARGINWIDTH=0 "
|
|
||||||
+ "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
|
|
||||||
+ "<FRAME NAME=\"Methods\" SRC=\"" + class_name
|
|
||||||
+ "_methods.html\"\n MARGINWIDTH=0 "
|
|
||||||
+ "MARGINHEIGHT=0 FRAMEBORDER=1 SCROLLING=\"AUTO\">\n"
|
|
||||||
+ "</FRAMESET></FRAMESET></HTML>");
|
|
||||||
file.close();
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
attribute_html.writeAttribute(attributes[i], "class" + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,184 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.classfile.ClassParser;
|
|
||||||
import org.apache.bcel.classfile.ConstantClass;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.ConstantUtf8;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Drop in replacement for the standard class loader of the JVM. You can use it
|
|
||||||
* in conjunction with the JavaWrapper to dynamically modify/create classes
|
|
||||||
* as they're requested.</p>
|
|
||||||
*
|
|
||||||
* <p>This class loader recognizes special requests in a distinct
|
|
||||||
* format, i.e., when the name of the requested class contains with
|
|
||||||
* "$$BCEL$$" it calls the createClass() method with that name
|
|
||||||
* (everything bevor the $$BCEL$$ is considered to be the package
|
|
||||||
* name. You can subclass the class loader and override that
|
|
||||||
* method. "Normal" classes class can be modified by overriding the
|
|
||||||
* modifyClass() method which is called just before defineClass().</p>
|
|
||||||
*
|
|
||||||
* <p>There may be a number of packages where you have to use the
|
|
||||||
* default class loader (which may also be faster). You can define the
|
|
||||||
* set of packages where to use the system class loader in the
|
|
||||||
* constructor. The default value contains "java.", "sun.",
|
|
||||||
* "javax."</p>
|
|
||||||
*
|
|
||||||
* @version $Id: ClassLoader.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @see JavaWrapper
|
|
||||||
* @see ClassPath
|
|
||||||
*/
|
|
||||||
public class ClassLoader extends java.lang.ClassLoader {
|
|
||||||
|
|
||||||
public static final String[] DEFAULT_IGNORED_PACKAGES = {
|
|
||||||
"java.", "javax.", "sun."
|
|
||||||
};
|
|
||||||
private Hashtable classes = new Hashtable(); // Hashtable is synchronized thus thread-safe
|
|
||||||
private String[] ignored_packages;
|
|
||||||
private Repository repository = SyntheticRepository.getInstance();
|
|
||||||
|
|
||||||
|
|
||||||
/** Ignored packages are by default ( "java.", "sun.",
|
|
||||||
* "javax."), i.e. loaded by system class loader
|
|
||||||
*/
|
|
||||||
public ClassLoader() {
|
|
||||||
this(DEFAULT_IGNORED_PACKAGES);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @param deferTo delegate class loader to use for ignored packages
|
|
||||||
*/
|
|
||||||
public ClassLoader(java.lang.ClassLoader deferTo) {
|
|
||||||
super(deferTo);
|
|
||||||
this.ignored_packages = DEFAULT_IGNORED_PACKAGES;
|
|
||||||
this.repository = new ClassLoaderRepository(deferTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @param ignored_packages classes contained in these packages will be loaded
|
|
||||||
* with the system class loader
|
|
||||||
*/
|
|
||||||
public ClassLoader(String[] ignored_packages) {
|
|
||||||
this.ignored_packages = ignored_packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @param ignored_packages classes contained in these packages will be loaded
|
|
||||||
* with the system class loader
|
|
||||||
* @param deferTo delegate class loader to use for ignored packages
|
|
||||||
*/
|
|
||||||
public ClassLoader(java.lang.ClassLoader deferTo, String[] ignored_packages) {
|
|
||||||
this(ignored_packages);
|
|
||||||
this.repository = new ClassLoaderRepository(deferTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected Class loadClass( String class_name, boolean resolve ) throws ClassNotFoundException {
|
|
||||||
Class cl = null;
|
|
||||||
/* First try: lookup hash table.
|
|
||||||
*/
|
|
||||||
if ((cl = (Class) classes.get(class_name)) == null) {
|
|
||||||
/* Second try: Load system class using system class loader. You better
|
|
||||||
* don't mess around with them.
|
|
||||||
*/
|
|
||||||
for (int i = 0; i < ignored_packages.length; i++) {
|
|
||||||
if (class_name.startsWith(ignored_packages[i])) {
|
|
||||||
cl = getParent().loadClass(class_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cl == null) {
|
|
||||||
JavaClass clazz = null;
|
|
||||||
/* Third try: Special request?
|
|
||||||
*/
|
|
||||||
if (class_name.indexOf("$$BCEL$$") >= 0) {
|
|
||||||
clazz = createClass(class_name);
|
|
||||||
} else { // Fourth try: Load classes via repository
|
|
||||||
if ((clazz = repository.loadClass(class_name)) != null) {
|
|
||||||
clazz = modifyClass(clazz);
|
|
||||||
} else {
|
|
||||||
throw new ClassNotFoundException(class_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (clazz != null) {
|
|
||||||
byte[] bytes = clazz.getBytes();
|
|
||||||
cl = defineClass(class_name, bytes, 0, bytes.length);
|
|
||||||
} else {
|
|
||||||
cl = Class.forName(class_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resolve) {
|
|
||||||
resolveClass(cl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
classes.put(class_name, cl);
|
|
||||||
return cl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Override this method if you want to alter a class before it gets actually
|
|
||||||
* loaded. Does nothing by default.
|
|
||||||
*/
|
|
||||||
protected JavaClass modifyClass( JavaClass clazz ) {
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override this method to create you own classes on the fly. The
|
|
||||||
* name contains the special token $$BCEL$$. Everything before that
|
|
||||||
* token is consddered to be a package name. You can encode you own
|
|
||||||
* arguments into the subsequent string. You must regard however not
|
|
||||||
* to use any "illegal" characters, i.e., characters that may not
|
|
||||||
* appear in a Java class name too<br>
|
|
||||||
*
|
|
||||||
* The default implementation interprets the string as a encoded compressed
|
|
||||||
* Java class, unpacks and decodes it with the Utility.decode() method, and
|
|
||||||
* parses the resulting byte array and returns the resulting JavaClass object.
|
|
||||||
*
|
|
||||||
* @param class_name compressed byte code with "$$BCEL$$" in it
|
|
||||||
*/
|
|
||||||
protected JavaClass createClass( String class_name ) {
|
|
||||||
int index = class_name.indexOf("$$BCEL$$");
|
|
||||||
String real_name = class_name.substring(index + 8);
|
|
||||||
JavaClass clazz = null;
|
|
||||||
try {
|
|
||||||
byte[] bytes = Utility.decode(real_name, true);
|
|
||||||
ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes), "foo");
|
|
||||||
clazz = parser.parse();
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Adapt the class name to the passed value
|
|
||||||
ConstantPool cp = clazz.getConstantPool();
|
|
||||||
ConstantClass cl = (ConstantClass) cp.getConstant(clazz.getClassNameIndex(),
|
|
||||||
Constants.CONSTANT_Class);
|
|
||||||
ConstantUtf8 name = (ConstantUtf8) cp.getConstant(cl.getNameIndex(),
|
|
||||||
Constants.CONSTANT_Utf8);
|
|
||||||
name.setBytes(class_name.replace('.', '/'));
|
|
||||||
return clazz;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.bcel.classfile.ClassParser;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The repository maintains information about which classes have
|
|
||||||
* been loaded.
|
|
||||||
*
|
|
||||||
* It loads its data from the ClassLoader implementation
|
|
||||||
* passed into its constructor.
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.Repository
|
|
||||||
*
|
|
||||||
* @version $Id: ClassLoaderRepository.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @author David Dixon-Peugh
|
|
||||||
*/
|
|
||||||
public class ClassLoaderRepository implements Repository {
|
|
||||||
|
|
||||||
private java.lang.ClassLoader loader;
|
|
||||||
private Map loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
|
|
||||||
|
|
||||||
|
|
||||||
public ClassLoaderRepository(java.lang.ClassLoader loader) {
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a new JavaClass into this Repository.
|
|
||||||
*/
|
|
||||||
public void storeClass( JavaClass clazz ) {
|
|
||||||
loadedClasses.put(clazz.getClassName(), clazz);
|
|
||||||
clazz.setRepository(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove class from repository
|
|
||||||
*/
|
|
||||||
public void removeClass( JavaClass clazz ) {
|
|
||||||
loadedClasses.remove(clazz.getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find an already defined JavaClass.
|
|
||||||
*/
|
|
||||||
public JavaClass findClass( String className ) {
|
|
||||||
if (loadedClasses.containsKey(className)) {
|
|
||||||
return (JavaClass) loadedClasses.get(className);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Lookup a JavaClass object from the Class Name provided.
|
|
||||||
*/
|
|
||||||
public JavaClass loadClass( String className ) throws ClassNotFoundException {
|
|
||||||
String classFile = className.replace('.', '/');
|
|
||||||
JavaClass RC = findClass(className);
|
|
||||||
if (RC != null) {
|
|
||||||
return RC;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
InputStream is = loader.getResourceAsStream(classFile + ".class");
|
|
||||||
if (is == null) {
|
|
||||||
throw new ClassNotFoundException(className + " not found.");
|
|
||||||
}
|
|
||||||
ClassParser parser = new ClassParser(is, className);
|
|
||||||
RC = parser.parse();
|
|
||||||
storeClass(RC);
|
|
||||||
return RC;
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ClassNotFoundException(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass loadClass( Class clazz ) throws ClassNotFoundException {
|
|
||||||
return loadClass(clazz.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Clear all entries from cache.
|
|
||||||
*/
|
|
||||||
public void clear() {
|
|
||||||
loadedClasses.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @return null
|
|
||||||
*/
|
|
||||||
public ClassPath getClassPath() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -40,6 +40,10 @@ import java.util.zip.ZipFile;
|
|||||||
*/
|
*/
|
||||||
public class ClassPath implements Serializable {
|
public class ClassPath implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath();
|
public static final ClassPath SYSTEM_CLASS_PATH = new ClassPath();
|
||||||
private PathEntry[] paths;
|
private PathEntry[] paths;
|
||||||
private String class_path;
|
private String class_path;
|
||||||
@ -50,7 +54,7 @@ public class ClassPath implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public ClassPath(String class_path) {
|
public ClassPath(String class_path) {
|
||||||
this.class_path = class_path;
|
this.class_path = class_path;
|
||||||
List vec = new ArrayList();
|
List<PathEntry> vec = new ArrayList<PathEntry>();
|
||||||
for (StringTokenizer tok = new StringTokenizer(class_path, System
|
for (StringTokenizer tok = new StringTokenizer(class_path, System
|
||||||
.getProperty("path.separator")); tok.hasMoreTokens();) {
|
.getProperty("path.separator")); tok.hasMoreTokens();) {
|
||||||
String path = tok.nextToken();
|
String path = tok.nextToken();
|
||||||
@ -103,7 +107,7 @@ public class ClassPath implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final void getPathComponents( String path, List list ) {
|
private static final void getPathComponents( String path, List<String> list ) {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
|
StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
@ -126,12 +130,12 @@ public class ClassPath implements Serializable {
|
|||||||
String class_path = System.getProperty("java.class.path");
|
String class_path = System.getProperty("java.class.path");
|
||||||
String boot_path = System.getProperty("sun.boot.class.path");
|
String boot_path = System.getProperty("sun.boot.class.path");
|
||||||
String ext_path = System.getProperty("java.ext.dirs");
|
String ext_path = System.getProperty("java.ext.dirs");
|
||||||
List list = new ArrayList();
|
List<String> list = new ArrayList<String>();
|
||||||
getPathComponents(class_path, list);
|
getPathComponents(class_path, list);
|
||||||
getPathComponents(boot_path, list);
|
getPathComponents(boot_path, list);
|
||||||
List dirs = new ArrayList();
|
List<String> dirs = new ArrayList<String>();
|
||||||
getPathComponents(ext_path, dirs);
|
getPathComponents(ext_path, dirs);
|
||||||
for (Iterator e = dirs.iterator(); e.hasNext();) {
|
for (Iterator<String> e = dirs.iterator(); e.hasNext();) {
|
||||||
File ext_dir = new File((String) e.next());
|
File ext_dir = new File((String) e.next());
|
||||||
String[] extensions = ext_dir.list(new FilenameFilter() {
|
String[] extensions = ext_dir.list(new FilenameFilter() {
|
||||||
|
|
||||||
@ -147,7 +151,7 @@ public class ClassPath implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
for (Iterator e = list.iterator(); e.hasNext();) {
|
for (Iterator<String> e = list.iterator(); e.hasNext();) {
|
||||||
buf.append((String) e.next());
|
buf.append((String) e.next());
|
||||||
if (e.hasNext()) {
|
if (e.hasNext()) {
|
||||||
buf.append(File.pathSeparatorChar);
|
buf.append(File.pathSeparatorChar);
|
||||||
@ -269,6 +273,11 @@ public class ClassPath implements Serializable {
|
|||||||
|
|
||||||
private static abstract class PathEntry implements Serializable {
|
private static abstract class PathEntry implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
abstract ClassFile getClassFile( String name, String suffix ) throws IOException;
|
abstract ClassFile getClassFile( String name, String suffix ) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,6 +313,10 @@ public class ClassPath implements Serializable {
|
|||||||
|
|
||||||
private static class Dir extends PathEntry {
|
private static class Dir extends PathEntry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
private String dir;
|
private String dir;
|
||||||
|
|
||||||
|
|
||||||
@ -355,6 +368,10 @@ public class ClassPath implements Serializable {
|
|||||||
|
|
||||||
private static class Zip extends PathEntry {
|
private static class Zip extends PathEntry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
private ZipFile zip;
|
private ZipFile zip;
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,11 @@ import org.apache.bcel.classfile.JavaClass;
|
|||||||
*/
|
*/
|
||||||
public class ClassQueue implements java.io.Serializable {
|
public class ClassQueue implements java.io.Serializable {
|
||||||
|
|
||||||
protected LinkedList vec = new LinkedList();
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
protected LinkedList<JavaClass> vec = new LinkedList<JavaClass>();
|
||||||
|
|
||||||
|
|
||||||
public void enqueue( JavaClass clazz ) {
|
public void enqueue( JavaClass clazz ) {
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class implementing a (typesafe) set of JavaClass objects.
|
|
||||||
* Since JavaClass has no equals() method, the name of the class is
|
|
||||||
* used for comparison.
|
|
||||||
*
|
|
||||||
* @version $Id: ClassSet.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @see ClassStack
|
|
||||||
*/
|
|
||||||
public class ClassSet implements java.io.Serializable {
|
|
||||||
|
|
||||||
private Map _map = new HashMap();
|
|
||||||
|
|
||||||
|
|
||||||
public boolean add( JavaClass clazz ) {
|
|
||||||
boolean result = false;
|
|
||||||
if (!_map.containsKey(clazz.getClassName())) {
|
|
||||||
result = true;
|
|
||||||
_map.put(clazz.getClassName(), clazz);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void remove( JavaClass clazz ) {
|
|
||||||
_map.remove(clazz.getClassName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean empty() {
|
|
||||||
return _map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass[] toArray() {
|
|
||||||
Collection values = _map.values();
|
|
||||||
JavaClass[] classes = new JavaClass[values.size()];
|
|
||||||
values.toArray(classes);
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String[] getClassNames() {
|
|
||||||
return (String[]) _map.keySet().toArray(new String[_map.keySet().size()]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.util.Stack;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class implementing a (typesafe) stack of JavaClass objects.
|
|
||||||
*
|
|
||||||
* @version $Id: ClassStack.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @see Stack
|
|
||||||
*/
|
|
||||||
public class ClassStack implements java.io.Serializable {
|
|
||||||
|
|
||||||
private Stack stack = new Stack();
|
|
||||||
|
|
||||||
|
|
||||||
public void push( JavaClass clazz ) {
|
|
||||||
stack.push(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass pop() {
|
|
||||||
return (JavaClass) stack.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass top() {
|
|
||||||
return (JavaClass) stack.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public boolean empty() {
|
|
||||||
return stack.empty();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class implementing a (typesafe) collection of JavaClass
|
|
||||||
* objects. Contains the most important methods of a Vector.
|
|
||||||
*
|
|
||||||
* @version $Id: ClassVector.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*
|
|
||||||
* @deprecated as of 5.1.1 - 7/17/2005
|
|
||||||
*/
|
|
||||||
public class ClassVector implements java.io.Serializable {
|
|
||||||
|
|
||||||
protected List vec = new ArrayList();
|
|
||||||
|
|
||||||
|
|
||||||
public void addElement( JavaClass clazz ) {
|
|
||||||
vec.add(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass elementAt( int index ) {
|
|
||||||
return (JavaClass) vec.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void removeElementAt( int index ) {
|
|
||||||
vec.remove(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaClass[] toArray() {
|
|
||||||
JavaClass[] classes = new JavaClass[vec.size()];
|
|
||||||
vec.toArray(classes);
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,564 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.BitSet;
|
|
||||||
import org.apache.bcel.classfile.Attribute;
|
|
||||||
import org.apache.bcel.classfile.Code;
|
|
||||||
import org.apache.bcel.classfile.CodeException;
|
|
||||||
import org.apache.bcel.classfile.ConstantFieldref;
|
|
||||||
import org.apache.bcel.classfile.ConstantInterfaceMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantNameAndType;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.LocalVariable;
|
|
||||||
import org.apache.bcel.classfile.LocalVariableTable;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert code into HTML file.
|
|
||||||
*
|
|
||||||
* @version $Id: CodeHTML.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
final class CodeHTML implements org.apache.bcel.Constants {
|
|
||||||
|
|
||||||
private String class_name; // name of current class
|
|
||||||
private Method[] methods; // Methods to print
|
|
||||||
private PrintWriter file; // file to write to
|
|
||||||
private BitSet goto_set;
|
|
||||||
private ConstantPool constant_pool;
|
|
||||||
private ConstantHTML constant_html;
|
|
||||||
private static boolean wide = false;
|
|
||||||
|
|
||||||
|
|
||||||
CodeHTML(String dir, String class_name, Method[] methods, ConstantPool constant_pool,
|
|
||||||
ConstantHTML constant_html) throws IOException {
|
|
||||||
this.class_name = class_name;
|
|
||||||
this.methods = methods;
|
|
||||||
this.constant_pool = constant_pool;
|
|
||||||
this.constant_html = constant_html;
|
|
||||||
file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html"));
|
|
||||||
file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\">");
|
|
||||||
for (int i = 0; i < methods.length; i++) {
|
|
||||||
writeMethod(methods[i], i);
|
|
||||||
}
|
|
||||||
file.println("</BODY></HTML>");
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disassemble a stream of byte codes and return the
|
|
||||||
* string representation.
|
|
||||||
*
|
|
||||||
* @param stream data input stream
|
|
||||||
* @return String representation of byte code
|
|
||||||
*/
|
|
||||||
private final String codeToHTML( ByteSequence bytes, int method_number ) throws IOException {
|
|
||||||
short opcode = (short) bytes.readUnsignedByte();
|
|
||||||
StringBuffer buf;
|
|
||||||
String name, signature;
|
|
||||||
int default_offset = 0, low, high;
|
|
||||||
int index, class_index, vindex, constant;
|
|
||||||
int[] jump_table;
|
|
||||||
int no_pad_bytes = 0, offset;
|
|
||||||
buf = new StringBuffer(256);
|
|
||||||
buf.append("<TT>").append(OPCODE_NAMES[opcode]).append("</TT></TD><TD>");
|
|
||||||
/* Special case: Skip (0-3) padding bytes, i.e., the
|
|
||||||
* following bytes are 4-byte-aligned
|
|
||||||
*/
|
|
||||||
if ((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) {
|
|
||||||
int remainder = bytes.getIndex() % 4;
|
|
||||||
no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
|
|
||||||
for (int i = 0; i < no_pad_bytes; i++) {
|
|
||||||
bytes.readByte();
|
|
||||||
}
|
|
||||||
// Both cases have a field default_offset in common
|
|
||||||
default_offset = bytes.readInt();
|
|
||||||
}
|
|
||||||
switch (opcode) {
|
|
||||||
case TABLESWITCH:
|
|
||||||
low = bytes.readInt();
|
|
||||||
high = bytes.readInt();
|
|
||||||
offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
|
|
||||||
default_offset += offset;
|
|
||||||
buf.append("<TABLE BORDER=1><TR>");
|
|
||||||
// Print switch indices in first row (and default)
|
|
||||||
jump_table = new int[high - low + 1];
|
|
||||||
for (int i = 0; i < jump_table.length; i++) {
|
|
||||||
jump_table[i] = offset + bytes.readInt();
|
|
||||||
buf.append("<TH>").append(low + i).append("</TH>");
|
|
||||||
}
|
|
||||||
buf.append("<TH>default</TH></TR>\n<TR>");
|
|
||||||
// Print target and default indices in second row
|
|
||||||
for (int i = 0; i < jump_table.length; i++) {
|
|
||||||
buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
|
|
||||||
jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
|
|
||||||
}
|
|
||||||
buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
|
|
||||||
default_offset).append("\">").append(default_offset).append(
|
|
||||||
"</A></TD></TR>\n</TABLE>\n");
|
|
||||||
break;
|
|
||||||
/* Lookup switch has variable length arguments.
|
|
||||||
*/
|
|
||||||
case LOOKUPSWITCH:
|
|
||||||
int npairs = bytes.readInt();
|
|
||||||
offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
|
|
||||||
jump_table = new int[npairs];
|
|
||||||
default_offset += offset;
|
|
||||||
buf.append("<TABLE BORDER=1><TR>");
|
|
||||||
// Print switch indices in first row (and default)
|
|
||||||
for (int i = 0; i < npairs; i++) {
|
|
||||||
int match = bytes.readInt();
|
|
||||||
jump_table[i] = offset + bytes.readInt();
|
|
||||||
buf.append("<TH>").append(match).append("</TH>");
|
|
||||||
}
|
|
||||||
buf.append("<TH>default</TH></TR>\n<TR>");
|
|
||||||
// Print target and default indices in second row
|
|
||||||
for (int i = 0; i < npairs; i++) {
|
|
||||||
buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
|
|
||||||
jump_table[i]).append("\">").append(jump_table[i]).append("</A></TD>");
|
|
||||||
}
|
|
||||||
buf.append("<TD><A HREF=\"#code").append(method_number).append("@").append(
|
|
||||||
default_offset).append("\">").append(default_offset).append(
|
|
||||||
"</A></TD></TR>\n</TABLE>\n");
|
|
||||||
break;
|
|
||||||
/* Two address bytes + offset from start of byte stream form the
|
|
||||||
* jump target.
|
|
||||||
*/
|
|
||||||
case GOTO:
|
|
||||||
case IFEQ:
|
|
||||||
case IFGE:
|
|
||||||
case IFGT:
|
|
||||||
case IFLE:
|
|
||||||
case IFLT:
|
|
||||||
case IFNE:
|
|
||||||
case IFNONNULL:
|
|
||||||
case IFNULL:
|
|
||||||
case IF_ACMPEQ:
|
|
||||||
case IF_ACMPNE:
|
|
||||||
case IF_ICMPEQ:
|
|
||||||
case IF_ICMPGE:
|
|
||||||
case IF_ICMPGT:
|
|
||||||
case IF_ICMPLE:
|
|
||||||
case IF_ICMPLT:
|
|
||||||
case IF_ICMPNE:
|
|
||||||
case JSR:
|
|
||||||
index = (int) (bytes.getIndex() + bytes.readShort() - 1);
|
|
||||||
buf.append("<A HREF=\"#code").append(method_number).append("@").append(index)
|
|
||||||
.append("\">").append(index).append("</A>");
|
|
||||||
break;
|
|
||||||
/* Same for 32-bit wide jumps
|
|
||||||
*/
|
|
||||||
case GOTO_W:
|
|
||||||
case JSR_W:
|
|
||||||
int windex = bytes.getIndex() + bytes.readInt() - 1;
|
|
||||||
buf.append("<A HREF=\"#code").append(method_number).append("@").append(windex)
|
|
||||||
.append("\">").append(windex).append("</A>");
|
|
||||||
break;
|
|
||||||
/* Index byte references local variable (register)
|
|
||||||
*/
|
|
||||||
case ALOAD:
|
|
||||||
case ASTORE:
|
|
||||||
case DLOAD:
|
|
||||||
case DSTORE:
|
|
||||||
case FLOAD:
|
|
||||||
case FSTORE:
|
|
||||||
case ILOAD:
|
|
||||||
case ISTORE:
|
|
||||||
case LLOAD:
|
|
||||||
case LSTORE:
|
|
||||||
case RET:
|
|
||||||
if (wide) {
|
|
||||||
vindex = bytes.readShort();
|
|
||||||
wide = false; // Clear flag
|
|
||||||
} else {
|
|
||||||
vindex = bytes.readUnsignedByte();
|
|
||||||
}
|
|
||||||
buf.append("%").append(vindex);
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
* Remember wide byte which is used to form a 16-bit address in the
|
|
||||||
* following instruction. Relies on that the method is called again with
|
|
||||||
* the following opcode.
|
|
||||||
*/
|
|
||||||
case WIDE:
|
|
||||||
wide = true;
|
|
||||||
buf.append("(wide)");
|
|
||||||
break;
|
|
||||||
/* Array of basic type.
|
|
||||||
*/
|
|
||||||
case NEWARRAY:
|
|
||||||
buf.append("<FONT COLOR=\"#00FF00\">").append(TYPE_NAMES[bytes.readByte()]).append(
|
|
||||||
"</FONT>");
|
|
||||||
break;
|
|
||||||
/* Access object/class fields.
|
|
||||||
*/
|
|
||||||
case GETFIELD:
|
|
||||||
case GETSTATIC:
|
|
||||||
case PUTFIELD:
|
|
||||||
case PUTSTATIC:
|
|
||||||
index = bytes.readShort();
|
|
||||||
ConstantFieldref c1 = (ConstantFieldref) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_Fieldref);
|
|
||||||
class_index = c1.getClassIndex();
|
|
||||||
name = constant_pool.getConstantString(class_index, CONSTANT_Class);
|
|
||||||
name = Utility.compactClassName(name, false);
|
|
||||||
index = c1.getNameAndTypeIndex();
|
|
||||||
String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType);
|
|
||||||
if (name.equals(class_name)) { // Local field
|
|
||||||
buf.append("<A HREF=\"").append(class_name).append("_methods.html#field")
|
|
||||||
.append(field_name).append("\" TARGET=Methods>").append(field_name)
|
|
||||||
.append("</A>\n");
|
|
||||||
} else {
|
|
||||||
buf.append(constant_html.referenceConstant(class_index)).append(".").append(
|
|
||||||
field_name);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
/* Operands are references to classes in constant pool
|
|
||||||
*/
|
|
||||||
case CHECKCAST:
|
|
||||||
case INSTANCEOF:
|
|
||||||
case NEW:
|
|
||||||
index = bytes.readShort();
|
|
||||||
buf.append(constant_html.referenceConstant(index));
|
|
||||||
break;
|
|
||||||
/* Operands are references to methods in constant pool
|
|
||||||
*/
|
|
||||||
case INVOKESPECIAL:
|
|
||||||
case INVOKESTATIC:
|
|
||||||
case INVOKEVIRTUAL:
|
|
||||||
case INVOKEINTERFACE:
|
|
||||||
int m_index = bytes.readShort();
|
|
||||||
String str;
|
|
||||||
if (opcode == INVOKEINTERFACE) { // Special treatment needed
|
|
||||||
int nargs = bytes.readUnsignedByte(); // Redundant
|
|
||||||
int reserved = bytes.readUnsignedByte(); // Reserved
|
|
||||||
ConstantInterfaceMethodref c = (ConstantInterfaceMethodref) constant_pool
|
|
||||||
.getConstant(m_index, CONSTANT_InterfaceMethodref);
|
|
||||||
class_index = c.getClassIndex();
|
|
||||||
str = constant_pool.constantToString(c);
|
|
||||||
index = c.getNameAndTypeIndex();
|
|
||||||
} else {
|
|
||||||
ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(m_index,
|
|
||||||
CONSTANT_Methodref);
|
|
||||||
class_index = c.getClassIndex();
|
|
||||||
str = constant_pool.constantToString(c);
|
|
||||||
index = c.getNameAndTypeIndex();
|
|
||||||
}
|
|
||||||
name = Class2HTML.referenceClass(class_index);
|
|
||||||
str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant(
|
|
||||||
index, CONSTANT_NameAndType)));
|
|
||||||
// Get signature, i.e., types
|
|
||||||
ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_NameAndType);
|
|
||||||
signature = constant_pool.constantToString(c2.getSignatureIndex(), CONSTANT_Utf8);
|
|
||||||
String[] args = Utility.methodSignatureArgumentTypes(signature, false);
|
|
||||||
String type = Utility.methodSignatureReturnType(signature, false);
|
|
||||||
buf.append(name).append(".<A HREF=\"").append(class_name).append("_cp.html#cp")
|
|
||||||
.append(m_index).append("\" TARGET=ConstantPool>").append(str).append(
|
|
||||||
"</A>").append("(");
|
|
||||||
// List arguments
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
buf.append(Class2HTML.referenceType(args[i]));
|
|
||||||
if (i < args.length - 1) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Attach return type
|
|
||||||
buf.append("):").append(Class2HTML.referenceType(type));
|
|
||||||
break;
|
|
||||||
/* Operands are references to items in constant pool
|
|
||||||
*/
|
|
||||||
case LDC_W:
|
|
||||||
case LDC2_W:
|
|
||||||
index = bytes.readShort();
|
|
||||||
buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
|
|
||||||
.append("\" TARGET=\"ConstantPool\">").append(
|
|
||||||
Class2HTML.toHTML(constant_pool.constantToString(index,
|
|
||||||
constant_pool.getConstant(index).getTag()))).append("</a>");
|
|
||||||
break;
|
|
||||||
case LDC:
|
|
||||||
index = bytes.readUnsignedByte();
|
|
||||||
buf.append("<A HREF=\"").append(class_name).append("_cp.html#cp").append(index)
|
|
||||||
.append("\" TARGET=\"ConstantPool\">").append(
|
|
||||||
Class2HTML.toHTML(constant_pool.constantToString(index,
|
|
||||||
constant_pool.getConstant(index).getTag()))).append("</a>");
|
|
||||||
break;
|
|
||||||
/* Array of references.
|
|
||||||
*/
|
|
||||||
case ANEWARRAY:
|
|
||||||
index = bytes.readShort();
|
|
||||||
buf.append(constant_html.referenceConstant(index));
|
|
||||||
break;
|
|
||||||
/* Multidimensional array of references.
|
|
||||||
*/
|
|
||||||
case MULTIANEWARRAY:
|
|
||||||
index = bytes.readShort();
|
|
||||||
int dimensions = bytes.readByte();
|
|
||||||
buf.append(constant_html.referenceConstant(index)).append(":").append(dimensions)
|
|
||||||
.append("-dimensional");
|
|
||||||
break;
|
|
||||||
/* Increment local variable.
|
|
||||||
*/
|
|
||||||
case IINC:
|
|
||||||
if (wide) {
|
|
||||||
vindex = bytes.readShort();
|
|
||||||
constant = bytes.readShort();
|
|
||||||
wide = false;
|
|
||||||
} else {
|
|
||||||
vindex = bytes.readUnsignedByte();
|
|
||||||
constant = bytes.readByte();
|
|
||||||
}
|
|
||||||
buf.append("%").append(vindex).append(" ").append(constant);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (NO_OF_OPERANDS[opcode] > 0) {
|
|
||||||
for (int i = 0; i < TYPE_OF_OPERANDS[opcode].length; i++) {
|
|
||||||
switch (TYPE_OF_OPERANDS[opcode][i]) {
|
|
||||||
case T_BYTE:
|
|
||||||
buf.append(bytes.readUnsignedByte());
|
|
||||||
break;
|
|
||||||
case T_SHORT: // Either branch or index
|
|
||||||
buf.append(bytes.readShort());
|
|
||||||
break;
|
|
||||||
case T_INT:
|
|
||||||
buf.append(bytes.readInt());
|
|
||||||
break;
|
|
||||||
default: // Never reached
|
|
||||||
System.err.println("Unreachable default case reached!");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
buf.append(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.append("</TD>");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all target addresses in code, so that they can be marked
|
|
||||||
* with <A NAME = ...>. Target addresses are kept in an BitSet object.
|
|
||||||
*/
|
|
||||||
private final void findGotos( ByteSequence bytes, Method method, Code code ) throws IOException {
|
|
||||||
int index;
|
|
||||||
goto_set = new BitSet(bytes.available());
|
|
||||||
int opcode;
|
|
||||||
/* First get Code attribute from method and the exceptions handled
|
|
||||||
* (try .. catch) in this method. We only need the line number here.
|
|
||||||
*/
|
|
||||||
if (code != null) {
|
|
||||||
CodeException[] ce = code.getExceptionTable();
|
|
||||||
int len = ce.length;
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
goto_set.set(ce[i].getStartPC());
|
|
||||||
goto_set.set(ce[i].getEndPC());
|
|
||||||
goto_set.set(ce[i].getHandlerPC());
|
|
||||||
}
|
|
||||||
// Look for local variables and their range
|
|
||||||
Attribute[] attributes = code.getAttributes();
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
if (attributes[i].getTag() == ATTR_LOCAL_VARIABLE_TABLE) {
|
|
||||||
LocalVariable[] vars = ((LocalVariableTable) attributes[i])
|
|
||||||
.getLocalVariableTable();
|
|
||||||
for (int j = 0; j < vars.length; j++) {
|
|
||||||
int start = vars[j].getStartPC();
|
|
||||||
int end = (int) (start + vars[j].getLength());
|
|
||||||
goto_set.set(start);
|
|
||||||
goto_set.set(end);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get target addresses from GOTO, JSR, TABLESWITCH, etc.
|
|
||||||
for (int i = 0; bytes.available() > 0; i++) {
|
|
||||||
opcode = bytes.readUnsignedByte();
|
|
||||||
//System.out.println(OPCODE_NAMES[opcode]);
|
|
||||||
switch (opcode) {
|
|
||||||
case TABLESWITCH:
|
|
||||||
case LOOKUPSWITCH:
|
|
||||||
//bytes.readByte(); // Skip already read byte
|
|
||||||
int remainder = bytes.getIndex() % 4;
|
|
||||||
int no_pad_bytes = (remainder == 0) ? 0 : 4 - remainder;
|
|
||||||
int default_offset,
|
|
||||||
offset;
|
|
||||||
for (int j = 0; j < no_pad_bytes; j++) {
|
|
||||||
bytes.readByte();
|
|
||||||
}
|
|
||||||
// Both cases have a field default_offset in common
|
|
||||||
default_offset = bytes.readInt();
|
|
||||||
if (opcode == TABLESWITCH) {
|
|
||||||
int low = bytes.readInt();
|
|
||||||
int high = bytes.readInt();
|
|
||||||
offset = bytes.getIndex() - 12 - no_pad_bytes - 1;
|
|
||||||
default_offset += offset;
|
|
||||||
goto_set.set(default_offset);
|
|
||||||
for (int j = 0; j < (high - low + 1); j++) {
|
|
||||||
index = offset + bytes.readInt();
|
|
||||||
goto_set.set(index);
|
|
||||||
}
|
|
||||||
} else { // LOOKUPSWITCH
|
|
||||||
int npairs = bytes.readInt();
|
|
||||||
offset = bytes.getIndex() - 8 - no_pad_bytes - 1;
|
|
||||||
default_offset += offset;
|
|
||||||
goto_set.set(default_offset);
|
|
||||||
for (int j = 0; j < npairs; j++) {
|
|
||||||
int match = bytes.readInt();
|
|
||||||
index = offset + bytes.readInt();
|
|
||||||
goto_set.set(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GOTO:
|
|
||||||
case IFEQ:
|
|
||||||
case IFGE:
|
|
||||||
case IFGT:
|
|
||||||
case IFLE:
|
|
||||||
case IFLT:
|
|
||||||
case IFNE:
|
|
||||||
case IFNONNULL:
|
|
||||||
case IFNULL:
|
|
||||||
case IF_ACMPEQ:
|
|
||||||
case IF_ACMPNE:
|
|
||||||
case IF_ICMPEQ:
|
|
||||||
case IF_ICMPGE:
|
|
||||||
case IF_ICMPGT:
|
|
||||||
case IF_ICMPLE:
|
|
||||||
case IF_ICMPLT:
|
|
||||||
case IF_ICMPNE:
|
|
||||||
case JSR:
|
|
||||||
//bytes.readByte(); // Skip already read byte
|
|
||||||
index = bytes.getIndex() + bytes.readShort() - 1;
|
|
||||||
goto_set.set(index);
|
|
||||||
break;
|
|
||||||
case GOTO_W:
|
|
||||||
case JSR_W:
|
|
||||||
//bytes.readByte(); // Skip already read byte
|
|
||||||
index = bytes.getIndex() + bytes.readInt() - 1;
|
|
||||||
goto_set.set(index);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
bytes.unreadByte();
|
|
||||||
codeToHTML(bytes, 0); // Ignore output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write a single method with the byte code associated with it.
|
|
||||||
*/
|
|
||||||
private void writeMethod( Method method, int method_number ) throws IOException {
|
|
||||||
// Get raw signature
|
|
||||||
String signature = method.getSignature();
|
|
||||||
// Get array of strings containing the argument types
|
|
||||||
String[] args = Utility.methodSignatureArgumentTypes(signature, false);
|
|
||||||
// Get return type string
|
|
||||||
String type = Utility.methodSignatureReturnType(signature, false);
|
|
||||||
// Get method name
|
|
||||||
String name = method.getName();
|
|
||||||
String html_name = Class2HTML.toHTML(name);
|
|
||||||
// Get method's access flags
|
|
||||||
String access = Utility.accessToString(method.getAccessFlags());
|
|
||||||
access = Utility.replace(access, " ", " ");
|
|
||||||
// Get the method's attributes, the Code Attribute in particular
|
|
||||||
Attribute[] attributes = method.getAttributes();
|
|
||||||
file.print("<P><B><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + "<A NAME=method"
|
|
||||||
+ method_number + ">" + Class2HTML.referenceType(type) + "</A> <A HREF=\""
|
|
||||||
+ class_name + "_methods.html#method" + method_number + "\" TARGET=Methods>"
|
|
||||||
+ html_name + "</A>(");
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
file.print(Class2HTML.referenceType(args[i]));
|
|
||||||
if (i < args.length - 1) {
|
|
||||||
file.print(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.println(")</B></P>");
|
|
||||||
Code c = null;
|
|
||||||
byte[] code = null;
|
|
||||||
if (attributes.length > 0) {
|
|
||||||
file.print("<H4>Attributes</H4><UL>\n");
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
byte tag = attributes[i].getTag();
|
|
||||||
if (tag != ATTR_UNKNOWN) {
|
|
||||||
file.print("<LI><A HREF=\"" + class_name + "_attributes.html#method"
|
|
||||||
+ method_number + "@" + i + "\" TARGET=Attributes>"
|
|
||||||
+ ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
|
|
||||||
} else {
|
|
||||||
file.print("<LI>" + attributes[i] + "</LI>");
|
|
||||||
}
|
|
||||||
if (tag == ATTR_CODE) {
|
|
||||||
c = (Code) attributes[i];
|
|
||||||
Attribute[] attributes2 = c.getAttributes();
|
|
||||||
code = c.getCode();
|
|
||||||
file.print("<UL>");
|
|
||||||
for (int j = 0; j < attributes2.length; j++) {
|
|
||||||
tag = attributes2[j].getTag();
|
|
||||||
file.print("<LI><A HREF=\"" + class_name + "_attributes.html#" + "method"
|
|
||||||
+ method_number + "@" + i + "@" + j + "\" TARGET=Attributes>"
|
|
||||||
+ ATTRIBUTE_NAMES[tag] + "</A></LI>\n");
|
|
||||||
}
|
|
||||||
file.print("</UL>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.println("</UL>");
|
|
||||||
}
|
|
||||||
if (code != null) { // No code, an abstract method, e.g.
|
|
||||||
//System.out.println(name + "\n" + Utility.codeToString(code, constant_pool, 0, -1));
|
|
||||||
// Print the byte code
|
|
||||||
ByteSequence stream = new ByteSequence(code);
|
|
||||||
stream.mark(stream.available());
|
|
||||||
findGotos(stream, method, c);
|
|
||||||
stream.reset();
|
|
||||||
file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Byte<BR>offset</TH>"
|
|
||||||
+ "<TH ALIGN=LEFT>Instruction</TH><TH ALIGN=LEFT>Argument</TH>");
|
|
||||||
for (int i = 0; stream.available() > 0; i++) {
|
|
||||||
int offset = stream.getIndex();
|
|
||||||
String str = codeToHTML(stream, method_number);
|
|
||||||
String anchor = "";
|
|
||||||
/* Set an anchor mark if this line is targetted by a goto, jsr, etc.
|
|
||||||
* Defining an anchor for every line is very inefficient!
|
|
||||||
*/
|
|
||||||
if (goto_set.get(offset)) {
|
|
||||||
anchor = "<A NAME=code" + method_number + "@" + offset + "></A>";
|
|
||||||
}
|
|
||||||
String anchor2;
|
|
||||||
if (stream.getIndex() == code.length) {
|
|
||||||
anchor2 = "<A NAME=code" + method_number + "@" + code.length + ">" + offset
|
|
||||||
+ "</A>";
|
|
||||||
} else {
|
|
||||||
anchor2 = "" + offset;
|
|
||||||
}
|
|
||||||
file
|
|
||||||
.println("<TR VALIGN=TOP><TD>" + anchor2 + "</TD><TD>" + anchor + str
|
|
||||||
+ "</TR>");
|
|
||||||
}
|
|
||||||
// Mark last line, may be targetted from Attributes window
|
|
||||||
file.println("<TR><TD> </A></TD></TR>");
|
|
||||||
file.println("</TABLE>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,234 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import org.apache.bcel.classfile.Constant;
|
|
||||||
import org.apache.bcel.classfile.ConstantClass;
|
|
||||||
import org.apache.bcel.classfile.ConstantFieldref;
|
|
||||||
import org.apache.bcel.classfile.ConstantInterfaceMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantNameAndType;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.ConstantString;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert constant pool into HTML file.
|
|
||||||
*
|
|
||||||
* @version $Id: ConstantHTML.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
final class ConstantHTML implements org.apache.bcel.Constants {
|
|
||||||
|
|
||||||
private String class_name; // name of current class
|
|
||||||
private String class_package; // name of package
|
|
||||||
private ConstantPool constant_pool; // reference to constant pool
|
|
||||||
private PrintWriter file; // file to write to
|
|
||||||
private String[] constant_ref; // String to return for cp[i]
|
|
||||||
private Constant[] constants; // The constants in the cp
|
|
||||||
private Method[] methods;
|
|
||||||
|
|
||||||
|
|
||||||
ConstantHTML(String dir, String class_name, String class_package, Method[] methods,
|
|
||||||
ConstantPool constant_pool) throws IOException {
|
|
||||||
this.class_name = class_name;
|
|
||||||
this.class_package = class_package;
|
|
||||||
this.constant_pool = constant_pool;
|
|
||||||
this.methods = methods;
|
|
||||||
constants = constant_pool.getConstantPool();
|
|
||||||
file = new PrintWriter(new FileOutputStream(dir + class_name + "_cp.html"));
|
|
||||||
constant_ref = new String[constants.length];
|
|
||||||
constant_ref[0] = "<unknown>";
|
|
||||||
file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
|
|
||||||
// Loop through constants, constants[0] is reserved
|
|
||||||
for (int i = 1; i < constants.length; i++) {
|
|
||||||
if (i % 2 == 0) {
|
|
||||||
file.print("<TR BGCOLOR=\"#C0C0C0\"><TD>");
|
|
||||||
} else {
|
|
||||||
file.print("<TR BGCOLOR=\"#A0A0A0\"><TD>");
|
|
||||||
}
|
|
||||||
if (constants[i] != null) {
|
|
||||||
writeConstant(i);
|
|
||||||
}
|
|
||||||
file.print("</TD></TR>\n");
|
|
||||||
}
|
|
||||||
file.println("</TABLE></BODY></HTML>");
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
String referenceConstant( int index ) {
|
|
||||||
return constant_ref[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void writeConstant( int index ) {
|
|
||||||
byte tag = constants[index].getTag();
|
|
||||||
int class_index, name_index;
|
|
||||||
String ref;
|
|
||||||
// The header is always the same
|
|
||||||
file.println("<H4> <A NAME=cp" + index + ">" + index + "</A> " + CONSTANT_NAMES[tag]
|
|
||||||
+ "</H4>");
|
|
||||||
/* For every constant type get the needed parameters and print them appropiately
|
|
||||||
*/
|
|
||||||
switch (tag) {
|
|
||||||
case CONSTANT_InterfaceMethodref:
|
|
||||||
case CONSTANT_Methodref:
|
|
||||||
// Get class_index and name_and_type_index, depending on type
|
|
||||||
if (tag == CONSTANT_Methodref) {
|
|
||||||
ConstantMethodref c = (ConstantMethodref) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_Methodref);
|
|
||||||
class_index = c.getClassIndex();
|
|
||||||
name_index = c.getNameAndTypeIndex();
|
|
||||||
} else {
|
|
||||||
ConstantInterfaceMethodref c1 = (ConstantInterfaceMethodref) constant_pool
|
|
||||||
.getConstant(index, CONSTANT_InterfaceMethodref);
|
|
||||||
class_index = c1.getClassIndex();
|
|
||||||
name_index = c1.getNameAndTypeIndex();
|
|
||||||
}
|
|
||||||
// Get method name and its class
|
|
||||||
String method_name = constant_pool.constantToString(name_index,
|
|
||||||
CONSTANT_NameAndType);
|
|
||||||
String html_method_name = Class2HTML.toHTML(method_name);
|
|
||||||
// Partially compacted class name, i.e., / -> .
|
|
||||||
String method_class = constant_pool.constantToString(class_index, CONSTANT_Class);
|
|
||||||
String short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang.
|
|
||||||
short_method_class = Utility.compactClassName(method_class); // I.e., remove java.lang.
|
|
||||||
short_method_class = Utility.compactClassName(short_method_class, class_package
|
|
||||||
+ ".", true); // Remove class package prefix
|
|
||||||
// Get method signature
|
|
||||||
ConstantNameAndType c2 = (ConstantNameAndType) constant_pool.getConstant(
|
|
||||||
name_index, CONSTANT_NameAndType);
|
|
||||||
String signature = constant_pool.constantToString(c2.getSignatureIndex(),
|
|
||||||
CONSTANT_Utf8);
|
|
||||||
// Get array of strings containing the argument types
|
|
||||||
String[] args = Utility.methodSignatureArgumentTypes(signature, false);
|
|
||||||
// Get return type string
|
|
||||||
String type = Utility.methodSignatureReturnType(signature, false);
|
|
||||||
String ret_type = Class2HTML.referenceType(type);
|
|
||||||
StringBuffer buf = new StringBuffer("(");
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
buf.append(Class2HTML.referenceType(args[i]));
|
|
||||||
if (i < args.length - 1) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.append(")");
|
|
||||||
String arg_types = buf.toString();
|
|
||||||
if (method_class.equals(class_name)) {
|
|
||||||
ref = "<A HREF=\"" + class_name + "_code.html#method"
|
|
||||||
+ getMethodNumber(method_name + signature) + "\" TARGET=Code>"
|
|
||||||
+ html_method_name + "</A>";
|
|
||||||
} else {
|
|
||||||
ref = "<A HREF=\"" + method_class + ".html" + "\" TARGET=_top>"
|
|
||||||
+ short_method_class + "</A>." + html_method_name;
|
|
||||||
}
|
|
||||||
constant_ref[index] = ret_type + " <A HREF=\"" + class_name + "_cp.html#cp"
|
|
||||||
+ class_index + "\" TARGET=Constants>" + short_method_class
|
|
||||||
+ "</A>.<A HREF=\"" + class_name + "_cp.html#cp" + index
|
|
||||||
+ "\" TARGET=ConstantPool>" + html_method_name + "</A> " + arg_types;
|
|
||||||
file.println("<P><TT>" + ret_type + " " + ref + arg_types
|
|
||||||
+ " </TT>\n<UL>" + "<LI><A HREF=\"#cp" + class_index
|
|
||||||
+ "\">Class index(" + class_index + ")</A>\n" + "<LI><A HREF=\"#cp"
|
|
||||||
+ name_index + "\">NameAndType index(" + name_index + ")</A></UL>");
|
|
||||||
break;
|
|
||||||
case CONSTANT_Fieldref:
|
|
||||||
// Get class_index and name_and_type_index
|
|
||||||
ConstantFieldref c3 = (ConstantFieldref) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_Fieldref);
|
|
||||||
class_index = c3.getClassIndex();
|
|
||||||
name_index = c3.getNameAndTypeIndex();
|
|
||||||
// Get method name and its class (compacted)
|
|
||||||
String field_class = constant_pool.constantToString(class_index, CONSTANT_Class);
|
|
||||||
String short_field_class = Utility.compactClassName(field_class); // I.e., remove java.lang.
|
|
||||||
short_field_class = Utility.compactClassName(short_field_class,
|
|
||||||
class_package + ".", true); // Remove class package prefix
|
|
||||||
String field_name = constant_pool
|
|
||||||
.constantToString(name_index, CONSTANT_NameAndType);
|
|
||||||
if (field_class.equals(class_name)) {
|
|
||||||
ref = "<A HREF=\"" + field_class + "_methods.html#field" + field_name
|
|
||||||
+ "\" TARGET=Methods>" + field_name + "</A>";
|
|
||||||
} else {
|
|
||||||
ref = "<A HREF=\"" + field_class + ".html\" TARGET=_top>" + short_field_class
|
|
||||||
+ "</A>." + field_name + "\n";
|
|
||||||
}
|
|
||||||
constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + class_index
|
|
||||||
+ "\" TARGET=Constants>" + short_field_class + "</A>.<A HREF=\""
|
|
||||||
+ class_name + "_cp.html#cp" + index + "\" TARGET=ConstantPool>"
|
|
||||||
+ field_name + "</A>";
|
|
||||||
file.println("<P><TT>" + ref + "</TT><BR>\n" + "<UL>" + "<LI><A HREF=\"#cp"
|
|
||||||
+ class_index + "\">Class(" + class_index + ")</A><BR>\n"
|
|
||||||
+ "<LI><A HREF=\"#cp" + name_index + "\">NameAndType(" + name_index
|
|
||||||
+ ")</A></UL>");
|
|
||||||
break;
|
|
||||||
case CONSTANT_Class:
|
|
||||||
ConstantClass c4 = (ConstantClass) constant_pool.getConstant(index, CONSTANT_Class);
|
|
||||||
name_index = c4.getNameIndex();
|
|
||||||
String class_name2 = constant_pool.constantToString(index, tag); // / -> .
|
|
||||||
String short_class_name = Utility.compactClassName(class_name2); // I.e., remove java.lang.
|
|
||||||
short_class_name = Utility.compactClassName(short_class_name, class_package + ".",
|
|
||||||
true); // Remove class package prefix
|
|
||||||
ref = "<A HREF=\"" + class_name2 + ".html\" TARGET=_top>" + short_class_name
|
|
||||||
+ "</A>";
|
|
||||||
constant_ref[index] = "<A HREF=\"" + class_name + "_cp.html#cp" + index
|
|
||||||
+ "\" TARGET=ConstantPool>" + short_class_name + "</A>";
|
|
||||||
file.println("<P><TT>" + ref + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
|
|
||||||
+ "\">Name index(" + name_index + ")</A></UL>\n");
|
|
||||||
break;
|
|
||||||
case CONSTANT_String:
|
|
||||||
ConstantString c5 = (ConstantString) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_String);
|
|
||||||
name_index = c5.getStringIndex();
|
|
||||||
String str = Class2HTML.toHTML(constant_pool.constantToString(index, tag));
|
|
||||||
file.println("<P><TT>" + str + "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index
|
|
||||||
+ "\">Name index(" + name_index + ")</A></UL>\n");
|
|
||||||
break;
|
|
||||||
case CONSTANT_NameAndType:
|
|
||||||
ConstantNameAndType c6 = (ConstantNameAndType) constant_pool.getConstant(index,
|
|
||||||
CONSTANT_NameAndType);
|
|
||||||
name_index = c6.getNameIndex();
|
|
||||||
int signature_index = c6.getSignatureIndex();
|
|
||||||
file.println("<P><TT>"
|
|
||||||
+ Class2HTML.toHTML(constant_pool.constantToString(index, tag))
|
|
||||||
+ "</TT><UL>" + "<LI><A HREF=\"#cp" + name_index + "\">Name index("
|
|
||||||
+ name_index + ")</A>\n" + "<LI><A HREF=\"#cp" + signature_index
|
|
||||||
+ "\">Signature index(" + signature_index + ")</A></UL>\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
file
|
|
||||||
.println("<P><TT>"
|
|
||||||
+ Class2HTML.toHTML(constant_pool.constantToString(index, tag))
|
|
||||||
+ "</TT>\n");
|
|
||||||
} // switch
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private final int getMethodNumber( String str ) {
|
|
||||||
for (int i = 0; i < methods.length; i++) {
|
|
||||||
String cmp = methods[i].getName() + methods[i].getSignature();
|
|
||||||
if (cmp.equals(str)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,472 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.generic.ClassGenException;
|
|
||||||
import org.apache.bcel.generic.Instruction;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.InstructionList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* InstructionFinder is a tool to search for given instructions patterns, i.e.,
|
|
||||||
* match sequences of instructions in an instruction list via regular
|
|
||||||
* expressions. This can be used, e.g., in order to implement a peep hole
|
|
||||||
* optimizer that looks for code patterns and replaces them with faster
|
|
||||||
* equivalents.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This class internally uses the <a href="http://jakarta.apache.org/regexp/">
|
|
||||||
* Regexp</a> package to search for regular expressions.
|
|
||||||
*
|
|
||||||
* A typical application would look like this:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* InstructionFinder f = new InstructionFinder(il);
|
|
||||||
* String pat = "IfInstruction ICONST_0 GOTO ICONST_1 NOP (IFEQ|IFNE)";
|
|
||||||
*
|
|
||||||
* for(Iterator i = f.search(pat, constraint); i.hasNext(); ) {
|
|
||||||
* InstructionHandle[] match = (InstructionHandle[])i.next();
|
|
||||||
* ...
|
|
||||||
* il.delete(match[1], match[5]);
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @version $Id: InstructionFinder.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @see Instruction
|
|
||||||
* @see InstructionList
|
|
||||||
*/
|
|
||||||
public class InstructionFinder {
|
|
||||||
|
|
||||||
private static final int OFFSET = 32767; // char + OFFSET is
|
|
||||||
// outside of
|
|
||||||
// LATIN-1
|
|
||||||
private static final int NO_OPCODES = 256; // Potential number,
|
|
||||||
// some are not used
|
|
||||||
private static final Map map = new HashMap(); // Map<String,Pattern>
|
|
||||||
private InstructionList il;
|
|
||||||
private String il_string; // instruction list
|
|
||||||
// as string
|
|
||||||
private InstructionHandle[] handles; // map instruction
|
|
||||||
|
|
||||||
|
|
||||||
// list to array
|
|
||||||
/**
|
|
||||||
* @param il
|
|
||||||
* instruction list to search for given patterns
|
|
||||||
*/
|
|
||||||
public InstructionFinder(InstructionList il) {
|
|
||||||
this.il = il;
|
|
||||||
reread();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reread the instruction list, e.g., after you've altered the list upon a
|
|
||||||
* match.
|
|
||||||
*/
|
|
||||||
public final void reread() {
|
|
||||||
int size = il.getLength();
|
|
||||||
char[] buf = new char[size]; // Create a string with length equal to il
|
|
||||||
// length
|
|
||||||
handles = il.getInstructionHandles();
|
|
||||||
// Map opcodes to characters
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
buf[i] = makeChar(handles[i].getInstruction().getOpcode());
|
|
||||||
}
|
|
||||||
il_string = new String(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map symbolic instruction names like "getfield" to a single character.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* instruction pattern in lower case
|
|
||||||
* @return encoded string for a pattern such as "BranchInstruction".
|
|
||||||
*/
|
|
||||||
private static final String mapName( String pattern ) {
|
|
||||||
String result = (String) map.get(pattern);
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (short i = 0; i < NO_OPCODES; i++) {
|
|
||||||
if (pattern.equals(Constants.OPCODE_NAMES[i])) {
|
|
||||||
return "" + makeChar(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Instruction unknown: " + pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace symbolic names of instructions with the appropiate character and
|
|
||||||
* remove all white space from string. Meta characters such as +, * are
|
|
||||||
* ignored.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* The pattern to compile
|
|
||||||
* @return translated regular expression string
|
|
||||||
*/
|
|
||||||
private static final String compilePattern( String pattern ) {
|
|
||||||
//Bug: 38787 - Instructions are assumed to be english, to avoid odd Locale issues
|
|
||||||
String lower = pattern.toLowerCase(Locale.ENGLISH);
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
int size = pattern.length();
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
char ch = lower.charAt(i);
|
|
||||||
if (Character.isLetterOrDigit(ch)) {
|
|
||||||
StringBuffer name = new StringBuffer();
|
|
||||||
while ((Character.isLetterOrDigit(ch) || ch == '_') && i < size) {
|
|
||||||
name.append(ch);
|
|
||||||
if (++i < size) {
|
|
||||||
ch = lower.charAt(i);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i--;
|
|
||||||
buf.append(mapName(name.toString()));
|
|
||||||
} else if (!Character.isWhitespace(ch)) {
|
|
||||||
buf.append(ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the matched piece of code as an array of instruction (handles)
|
|
||||||
*/
|
|
||||||
private InstructionHandle[] getMatch( int matched_from, int match_length ) {
|
|
||||||
InstructionHandle[] match = new InstructionHandle[match_length];
|
|
||||||
System.arraycopy(handles, matched_from, match, 0, match_length);
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for the given pattern in the instruction list. You can search for
|
|
||||||
* any valid opcode via its symbolic name, e.g. "istore". You can also use a
|
|
||||||
* super class or an interface name to match a whole set of instructions, e.g.
|
|
||||||
* "BranchInstruction" or "LoadInstruction". "istore" is also an alias for all
|
|
||||||
* "istore_x" instructions. Additional aliases are "if" for "ifxx", "if_icmp"
|
|
||||||
* for "if_icmpxx", "if_acmp" for "if_acmpxx".
|
|
||||||
*
|
|
||||||
* Consecutive instruction names must be separated by white space which will
|
|
||||||
* be removed during the compilation of the pattern.
|
|
||||||
*
|
|
||||||
* For the rest the usual pattern matching rules for regular expressions
|
|
||||||
* apply.
|
|
||||||
* <P>
|
|
||||||
* Example pattern:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* search("BranchInstruction NOP ((IfInstruction|GOTO)+ ISTORE Instruction)*");
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If you alter the instruction list upon a match such that other matching
|
|
||||||
* areas are affected, you should call reread() to update the finder and call
|
|
||||||
* search() again, because the matches are cached.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* the instruction pattern to search for, where case is ignored
|
|
||||||
* @param from
|
|
||||||
* where to start the search in the instruction list
|
|
||||||
* @param constraint
|
|
||||||
* optional CodeConstraint to check the found code pattern for
|
|
||||||
* user-defined constraints
|
|
||||||
* @return iterator of matches where e.nextElement() returns an array of
|
|
||||||
* instruction handles describing the matched area
|
|
||||||
*/
|
|
||||||
public final Iterator search( String pattern, InstructionHandle from, CodeConstraint constraint ) {
|
|
||||||
String search = compilePattern(pattern);
|
|
||||||
int start = -1;
|
|
||||||
for (int i = 0; i < handles.length; i++) {
|
|
||||||
if (handles[i] == from) {
|
|
||||||
start = i; // Where to start search from (index)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (start == -1) {
|
|
||||||
throw new ClassGenException("Instruction handle " + from
|
|
||||||
+ " not found in instruction list.");
|
|
||||||
}
|
|
||||||
Pattern regex = Pattern.compile(search);
|
|
||||||
List matches = new ArrayList();
|
|
||||||
Matcher matcher = regex.matcher(il_string);
|
|
||||||
while (start < il_string.length() && matcher.find(start)) {
|
|
||||||
int startExpr = matcher.start();
|
|
||||||
int endExpr = matcher.end();
|
|
||||||
int lenExpr = (endExpr - startExpr) + 1;
|
|
||||||
InstructionHandle[] match = getMatch(startExpr, lenExpr);
|
|
||||||
if ((constraint == null) || constraint.checkCode(match)) {
|
|
||||||
matches.add(match);
|
|
||||||
}
|
|
||||||
start = endExpr;
|
|
||||||
}
|
|
||||||
return matches.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start search beginning from the start of the given instruction list.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* the instruction pattern to search for, where case is ignored
|
|
||||||
* @return iterator of matches where e.nextElement() returns an array of
|
|
||||||
* instruction handles describing the matched area
|
|
||||||
*/
|
|
||||||
public final Iterator search( String pattern ) {
|
|
||||||
return search(pattern, il.getStart(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start search beginning from `from'.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* the instruction pattern to search for, where case is ignored
|
|
||||||
* @param from
|
|
||||||
* where to start the search in the instruction list
|
|
||||||
* @return iterator of matches where e.nextElement() returns an array of
|
|
||||||
* instruction handles describing the matched area
|
|
||||||
*/
|
|
||||||
public final Iterator search( String pattern, InstructionHandle from ) {
|
|
||||||
return search(pattern, from, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start search beginning from the start of the given instruction list. Check
|
|
||||||
* found matches with the constraint object.
|
|
||||||
*
|
|
||||||
* @param pattern
|
|
||||||
* the instruction pattern to search for, case is ignored
|
|
||||||
* @param constraint
|
|
||||||
* constraints to be checked on matching code
|
|
||||||
* @return instruction handle or `null' if the match failed
|
|
||||||
*/
|
|
||||||
public final Iterator search( String pattern, CodeConstraint constraint ) {
|
|
||||||
return search(pattern, il.getStart(), constraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert opcode number to char.
|
|
||||||
*/
|
|
||||||
private static final char makeChar( short opcode ) {
|
|
||||||
return (char) (opcode + OFFSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the inquired instruction list
|
|
||||||
*/
|
|
||||||
public final InstructionList getInstructionList() {
|
|
||||||
return il;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Code patterns found may be checked using an additional user-defined
|
|
||||||
* constraint object whether they really match the needed criterion. I.e.,
|
|
||||||
* check constraints that can not expressed with regular expressions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static interface CodeConstraint {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param match
|
|
||||||
* array of instructions matching the requested pattern
|
|
||||||
* @return true if the matched area is really useful
|
|
||||||
*/
|
|
||||||
public boolean checkCode( InstructionHandle[] match );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize pattern map
|
|
||||||
static {
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"arithmeticinstruction",
|
|
||||||
"(irem|lrem|iand|ior|ineg|isub|lneg|fneg|fmul|ldiv|fadd|lxor|frem|idiv|land|ixor|ishr|fsub|lshl|fdiv|iadd|lor|dmul|lsub|ishl|imul|lmul|lushr|dneg|iushr|lshr|ddiv|drem|dadd|ladd|dsub)");
|
|
||||||
map.put("invokeinstruction", "(invokevirtual|invokeinterface|invokestatic|invokespecial)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"arrayinstruction",
|
|
||||||
"(baload|aastore|saload|caload|fastore|lastore|iaload|castore|iastore|aaload|bastore|sastore|faload|laload|daload|dastore)");
|
|
||||||
map.put("gotoinstruction", "(goto|goto_w)");
|
|
||||||
map.put("conversioninstruction",
|
|
||||||
"(d2l|l2d|i2s|d2i|l2i|i2b|l2f|d2f|f2i|i2d|i2l|f2d|i2c|f2l|i2f)");
|
|
||||||
map.put("localvariableinstruction",
|
|
||||||
"(fstore|iinc|lload|dstore|dload|iload|aload|astore|istore|fload|lstore)");
|
|
||||||
map.put("loadinstruction", "(fload|dload|lload|iload|aload)");
|
|
||||||
map.put("fieldinstruction", "(getfield|putstatic|getstatic|putfield)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"cpinstruction",
|
|
||||||
"(ldc2_w|invokeinterface|multianewarray|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|ldc_w|invokestatic|invokevirtual|putfield|ldc|new|anewarray)");
|
|
||||||
map.put("stackinstruction", "(dup2|swap|dup2_x2|pop|pop2|dup|dup2_x1|dup_x2|dup_x1)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"branchinstruction",
|
|
||||||
"(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
|
|
||||||
map.put("returninstruction", "(lreturn|ireturn|freturn|dreturn|areturn|return)");
|
|
||||||
map.put("storeinstruction", "(istore|fstore|dstore|astore|lstore)");
|
|
||||||
map.put("select", "(tableswitch|lookupswitch)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"ifinstruction",
|
|
||||||
"(ifeq|ifgt|if_icmpne|if_icmpeq|ifge|ifnull|ifne|if_icmple|if_icmpge|if_acmpeq|if_icmplt|if_acmpne|ifnonnull|iflt|if_icmpgt|ifle)");
|
|
||||||
map.put("jsrinstruction", "(jsr|jsr_w)");
|
|
||||||
map.put("variablelengthinstruction", "(tableswitch|jsr|goto|lookupswitch)");
|
|
||||||
map.put("unconditionalbranch", "(goto|jsr|jsr_w|athrow|goto_w)");
|
|
||||||
map.put("constantpushinstruction", "(dconst|bipush|sipush|fconst|iconst|lconst)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"typedinstruction",
|
|
||||||
"(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dastore|ret|f2d|f2i|drem|iinc|i2c|checkcast|frem|lreturn|astore|lushr|daload|dneg|fastore|istore|lshl|ldiv|lstore|areturn|ishr|ldc_w|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|faload|sipush|iushr|caload|instanceof|invokespecial|putfield|fmul|ireturn|laload|d2f|lneg|ixor|i2l|fdiv|lastore|multianewarray|i2b|getstatic|i2d|putstatic|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|freturn|ldc|aconst_null|castore|lmul|ldc2_w|dadd|iconst|f2l|ddiv|dstore|land|jsr|anewarray|dmul|bipush|dsub|sastore|d2i|i2s|lshr|iadd|l2i|lload|bastore|fstore|fneg|iload|fadd|baload|fconst|ior|ineg|dreturn|l2f|lconst|getfield|invokevirtual|invokestatic|iastore)");
|
|
||||||
map.put("popinstruction", "(fstore|dstore|pop|pop2|astore|putstatic|istore|lstore)");
|
|
||||||
map.put("allocationinstruction", "(multianewarray|new|anewarray|newarray)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"indexedinstruction",
|
|
||||||
"(lload|lstore|fload|ldc2_w|invokeinterface|multianewarray|astore|dload|putstatic|instanceof|getstatic|checkcast|getfield|invokespecial|dstore|istore|iinc|ldc_w|ret|fstore|invokestatic|iload|putfield|invokevirtual|ldc|new|aload|anewarray)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"pushinstruction",
|
|
||||||
"(dup|lload|dup2|bipush|fload|ldc2_w|sipush|lconst|fconst|dload|getstatic|ldc_w|aconst_null|dconst|iload|ldc|iconst|aload)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"stackproducer",
|
|
||||||
"(imul|lsub|aload|fload|lor|new|aaload|fcmpg|iand|iaload|lrem|idiv|d2l|isub|dcmpg|dup|f2d|f2i|drem|i2c|checkcast|frem|lushr|daload|dneg|lshl|ldiv|ishr|ldc_w|invokeinterface|lxor|ishl|l2d|i2f|faload|sipush|iushr|caload|instanceof|invokespecial|fmul|laload|d2f|lneg|ixor|i2l|fdiv|getstatic|i2b|swap|i2d|dup2|fcmpl|saload|ladd|irem|dload|jsr_w|dconst|dcmpl|fsub|ldc|arraylength|aconst_null|tableswitch|lmul|ldc2_w|iconst|dadd|f2l|ddiv|land|jsr|anewarray|dmul|bipush|dsub|d2i|newarray|i2s|lshr|iadd|lload|l2i|fneg|iload|fadd|baload|fconst|lookupswitch|ior|ineg|lconst|l2f|getfield|invokevirtual|invokestatic)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"stackconsumer",
|
|
||||||
"(imul|lsub|lor|iflt|fcmpg|if_icmpgt|iand|ifeq|if_icmplt|lrem|ifnonnull|idiv|d2l|isub|dcmpg|dastore|if_icmpeq|f2d|f2i|drem|i2c|checkcast|frem|lreturn|astore|lushr|pop2|monitorexit|dneg|fastore|istore|lshl|ldiv|lstore|areturn|if_icmpge|ishr|monitorenter|invokeinterface|aastore|lxor|ishl|l2d|i2f|return|iushr|instanceof|invokespecial|fmul|ireturn|d2f|lneg|ixor|pop|i2l|ifnull|fdiv|lastore|i2b|if_acmpeq|ifge|swap|i2d|putstatic|fcmpl|ladd|irem|dcmpl|fsub|freturn|ifgt|castore|lmul|dadd|f2l|ddiv|dstore|land|if_icmpne|if_acmpne|dmul|dsub|sastore|ifle|d2i|i2s|lshr|iadd|l2i|bastore|fstore|fneg|fadd|ior|ineg|ifne|dreturn|l2f|if_icmple|getfield|invokevirtual|invokestatic|iastore)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"exceptionthrower",
|
|
||||||
"(irem|lrem|laload|putstatic|baload|dastore|areturn|getstatic|ldiv|anewarray|iastore|castore|idiv|saload|lastore|fastore|putfield|lreturn|caload|getfield|return|aastore|freturn|newarray|instanceof|multianewarray|athrow|faload|iaload|aaload|dreturn|monitorenter|checkcast|bastore|arraylength|new|invokevirtual|sastore|ldc_w|ireturn|invokespecial|monitorexit|invokeinterface|ldc|invokestatic|daload)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"loadclass",
|
|
||||||
"(multianewarray|invokeinterface|instanceof|invokespecial|putfield|checkcast|putstatic|invokevirtual|new|getstatic|invokestatic|getfield|anewarray)");
|
|
||||||
map
|
|
||||||
.put(
|
|
||||||
"instructiontargeter",
|
|
||||||
"(ifle|if_acmpne|if_icmpeq|if_acmpeq|ifnonnull|goto_w|iflt|ifnull|if_icmpne|tableswitch|if_icmple|ifeq|if_icmplt|jsr_w|if_icmpgt|ifgt|jsr|goto|ifne|ifge|lookupswitch|if_icmpge)");
|
|
||||||
// Some aliases
|
|
||||||
map.put("if_icmp", "(if_icmpne|if_icmpeq|if_icmple|if_icmpge|if_icmplt|if_icmpgt)");
|
|
||||||
map.put("if_acmp", "(if_acmpeq|if_acmpne)");
|
|
||||||
map.put("if", "(ifeq|ifne|iflt|ifge|ifgt|ifle)");
|
|
||||||
// Precompile some aliases first
|
|
||||||
map.put("iconst", precompile(Constants.ICONST_0, Constants.ICONST_5, Constants.ICONST_M1));
|
|
||||||
map.put("lconst", new String(new char[] {
|
|
||||||
'(', makeChar(Constants.LCONST_0), '|', makeChar(Constants.LCONST_1), ')'
|
|
||||||
}));
|
|
||||||
map.put("dconst", new String(new char[] {
|
|
||||||
'(', makeChar(Constants.DCONST_0), '|', makeChar(Constants.DCONST_1), ')'
|
|
||||||
}));
|
|
||||||
map.put("fconst", new String(new char[] {
|
|
||||||
'(', makeChar(Constants.FCONST_0), '|', makeChar(Constants.FCONST_1), ')'
|
|
||||||
}));
|
|
||||||
map.put("iload", precompile(Constants.ILOAD_0, Constants.ILOAD_3, Constants.ILOAD));
|
|
||||||
map.put("dload", precompile(Constants.DLOAD_0, Constants.DLOAD_3, Constants.DLOAD));
|
|
||||||
map.put("fload", precompile(Constants.FLOAD_0, Constants.FLOAD_3, Constants.FLOAD));
|
|
||||||
map.put("aload", precompile(Constants.ALOAD_0, Constants.ALOAD_3, Constants.ALOAD));
|
|
||||||
map.put("istore", precompile(Constants.ISTORE_0, Constants.ISTORE_3, Constants.ISTORE));
|
|
||||||
map.put("dstore", precompile(Constants.DSTORE_0, Constants.DSTORE_3, Constants.DSTORE));
|
|
||||||
map.put("fstore", precompile(Constants.FSTORE_0, Constants.FSTORE_3, Constants.FSTORE));
|
|
||||||
map.put("astore", precompile(Constants.ASTORE_0, Constants.ASTORE_3, Constants.ASTORE));
|
|
||||||
// Compile strings
|
|
||||||
for (Iterator i = map.keySet().iterator(); i.hasNext();) {
|
|
||||||
String key = (String) i.next();
|
|
||||||
String value = (String) map.get(key);
|
|
||||||
char ch = value.charAt(1); // Omit already precompiled patterns
|
|
||||||
if (ch < OFFSET) {
|
|
||||||
map.put(key, compilePattern(value)); // precompile all patterns
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add instruction alias to match anything
|
|
||||||
StringBuffer buf = new StringBuffer("(");
|
|
||||||
for (short i = 0; i < NO_OPCODES; i++) {
|
|
||||||
if (Constants.NO_OF_OPERANDS[i] != Constants.UNDEFINED) { // Not an
|
|
||||||
// invalid
|
|
||||||
// opcode
|
|
||||||
buf.append(makeChar(i));
|
|
||||||
if (i < NO_OPCODES - 1) {
|
|
||||||
buf.append('|');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.append(')');
|
|
||||||
map.put("instruction", buf.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static String precompile( short from, short to, short extra ) {
|
|
||||||
StringBuffer buf = new StringBuffer("(");
|
|
||||||
for (short i = from; i <= to; i++) {
|
|
||||||
buf.append(makeChar(i));
|
|
||||||
buf.append('|');
|
|
||||||
}
|
|
||||||
buf.append(makeChar(extra));
|
|
||||||
buf.append(")");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Internal debugging routines.
|
|
||||||
*/
|
|
||||||
private static final String pattern2string( String pattern ) {
|
|
||||||
return pattern2string(pattern, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static final String pattern2string( String pattern, boolean make_string ) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
for (int i = 0; i < pattern.length(); i++) {
|
|
||||||
char ch = pattern.charAt(i);
|
|
||||||
if (ch >= OFFSET) {
|
|
||||||
if (make_string) {
|
|
||||||
buf.append(Constants.OPCODE_NAMES[ch - OFFSET]);
|
|
||||||
} else {
|
|
||||||
buf.append((ch - OFFSET));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf.append(ch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Java interpreter replacement, i.e., wrapper that uses its own ClassLoader
|
|
||||||
* to modify/generate classes as they're requested. You can take this as a template
|
|
||||||
* for your own applications.<br>
|
|
||||||
* Call this wrapper with
|
|
||||||
* <pre>java org.apache.bcel.util.JavaWrapper <real.class.name> [arguments]</pre>
|
|
||||||
* <p>
|
|
||||||
* To use your own class loader you can set the "bcel.classloader" system property
|
|
||||||
* which defaults to "org.apache.bcel.util.ClassLoader", e.g., with
|
|
||||||
* <pre>java org.apache.bcel.util.JavaWrapper -Dbcel.classloader=foo.MyLoader <real.class.name> [arguments]</pre>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @version $Id: JavaWrapper.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
* @see ClassLoader
|
|
||||||
*/
|
|
||||||
public class JavaWrapper {
|
|
||||||
|
|
||||||
private java.lang.ClassLoader loader;
|
|
||||||
|
|
||||||
|
|
||||||
private static java.lang.ClassLoader getClassLoader() {
|
|
||||||
String s = System.getProperty("bcel.classloader");
|
|
||||||
if ((s == null) || "".equals(s)) {
|
|
||||||
s = "org.apache.bcel.util.ClassLoader";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (java.lang.ClassLoader) Class.forName(s).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaWrapper(java.lang.ClassLoader loader) {
|
|
||||||
this.loader = loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public JavaWrapper() {
|
|
||||||
this(getClassLoader());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Runs the main method of the given class with the arguments passed in argv
|
|
||||||
*
|
|
||||||
* @param class_name the fully qualified class name
|
|
||||||
* @param argv the arguments just as you would pass them directly
|
|
||||||
*/
|
|
||||||
public void runMain( String class_name, String[] argv ) throws ClassNotFoundException {
|
|
||||||
Class cl = loader.loadClass(class_name);
|
|
||||||
Method method = null;
|
|
||||||
try {
|
|
||||||
method = cl.getMethod("main", new Class[] {
|
|
||||||
argv.getClass()
|
|
||||||
});
|
|
||||||
/* Method main is sane ?
|
|
||||||
*/
|
|
||||||
int m = method.getModifiers();
|
|
||||||
Class r = method.getReturnType();
|
|
||||||
if (!(Modifier.isPublic(m) && Modifier.isStatic(m)) || Modifier.isAbstract(m)
|
|
||||||
|| (r != Void.TYPE)) {
|
|
||||||
throw new NoSuchMethodException();
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException no) {
|
|
||||||
System.out.println("In class " + class_name
|
|
||||||
+ ": public static void main(String[] argv) is not defined");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
method.invoke(null, new Object[] {
|
|
||||||
argv
|
|
||||||
});
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Default main method used as wrapper, expects the fully qualified class name
|
|
||||||
* of the real class as the first argument.
|
|
||||||
*/
|
|
||||||
public static void main( String[] argv ) throws Exception {
|
|
||||||
/* Expects class name as first argument, other arguments are by-passed.
|
|
||||||
*/
|
|
||||||
if (argv.length == 0) {
|
|
||||||
System.out.println("Missing class name.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String class_name = argv[0];
|
|
||||||
String[] new_argv = new String[argv.length - 1];
|
|
||||||
System.arraycopy(argv, 1, new_argv, 0, new_argv.length);
|
|
||||||
JavaWrapper wrapper = new JavaWrapper();
|
|
||||||
wrapper.runMain(class_name, new_argv);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,156 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.util;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import org.apache.bcel.classfile.Attribute;
|
|
||||||
import org.apache.bcel.classfile.Code;
|
|
||||||
import org.apache.bcel.classfile.ConstantValue;
|
|
||||||
import org.apache.bcel.classfile.ExceptionTable;
|
|
||||||
import org.apache.bcel.classfile.Field;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.classfile.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert methods and fields into HTML file.
|
|
||||||
*
|
|
||||||
* @version $Id: MethodHTML.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
final class MethodHTML implements org.apache.bcel.Constants {
|
|
||||||
|
|
||||||
private String class_name; // name of current class
|
|
||||||
private PrintWriter file; // file to write to
|
|
||||||
private ConstantHTML constant_html;
|
|
||||||
private AttributeHTML attribute_html;
|
|
||||||
|
|
||||||
|
|
||||||
MethodHTML(String dir, String class_name, Method[] methods, Field[] fields,
|
|
||||||
ConstantHTML constant_html, AttributeHTML attribute_html) throws IOException {
|
|
||||||
this.class_name = class_name;
|
|
||||||
this.attribute_html = attribute_html;
|
|
||||||
this.constant_html = constant_html;
|
|
||||||
file = new PrintWriter(new FileOutputStream(dir + class_name + "_methods.html"));
|
|
||||||
file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\"><TABLE BORDER=0>");
|
|
||||||
file.println("<TR><TH ALIGN=LEFT>Access flags</TH><TH ALIGN=LEFT>Type</TH>"
|
|
||||||
+ "<TH ALIGN=LEFT>Field name</TH></TR>");
|
|
||||||
for (int i = 0; i < fields.length; i++) {
|
|
||||||
writeField(fields[i]);
|
|
||||||
}
|
|
||||||
file.println("</TABLE>");
|
|
||||||
file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Access flags</TH>"
|
|
||||||
+ "<TH ALIGN=LEFT>Return type</TH><TH ALIGN=LEFT>Method name</TH>"
|
|
||||||
+ "<TH ALIGN=LEFT>Arguments</TH></TR>");
|
|
||||||
for (int i = 0; i < methods.length; i++) {
|
|
||||||
writeMethod(methods[i], i);
|
|
||||||
}
|
|
||||||
file.println("</TABLE></BODY></HTML>");
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print field of class.
|
|
||||||
*
|
|
||||||
* @param field field to print
|
|
||||||
* @exception java.io.IOException
|
|
||||||
*/
|
|
||||||
private void writeField( Field field ) throws IOException {
|
|
||||||
String type = Utility.signatureToString(field.getSignature());
|
|
||||||
String name = field.getName();
|
|
||||||
String access = Utility.accessToString(field.getAccessFlags());
|
|
||||||
Attribute[] attributes;
|
|
||||||
access = Utility.replace(access, " ", " ");
|
|
||||||
file.print("<TR><TD><FONT COLOR=\"#FF0000\">" + access + "</FONT></TD>\n<TD>"
|
|
||||||
+ Class2HTML.referenceType(type) + "</TD><TD><A NAME=\"field" + name + "\">" + name
|
|
||||||
+ "</A></TD>");
|
|
||||||
attributes = field.getAttributes();
|
|
||||||
// Write them to the Attributes.html file with anchor "<name>[<i>]"
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
attribute_html.writeAttribute(attributes[i], name + "@" + i);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
if (attributes[i].getTag() == ATTR_CONSTANT_VALUE) { // Default value
|
|
||||||
String str = ((ConstantValue) attributes[i]).toString();
|
|
||||||
// Reference attribute in _attributes.html
|
|
||||||
file.print("<TD>= <A HREF=\"" + class_name + "_attributes.html#" + name + "@" + i
|
|
||||||
+ "\" TARGET=\"Attributes\">" + str + "</TD>\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.println("</TR>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private final void writeMethod( Method method, int method_number ) throws IOException {
|
|
||||||
// Get raw signature
|
|
||||||
String signature = method.getSignature();
|
|
||||||
// Get array of strings containing the argument types
|
|
||||||
String[] args = Utility.methodSignatureArgumentTypes(signature, false);
|
|
||||||
// Get return type string
|
|
||||||
String type = Utility.methodSignatureReturnType(signature, false);
|
|
||||||
// Get method name
|
|
||||||
String name = method.getName(), html_name;
|
|
||||||
// Get method's access flags
|
|
||||||
String access = Utility.accessToString(method.getAccessFlags());
|
|
||||||
// Get the method's attributes, the Code Attribute in particular
|
|
||||||
Attribute[] attributes = method.getAttributes();
|
|
||||||
/* HTML doesn't like names like <clinit> and spaces are places to break
|
|
||||||
* lines. Both we don't want...
|
|
||||||
*/
|
|
||||||
access = Utility.replace(access, " ", " ");
|
|
||||||
html_name = Class2HTML.toHTML(name);
|
|
||||||
file.print("<TR VALIGN=TOP><TD><FONT COLOR=\"#FF0000\"><A NAME=method" + method_number
|
|
||||||
+ ">" + access + "</A></FONT></TD>");
|
|
||||||
file.print("<TD>" + Class2HTML.referenceType(type) + "</TD><TD>" + "<A HREF=" + class_name
|
|
||||||
+ "_code.html#method" + method_number + " TARGET=Code>" + html_name
|
|
||||||
+ "</A></TD>\n<TD>(");
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
file.print(Class2HTML.referenceType(args[i]));
|
|
||||||
if (i < args.length - 1) {
|
|
||||||
file.print(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.print(")</TD></TR>");
|
|
||||||
// Check for thrown exceptions
|
|
||||||
for (int i = 0; i < attributes.length; i++) {
|
|
||||||
attribute_html.writeAttribute(attributes[i], "method" + method_number + "@" + i,
|
|
||||||
method_number);
|
|
||||||
byte tag = attributes[i].getTag();
|
|
||||||
if (tag == ATTR_EXCEPTIONS) {
|
|
||||||
file.print("<TR VALIGN=TOP><TD COLSPAN=2></TD><TH ALIGN=LEFT>throws</TH><TD>");
|
|
||||||
int[] exceptions = ((ExceptionTable) attributes[i]).getExceptionIndexTable();
|
|
||||||
for (int j = 0; j < exceptions.length; j++) {
|
|
||||||
file.print(constant_html.referenceConstant(exceptions[j]));
|
|
||||||
if (j < exceptions.length - 1) {
|
|
||||||
file.print(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.println("</TD></TR>");
|
|
||||||
} else if (tag == ATTR_CODE) {
|
|
||||||
Attribute[] c_a = ((Code) attributes[i]).getAttributes();
|
|
||||||
for (int j = 0; j < c_a.length; j++) {
|
|
||||||
attribute_html.writeAttribute(c_a[j], "method" + method_number + "@" + i + "@"
|
|
||||||
+ j, method_number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -59,7 +59,7 @@ public interface Repository extends java.io.Serializable {
|
|||||||
/**
|
/**
|
||||||
* Find the JavaClass instance for the given run-time class object
|
* Find the JavaClass instance for the given run-time class object
|
||||||
*/
|
*/
|
||||||
public JavaClass loadClass( Class clazz ) throws java.lang.ClassNotFoundException;
|
public JavaClass loadClass( Class<?> clazz ) throws java.lang.ClassNotFoundException;
|
||||||
|
|
||||||
|
|
||||||
/** Clear all entries from cache.
|
/** Clear all entries from cache.
|
||||||
|
@ -21,6 +21,7 @@ import java.io.InputStream;
|
|||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.bcel.classfile.ClassParser;
|
import org.apache.bcel.classfile.ClassParser;
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
import org.apache.bcel.classfile.JavaClass;
|
||||||
|
|
||||||
@ -47,10 +48,13 @@ import org.apache.bcel.classfile.JavaClass;
|
|||||||
*/
|
*/
|
||||||
public class SyntheticRepository implements Repository {
|
public class SyntheticRepository implements Repository {
|
||||||
|
|
||||||
private static final String DEFAULT_PATH = ClassPath.getClassPath();
|
/**
|
||||||
private static Map _instances = new HashMap(); // CLASSPATH X REPOSITORY
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static Map<ClassPath, SyntheticRepository> _instances = new HashMap<ClassPath, SyntheticRepository>(); // CLASSPATH X REPOSITORY
|
||||||
private ClassPath _path = null;
|
private ClassPath _path = null;
|
||||||
private Map _loadedClasses = new HashMap(); // CLASSNAME X JAVACLASS
|
private Map<String, SoftReference<JavaClass>> _loadedClasses = new HashMap<String, SoftReference<JavaClass>>(); // CLASSNAME X JAVACLASS
|
||||||
|
|
||||||
|
|
||||||
private SyntheticRepository(ClassPath path) {
|
private SyntheticRepository(ClassPath path) {
|
||||||
@ -77,7 +81,7 @@ public class SyntheticRepository implements Repository {
|
|||||||
* Store a new JavaClass instance into this Repository.
|
* Store a new JavaClass instance into this Repository.
|
||||||
*/
|
*/
|
||||||
public void storeClass( JavaClass clazz ) {
|
public void storeClass( JavaClass clazz ) {
|
||||||
_loadedClasses.put(clazz.getClassName(), new SoftReference(clazz));
|
_loadedClasses.put(clazz.getClassName(), new SoftReference<JavaClass>(clazz));
|
||||||
clazz.setRepository(this);
|
clazz.setRepository(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ public class SyntheticRepository implements Repository {
|
|||||||
* Find an already defined (cached) JavaClass object by name.
|
* Find an already defined (cached) JavaClass object by name.
|
||||||
*/
|
*/
|
||||||
public JavaClass findClass( String className ) {
|
public JavaClass findClass( String className ) {
|
||||||
SoftReference ref = (SoftReference) _loadedClasses.get(className);
|
SoftReference<?> ref = (SoftReference<?>) _loadedClasses.get(className);
|
||||||
if (ref == null) {
|
if (ref == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -144,7 +148,7 @@ public class SyntheticRepository implements Repository {
|
|||||||
* @throws ClassNotFoundException if the class is not in the
|
* @throws ClassNotFoundException if the class is not in the
|
||||||
* Repository, and its representation could not be found
|
* Repository, and its representation could not be found
|
||||||
*/
|
*/
|
||||||
public JavaClass loadClass( Class clazz ) throws ClassNotFoundException {
|
public JavaClass loadClass( Class<?> clazz ) throws ClassNotFoundException {
|
||||||
String className = clazz.getName();
|
String className = clazz.getName();
|
||||||
JavaClass repositoryClass = findClass(className);
|
JavaClass repositoryClass = findClass(className);
|
||||||
if (repositoryClass != null) {
|
if (repositoryClass != null) {
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Toolkit;
|
|
||||||
import javax.swing.UIManager;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A graphical user interface application demonstrating JustIce.
|
|
||||||
*
|
|
||||||
* @version $Id: GraphicalVerifier.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class GraphicalVerifier {
|
|
||||||
|
|
||||||
boolean packFrame = false;
|
|
||||||
|
|
||||||
|
|
||||||
/** Constructor. */
|
|
||||||
public GraphicalVerifier() {
|
|
||||||
VerifierAppFrame frame = new VerifierAppFrame();
|
|
||||||
if (packFrame) {
|
|
||||||
frame.pack();
|
|
||||||
} else {
|
|
||||||
frame.validate();
|
|
||||||
}
|
|
||||||
//Das Fenster zentrieren
|
|
||||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
|
||||||
Dimension frameSize = frame.getSize();
|
|
||||||
if (frameSize.height > screenSize.height) {
|
|
||||||
frameSize.height = screenSize.height;
|
|
||||||
}
|
|
||||||
if (frameSize.width > screenSize.width) {
|
|
||||||
frameSize.width = screenSize.width;
|
|
||||||
}
|
|
||||||
frame.setLocation((screenSize.width - frameSize.width) / 2,
|
|
||||||
(screenSize.height - frameSize.height) / 2);
|
|
||||||
frame.setVisible(true);
|
|
||||||
frame.classNamesJList.setModel(new VerifierFactoryListModel());
|
|
||||||
VerifierFactory.getVerifier(Type.OBJECT.getClassName()); // Fill list with java.lang.Object
|
|
||||||
frame.classNamesJList.setSelectedIndex(0); // default, will verify java.lang.Object
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Main method. */
|
|
||||||
public static void main( String[] args ) {
|
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
new GraphicalVerifier();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The NativeVerifier class implements a main(String[] args) method that's
|
|
||||||
* roughly compatible to the one in the Verifier class, but that uses the
|
|
||||||
* JVM's internal verifier for its class file verification.
|
|
||||||
* This can be used for comparison runs between the JVM-internal verifier
|
|
||||||
* and JustIce.
|
|
||||||
*
|
|
||||||
* @version $Id: NativeVerifier.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public abstract class NativeVerifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class must not be instantiated.
|
|
||||||
*/
|
|
||||||
private NativeVerifier() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Works only on the first argument.
|
|
||||||
*/
|
|
||||||
public static void main( String[] args ) {
|
|
||||||
if (args.length != 1) {
|
|
||||||
System.out.println("Verifier front-end: need exactly one argument.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
int dotclasspos = args[0].lastIndexOf(".class");
|
|
||||||
if (dotclasspos != -1) {
|
|
||||||
args[0] = args[0].substring(0, dotclasspos);
|
|
||||||
}
|
|
||||||
args[0] = args[0].replace('/', '.');
|
|
||||||
//System.out.println(args[0]);
|
|
||||||
try {
|
|
||||||
Class.forName(args[0]);
|
|
||||||
} catch (ExceptionInInitializerError eiie) { //subclass of LinkageError!
|
|
||||||
System.out.println("NativeVerifier: ExceptionInInitializerError encountered on '"
|
|
||||||
+ args[0] + "'.");
|
|
||||||
System.out.println(eiie);
|
|
||||||
System.exit(1);
|
|
||||||
} catch (LinkageError le) {
|
|
||||||
System.out.println("NativeVerifier: LinkageError encountered on '" + args[0] + "'.");
|
|
||||||
System.out.println(le);
|
|
||||||
System.exit(1);
|
|
||||||
} catch (ClassNotFoundException cnfe) {
|
|
||||||
System.out.println("NativeVerifier: FILE NOT FOUND: '" + args[0] + "'.");
|
|
||||||
System.exit(1);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
System.out.println("NativeVerifier: Unspecified verification error on'" + args[0]
|
|
||||||
+ "'.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
System.out.println("NativeVerifier: Class file '" + args[0] + "' seems to be okay.");
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A PassVerifier actually verifies a class file; it is instantiated
|
|
||||||
* by a Verifier.
|
|
||||||
* The verification should conform with a certain pass as described
|
|
||||||
* in The Java Virtual Machine Specification, 2nd edition.
|
|
||||||
* This book describes four passes. Pass one means loading the
|
|
||||||
* class and verifying a few static constraints. Pass two actually
|
|
||||||
* verifies some other constraints that could enforce loading in
|
|
||||||
* referenced class files. Pass three is the first pass that actually
|
|
||||||
* checks constraints in the code array of a method in the class file;
|
|
||||||
* it has two parts with the first verifying static constraints and
|
|
||||||
* the second part verifying structural constraints (where a data flow
|
|
||||||
* analysis is used for). The fourth pass, finally, performs checks
|
|
||||||
* that can only be done at run-time.
|
|
||||||
* JustIce does not have a run-time pass, but certain constraints that
|
|
||||||
* are usually delayed until run-time for performance reasons are also
|
|
||||||
* checked during the second part of pass three.
|
|
||||||
* PassVerifier instances perform caching.
|
|
||||||
* That means, if you really want a new verification run of a certain
|
|
||||||
* pass you must use a new instance of a given PassVerifier.
|
|
||||||
*
|
|
||||||
* @version $Id: PassVerifier.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see org.apache.bcel.verifier.Verifier
|
|
||||||
* @see #verify()
|
|
||||||
*/
|
|
||||||
public abstract class PassVerifier {
|
|
||||||
|
|
||||||
/** The (warning) messages. */
|
|
||||||
private List messages = new ArrayList(); //Type of elements: String
|
|
||||||
/** The VerificationResult cache. */
|
|
||||||
private VerificationResult verificationResult = null;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method runs a verification pass conforming to the
|
|
||||||
* Java Virtual Machine Specification, 2nd edition, on a
|
|
||||||
* class file.
|
|
||||||
* PassVerifier instances perform caching;
|
|
||||||
* i.e. if the verify() method once determined a VerificationResult,
|
|
||||||
* then this result may be returned after every invocation of this
|
|
||||||
* method instead of running the verification pass anew; likewise with
|
|
||||||
* the result of getMessages().
|
|
||||||
*
|
|
||||||
* @see #getMessages()
|
|
||||||
* @see #addMessage(String)
|
|
||||||
*/
|
|
||||||
public VerificationResult verify() {
|
|
||||||
if (verificationResult == null) {
|
|
||||||
verificationResult = do_verify();
|
|
||||||
}
|
|
||||||
return verificationResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Does the real verification work, uncached. */
|
|
||||||
public abstract VerificationResult do_verify();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method adds a (warning) message to the message pool of this
|
|
||||||
* PassVerifier. This method is normally only internally used by
|
|
||||||
* BCEL's class file verifier "JustIce" and should not be used from
|
|
||||||
* the outside.
|
|
||||||
*
|
|
||||||
* @see #getMessages()
|
|
||||||
*/
|
|
||||||
public void addMessage( String message ) {
|
|
||||||
messages.add(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the (warning) messages that this PassVerifier accumulated
|
|
||||||
* during its do_verify()ing work.
|
|
||||||
*
|
|
||||||
* @see #addMessage(String)
|
|
||||||
* @see #do_verify()
|
|
||||||
*/
|
|
||||||
public String[] getMessages() {
|
|
||||||
verify(); // create messages if not already done (cached!)
|
|
||||||
return (String[]) messages.toArray(new String[messages.size()]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import org.apache.bcel.Repository;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class has a main method implementing a demonstration program
|
|
||||||
* of how to use the VerifierFactoryObserver. It transitively verifies
|
|
||||||
* all class files encountered; this may take up a lot of time and,
|
|
||||||
* more notably, memory.
|
|
||||||
*
|
|
||||||
* @version $Id: TransitiveHull.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class TransitiveHull implements VerifierFactoryObserver {
|
|
||||||
|
|
||||||
/** Used for indentation. */
|
|
||||||
private int indent = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/** Not publicly instantiable. */
|
|
||||||
private TransitiveHull() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Implementing VerifierFactoryObserver. */
|
|
||||||
public void update( String classname ) {
|
|
||||||
System.gc(); // avoid swapping if possible.
|
|
||||||
for (int i = 0; i < indent; i++) {
|
|
||||||
System.out.print(" ");
|
|
||||||
}
|
|
||||||
System.out.println(classname);
|
|
||||||
indent += 1;
|
|
||||||
Verifier v = VerifierFactory.getVerifier(classname);
|
|
||||||
VerificationResult vr;
|
|
||||||
vr = v.doPass1();
|
|
||||||
if (vr != VerificationResult.VR_OK) {
|
|
||||||
System.out.println("Pass 1:\n" + vr);
|
|
||||||
}
|
|
||||||
vr = v.doPass2();
|
|
||||||
if (vr != VerificationResult.VR_OK) {
|
|
||||||
System.out.println("Pass 2:\n" + vr);
|
|
||||||
}
|
|
||||||
if (vr == VerificationResult.VR_OK) {
|
|
||||||
try {
|
|
||||||
JavaClass jc = Repository.lookupClass(v.getClassName());
|
|
||||||
for (int i = 0; i < jc.getMethods().length; i++) {
|
|
||||||
vr = v.doPass3a(i);
|
|
||||||
if (vr != VerificationResult.VR_OK) {
|
|
||||||
System.out.println(v.getClassName() + ", Pass 3a, method " + i + " ['"
|
|
||||||
+ jc.getMethods()[i] + "']:\n" + vr);
|
|
||||||
}
|
|
||||||
vr = v.doPass3b(i);
|
|
||||||
if (vr != VerificationResult.VR_OK) {
|
|
||||||
System.out.println(v.getClassName() + ", Pass 3b, method " + i + " ['"
|
|
||||||
+ jc.getMethods()[i] + "']:\n" + vr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
System.err.println("Could not find class " + v.getClassName() + " in Repository");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
indent -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method implements a demonstration program
|
|
||||||
* of how to use the VerifierFactoryObserver. It transitively verifies
|
|
||||||
* all class files encountered; this may take up a lot of time and,
|
|
||||||
* more notably, memory.
|
|
||||||
*/
|
|
||||||
public static void main( String[] args ) {
|
|
||||||
if (args.length != 1) {
|
|
||||||
System.out.println("Need exactly one argument: The root class to verify.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
int dotclasspos = args[0].lastIndexOf(".class");
|
|
||||||
if (dotclasspos != -1) {
|
|
||||||
args[0] = args[0].substring(0, dotclasspos);
|
|
||||||
}
|
|
||||||
args[0] = args[0].replace('/', '.');
|
|
||||||
TransitiveHull th = new TransitiveHull();
|
|
||||||
VerifierFactory.attach(th);
|
|
||||||
VerifierFactory.getVerifier(args[0]); // the observer is called back and does the actual trick.
|
|
||||||
VerifierFactory.detach(th);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A VerificationResult is what a PassVerifier returns
|
|
||||||
* after verifying.
|
|
||||||
*
|
|
||||||
* @version $Id: VerificationResult.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class VerificationResult {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant to indicate verification has not been tried yet.
|
|
||||||
* This happens if some earlier verification pass did not return VERIFIED_OK.
|
|
||||||
*/
|
|
||||||
public static final int VERIFIED_NOTYET = 0;
|
|
||||||
/** Constant to indicate verification was passed. */
|
|
||||||
public static final int VERIFIED_OK = 1;
|
|
||||||
/** Constant to indicate verfication failed. */
|
|
||||||
public static final int VERIFIED_REJECTED = 2;
|
|
||||||
/**
|
|
||||||
* This string is the canonical message for verifications that have not been tried yet.
|
|
||||||
* This happens if some earlier verification pass did not return VERIFIED_OK.
|
|
||||||
*/
|
|
||||||
private static final String VERIFIED_NOTYET_MSG = "Not yet verified.";
|
|
||||||
/** This string is the canonical message for passed verification passes. */
|
|
||||||
private static final String VERIFIED_OK_MSG = "Passed verification.";
|
|
||||||
/**
|
|
||||||
* Canonical VerificationResult for not-yet-tried verifications.
|
|
||||||
* This happens if some earlier verification pass did not return VERIFIED_OK.
|
|
||||||
*/
|
|
||||||
public static final VerificationResult VR_NOTYET = new VerificationResult(VERIFIED_NOTYET,
|
|
||||||
VERIFIED_NOTYET_MSG);
|
|
||||||
/** Canonical VerificationResult for passed verifications. */
|
|
||||||
public static final VerificationResult VR_OK = new VerificationResult(VERIFIED_OK,
|
|
||||||
VERIFIED_OK_MSG);
|
|
||||||
/** The numeric status. */
|
|
||||||
private int numeric;
|
|
||||||
/** The detailed message. */
|
|
||||||
private String detailMessage;
|
|
||||||
|
|
||||||
|
|
||||||
/** The usual constructor. */
|
|
||||||
public VerificationResult(int status, String message) {
|
|
||||||
numeric = status;
|
|
||||||
detailMessage = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns one one the VERIFIED_OK, VERIFIED_NOTYET, VERIFIED_REJECTED constants. */
|
|
||||||
public int getStatus() {
|
|
||||||
return numeric;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns a detailed message. */
|
|
||||||
public String getMessage() {
|
|
||||||
return detailMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** @return a hash code value for the object.
|
|
||||||
*/
|
|
||||||
public int hashCode() {
|
|
||||||
return numeric ^ detailMessage.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if two VerificationResult instances are equal.
|
|
||||||
*/
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if (!(o instanceof VerificationResult)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
VerificationResult other = (VerificationResult) o;
|
|
||||||
return ((other.numeric == this.numeric) && (other.detailMessage.equals(this.detailMessage)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of the VerificationResult.
|
|
||||||
*/
|
|
||||||
public String toString() {
|
|
||||||
String ret = "";
|
|
||||||
if (numeric == VERIFIED_NOTYET) {
|
|
||||||
ret = "VERIFIED_NOTYET";
|
|
||||||
}
|
|
||||||
if (numeric == VERIFIED_OK) {
|
|
||||||
ret = "VERIFIED_OK";
|
|
||||||
}
|
|
||||||
if (numeric == VERIFIED_REJECTED) {
|
|
||||||
ret = "VERIFIED_REJECTED";
|
|
||||||
}
|
|
||||||
ret += "\n" + detailMessage + "\n";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,248 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.verifier.statics.Pass1Verifier;
|
|
||||||
import org.apache.bcel.verifier.statics.Pass2Verifier;
|
|
||||||
import org.apache.bcel.verifier.statics.Pass3aVerifier;
|
|
||||||
import org.apache.bcel.verifier.structurals.Pass3bVerifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Verifier instance is there to verify a class file according to The Java Virtual
|
|
||||||
* Machine Specification, 2nd Edition.
|
|
||||||
*
|
|
||||||
* Pass-3b-verification includes pass-3a-verification;
|
|
||||||
* pass-3a-verification includes pass-2-verification;
|
|
||||||
* pass-2-verification includes pass-1-verification.
|
|
||||||
*
|
|
||||||
* A Verifier creates PassVerifier instances to perform the actual verification.
|
|
||||||
* Verifier instances are usually generated by the VerifierFactory.
|
|
||||||
*
|
|
||||||
* @version $Id: Verifier.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see org.apache.bcel.verifier.VerifierFactory
|
|
||||||
* @see org.apache.bcel.verifier.PassVerifier
|
|
||||||
*/
|
|
||||||
public class Verifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the class this verifier operates on.
|
|
||||||
*/
|
|
||||||
private final String classname;
|
|
||||||
/** A Pass1Verifier for this Verifier instance. */
|
|
||||||
private Pass1Verifier p1v;
|
|
||||||
/** A Pass2Verifier for this Verifier instance. */
|
|
||||||
private Pass2Verifier p2v;
|
|
||||||
/** The Pass3aVerifiers for this Verifier instance. Key: Interned string specifying the method number. */
|
|
||||||
private Map p3avs = new HashMap();
|
|
||||||
/** The Pass3bVerifiers for this Verifier instance. Key: Interned string specifying the method number. */
|
|
||||||
private Map p3bvs = new HashMap();
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the VerificationResult for the given pass. */
|
|
||||||
public VerificationResult doPass1() {
|
|
||||||
if (p1v == null) {
|
|
||||||
p1v = new Pass1Verifier(this);
|
|
||||||
}
|
|
||||||
return p1v.verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the VerificationResult for the given pass. */
|
|
||||||
public VerificationResult doPass2() {
|
|
||||||
if (p2v == null) {
|
|
||||||
p2v = new Pass2Verifier(this);
|
|
||||||
}
|
|
||||||
return p2v.verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the VerificationResult for the given pass. */
|
|
||||||
public VerificationResult doPass3a( int method_no ) {
|
|
||||||
String key = Integer.toString(method_no);
|
|
||||||
Pass3aVerifier p3av;
|
|
||||||
p3av = (Pass3aVerifier) (p3avs.get(key));
|
|
||||||
if (p3avs.get(key) == null) {
|
|
||||||
p3av = new Pass3aVerifier(this, method_no);
|
|
||||||
p3avs.put(key, p3av);
|
|
||||||
}
|
|
||||||
return p3av.verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the VerificationResult for the given pass. */
|
|
||||||
public VerificationResult doPass3b( int method_no ) {
|
|
||||||
String key = Integer.toString(method_no);
|
|
||||||
Pass3bVerifier p3bv;
|
|
||||||
p3bv = (Pass3bVerifier) (p3bvs.get(key));
|
|
||||||
if (p3bvs.get(key) == null) {
|
|
||||||
p3bv = new Pass3bVerifier(this, method_no);
|
|
||||||
p3bvs.put(key, p3bv);
|
|
||||||
}
|
|
||||||
return p3bv.verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiation is done by the VerifierFactory.
|
|
||||||
*
|
|
||||||
* @see VerifierFactory
|
|
||||||
*/
|
|
||||||
Verifier(String fully_qualified_classname) {
|
|
||||||
classname = fully_qualified_classname;
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name of the class this verifier operates on.
|
|
||||||
* This is particularly interesting when this verifier was created
|
|
||||||
* recursively by another Verifier and you got a reference to this
|
|
||||||
* Verifier by the getVerifiers() method of the VerifierFactory.
|
|
||||||
* @see VerifierFactory
|
|
||||||
*/
|
|
||||||
public final String getClassName() {
|
|
||||||
return classname;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forget everything known about the class file; that means, really
|
|
||||||
* start a new verification of a possibly different class file from
|
|
||||||
* BCEL's repository.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void flush() {
|
|
||||||
p1v = null;
|
|
||||||
p2v = null;
|
|
||||||
p3avs.clear();
|
|
||||||
p3bvs.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns all the (warning) messages collected during verification.
|
|
||||||
* A prefix shows from which verifying pass a message originates.
|
|
||||||
*/
|
|
||||||
public String[] getMessages() throws ClassNotFoundException {
|
|
||||||
ArrayList messages = new ArrayList();
|
|
||||||
if (p1v != null) {
|
|
||||||
String[] p1m = p1v.getMessages();
|
|
||||||
for (int i = 0; i < p1m.length; i++) {
|
|
||||||
messages.add("Pass 1: " + p1m[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p2v != null) {
|
|
||||||
String[] p2m = p2v.getMessages();
|
|
||||||
for (int i = 0; i < p2m.length; i++) {
|
|
||||||
messages.add("Pass 2: " + p2m[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iterator p3as = p3avs.values().iterator();
|
|
||||||
while (p3as.hasNext()) {
|
|
||||||
Pass3aVerifier pv = (Pass3aVerifier) p3as.next();
|
|
||||||
String[] p3am = pv.getMessages();
|
|
||||||
int meth = pv.getMethodNo();
|
|
||||||
for (int i = 0; i < p3am.length; i++) {
|
|
||||||
messages.add("Pass 3a, method " + meth + " ('"
|
|
||||||
+ org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth]
|
|
||||||
+ "'): " + p3am[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iterator p3bs = p3bvs.values().iterator();
|
|
||||||
while (p3bs.hasNext()) {
|
|
||||||
Pass3bVerifier pv = (Pass3bVerifier) p3bs.next();
|
|
||||||
String[] p3bm = pv.getMessages();
|
|
||||||
int meth = pv.getMethodNo();
|
|
||||||
for (int i = 0; i < p3bm.length; i++) {
|
|
||||||
messages.add("Pass 3b, method " + meth + " ('"
|
|
||||||
+ org.apache.bcel.Repository.lookupClass(classname).getMethods()[meth]
|
|
||||||
+ "'): " + p3bm[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String[] ret = new String[messages.size()];
|
|
||||||
for (int i = 0; i < messages.size(); i++) {
|
|
||||||
ret[i] = (String) messages.get(i);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies class files.
|
|
||||||
* This is a simple demonstration of how the API of BCEL's
|
|
||||||
* class file verifier "JustIce" may be used.
|
|
||||||
* You should supply command-line arguments which are
|
|
||||||
* fully qualified namea of the classes to verify. These class files
|
|
||||||
* must be somewhere in your CLASSPATH (refer to Sun's
|
|
||||||
* documentation for questions about this) or you must have put the classes
|
|
||||||
* into the BCEL Repository yourself (via 'addClass(JavaClass)').
|
|
||||||
*/
|
|
||||||
public static void main( String[] args ) {
|
|
||||||
System.out
|
|
||||||
.println("JustIce by Enver Haase, (C) 2001-2002.\n<http://bcel.sourceforge.net>\n<http://jakarta.apache.org/bcel>\n");
|
|
||||||
for (int k = 0; k < args.length; k++) {
|
|
||||||
try {
|
|
||||||
if (args[k].endsWith(".class")) {
|
|
||||||
int dotclasspos = args[k].lastIndexOf(".class");
|
|
||||||
if (dotclasspos != -1) {
|
|
||||||
args[k] = args[k].substring(0, dotclasspos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
args[k] = args[k].replace('/', '.');
|
|
||||||
System.out.println("Now verifying: " + args[k] + "\n");
|
|
||||||
Verifier v = VerifierFactory.getVerifier(args[k]);
|
|
||||||
VerificationResult vr;
|
|
||||||
vr = v.doPass1();
|
|
||||||
System.out.println("Pass 1:\n" + vr);
|
|
||||||
vr = v.doPass2();
|
|
||||||
System.out.println("Pass 2:\n" + vr);
|
|
||||||
if (vr == VerificationResult.VR_OK) {
|
|
||||||
JavaClass jc = org.apache.bcel.Repository.lookupClass(args[k]);
|
|
||||||
for (int i = 0; i < jc.getMethods().length; i++) {
|
|
||||||
vr = v.doPass3a(i);
|
|
||||||
System.out.println("Pass 3a, method number " + i + " ['"
|
|
||||||
+ jc.getMethods()[i] + "']:\n" + vr);
|
|
||||||
vr = v.doPass3b(i);
|
|
||||||
System.out.println("Pass 3b, method number " + i + " ['"
|
|
||||||
+ jc.getMethods()[i] + "']:\n" + vr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("Warnings:");
|
|
||||||
String[] warnings = v.getMessages();
|
|
||||||
if (warnings.length == 0) {
|
|
||||||
System.out.println("<none>");
|
|
||||||
}
|
|
||||||
for (int j = 0; j < warnings.length; j++) {
|
|
||||||
System.out.println(warnings[j]);
|
|
||||||
}
|
|
||||||
System.out.println("\n");
|
|
||||||
// avoid swapping.
|
|
||||||
v.flush();
|
|
||||||
org.apache.bcel.Repository.clearCache();
|
|
||||||
System.gc();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,396 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.awt.AWTEvent;
|
|
||||||
import java.awt.CardLayout;
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.GridLayout;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.WindowEvent;
|
|
||||||
import javax.swing.BorderFactory;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JList;
|
|
||||||
import javax.swing.JMenu;
|
|
||||||
import javax.swing.JMenuBar;
|
|
||||||
import javax.swing.JMenuItem;
|
|
||||||
import javax.swing.JOptionPane;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JScrollPane;
|
|
||||||
import javax.swing.JSplitPane;
|
|
||||||
import javax.swing.JTextPane;
|
|
||||||
import javax.swing.ListSelectionModel;
|
|
||||||
import javax.swing.event.ListSelectionEvent;
|
|
||||||
import org.apache.bcel.Repository;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements a machine-generated frame for use with
|
|
||||||
* the GraphicalVerfifier.
|
|
||||||
*
|
|
||||||
* @version $Id: VerifierAppFrame.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see GraphicalVerifier
|
|
||||||
*/
|
|
||||||
public class VerifierAppFrame extends JFrame {
|
|
||||||
|
|
||||||
JPanel contentPane;
|
|
||||||
JSplitPane jSplitPane1 = new JSplitPane();
|
|
||||||
JPanel jPanel1 = new JPanel();
|
|
||||||
JPanel jPanel2 = new JPanel();
|
|
||||||
JSplitPane jSplitPane2 = new JSplitPane();
|
|
||||||
JPanel jPanel3 = new JPanel();
|
|
||||||
JList classNamesJList = new JList();
|
|
||||||
GridLayout gridLayout1 = new GridLayout();
|
|
||||||
JPanel messagesPanel = new JPanel();
|
|
||||||
GridLayout gridLayout2 = new GridLayout();
|
|
||||||
JMenuBar jMenuBar1 = new JMenuBar();
|
|
||||||
JMenu jMenu1 = new JMenu();
|
|
||||||
JScrollPane jScrollPane1 = new JScrollPane();
|
|
||||||
JScrollPane messagesScrollPane = new JScrollPane();
|
|
||||||
JScrollPane jScrollPane3 = new JScrollPane();
|
|
||||||
GridLayout gridLayout4 = new GridLayout();
|
|
||||||
JScrollPane jScrollPane4 = new JScrollPane();
|
|
||||||
CardLayout cardLayout1 = new CardLayout();
|
|
||||||
private String JUSTICE_VERSION = "JustIce by Enver Haase";
|
|
||||||
private String current_class;
|
|
||||||
GridLayout gridLayout3 = new GridLayout();
|
|
||||||
JTextPane pass1TextPane = new JTextPane();
|
|
||||||
JTextPane pass2TextPane = new JTextPane();
|
|
||||||
JTextPane messagesTextPane = new JTextPane();
|
|
||||||
JMenuItem newFileMenuItem = new JMenuItem();
|
|
||||||
JSplitPane jSplitPane3 = new JSplitPane();
|
|
||||||
JSplitPane jSplitPane4 = new JSplitPane();
|
|
||||||
JScrollPane jScrollPane2 = new JScrollPane();
|
|
||||||
JScrollPane jScrollPane5 = new JScrollPane();
|
|
||||||
JScrollPane jScrollPane6 = new JScrollPane();
|
|
||||||
JScrollPane jScrollPane7 = new JScrollPane();
|
|
||||||
JList pass3aJList = new JList();
|
|
||||||
JList pass3bJList = new JList();
|
|
||||||
JTextPane pass3aTextPane = new JTextPane();
|
|
||||||
JTextPane pass3bTextPane = new JTextPane();
|
|
||||||
JMenu jMenu2 = new JMenu();
|
|
||||||
JMenuItem whatisMenuItem = new JMenuItem();
|
|
||||||
JMenuItem aboutMenuItem = new JMenuItem();
|
|
||||||
|
|
||||||
|
|
||||||
/** Constructor. */
|
|
||||||
public VerifierAppFrame() {
|
|
||||||
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
|
|
||||||
try {
|
|
||||||
jbInit();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Initizalization of the components. */
|
|
||||||
private void jbInit() throws Exception {
|
|
||||||
//setIconImage(Toolkit.getDefaultToolkit().createImage(Frame1.class.getResource("[Ihr Symbol]")));
|
|
||||||
contentPane = (JPanel) this.getContentPane();
|
|
||||||
contentPane.setLayout(cardLayout1);
|
|
||||||
this.setJMenuBar(jMenuBar1);
|
|
||||||
this.setSize(new Dimension(708, 451));
|
|
||||||
this.setTitle("JustIce");
|
|
||||||
jPanel1.setMinimumSize(new Dimension(100, 100));
|
|
||||||
jPanel1.setPreferredSize(new Dimension(100, 100));
|
|
||||||
jPanel1.setLayout(gridLayout1);
|
|
||||||
jSplitPane2.setOrientation(JSplitPane.VERTICAL_SPLIT);
|
|
||||||
jPanel2.setLayout(gridLayout2);
|
|
||||||
jPanel3.setMinimumSize(new Dimension(200, 100));
|
|
||||||
jPanel3.setPreferredSize(new Dimension(400, 400));
|
|
||||||
jPanel3.setLayout(gridLayout4);
|
|
||||||
messagesPanel.setMinimumSize(new Dimension(100, 100));
|
|
||||||
messagesPanel.setLayout(gridLayout3);
|
|
||||||
jPanel2.setMinimumSize(new Dimension(200, 100));
|
|
||||||
jMenu1.setText("File");
|
|
||||||
jScrollPane1.getViewport().setBackground(Color.red);
|
|
||||||
messagesScrollPane.getViewport().setBackground(Color.red);
|
|
||||||
messagesScrollPane.setPreferredSize(new Dimension(10, 10));
|
|
||||||
classNamesJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
|
|
||||||
|
|
||||||
public void valueChanged( ListSelectionEvent e ) {
|
|
||||||
classNamesJList_valueChanged(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
classNamesJList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
jScrollPane3.setBorder(BorderFactory.createLineBorder(Color.black));
|
|
||||||
jScrollPane3.setPreferredSize(new Dimension(100, 100));
|
|
||||||
gridLayout4.setRows(4);
|
|
||||||
gridLayout4.setColumns(1);
|
|
||||||
gridLayout4.setHgap(1);
|
|
||||||
jScrollPane4.setBorder(BorderFactory.createLineBorder(Color.black));
|
|
||||||
jScrollPane4.setPreferredSize(new Dimension(100, 100));
|
|
||||||
pass1TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
|
|
||||||
pass1TextPane.setToolTipText("");
|
|
||||||
pass1TextPane.setEditable(false);
|
|
||||||
pass2TextPane.setBorder(BorderFactory.createRaisedBevelBorder());
|
|
||||||
pass2TextPane.setEditable(false);
|
|
||||||
messagesTextPane.setBorder(BorderFactory.createRaisedBevelBorder());
|
|
||||||
messagesTextPane.setEditable(false);
|
|
||||||
newFileMenuItem.setText("New...");
|
|
||||||
newFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(78,
|
|
||||||
java.awt.event.KeyEvent.CTRL_MASK, true));
|
|
||||||
newFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed( ActionEvent e ) {
|
|
||||||
newFileMenuItem_actionPerformed(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pass3aTextPane.setEditable(false);
|
|
||||||
pass3bTextPane.setEditable(false);
|
|
||||||
pass3aJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
|
|
||||||
|
|
||||||
public void valueChanged( ListSelectionEvent e ) {
|
|
||||||
pass3aJList_valueChanged(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pass3bJList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
|
|
||||||
|
|
||||||
public void valueChanged( ListSelectionEvent e ) {
|
|
||||||
pass3bJList_valueChanged(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
jMenu2.setText("Help");
|
|
||||||
whatisMenuItem.setText("What is...");
|
|
||||||
whatisMenuItem.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed( ActionEvent e ) {
|
|
||||||
whatisMenuItem_actionPerformed(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
aboutMenuItem.setText("About");
|
|
||||||
aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
|
|
||||||
|
|
||||||
public void actionPerformed( ActionEvent e ) {
|
|
||||||
aboutMenuItem_actionPerformed(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
jSplitPane2.add(messagesPanel, JSplitPane.BOTTOM);
|
|
||||||
messagesPanel.add(messagesScrollPane, null);
|
|
||||||
messagesScrollPane.getViewport().add(messagesTextPane, null);
|
|
||||||
jSplitPane2.add(jPanel3, JSplitPane.TOP);
|
|
||||||
jPanel3.add(jScrollPane3, null);
|
|
||||||
jScrollPane3.getViewport().add(pass1TextPane, null);
|
|
||||||
jPanel3.add(jScrollPane4, null);
|
|
||||||
jPanel3.add(jSplitPane3, null);
|
|
||||||
jSplitPane3.add(jScrollPane2, JSplitPane.LEFT);
|
|
||||||
jScrollPane2.getViewport().add(pass3aJList, null);
|
|
||||||
jSplitPane3.add(jScrollPane5, JSplitPane.RIGHT);
|
|
||||||
jScrollPane5.getViewport().add(pass3aTextPane, null);
|
|
||||||
jPanel3.add(jSplitPane4, null);
|
|
||||||
jSplitPane4.add(jScrollPane6, JSplitPane.LEFT);
|
|
||||||
jScrollPane6.getViewport().add(pass3bJList, null);
|
|
||||||
jSplitPane4.add(jScrollPane7, JSplitPane.RIGHT);
|
|
||||||
jScrollPane7.getViewport().add(pass3bTextPane, null);
|
|
||||||
jScrollPane4.getViewport().add(pass2TextPane, null);
|
|
||||||
jSplitPane1.add(jPanel2, JSplitPane.TOP);
|
|
||||||
jPanel2.add(jScrollPane1, null);
|
|
||||||
jSplitPane1.add(jPanel1, JSplitPane.BOTTOM);
|
|
||||||
jPanel1.add(jSplitPane2, null);
|
|
||||||
jScrollPane1.getViewport().add(classNamesJList, null);
|
|
||||||
jMenuBar1.add(jMenu1);
|
|
||||||
jMenuBar1.add(jMenu2);
|
|
||||||
contentPane.add(jSplitPane1, "jSplitPane1");
|
|
||||||
jMenu1.add(newFileMenuItem);
|
|
||||||
jMenu2.add(whatisMenuItem);
|
|
||||||
jMenu2.add(aboutMenuItem);
|
|
||||||
jSplitPane2.setDividerLocation(300);
|
|
||||||
jSplitPane3.setDividerLocation(150);
|
|
||||||
jSplitPane4.setDividerLocation(150);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Overridden to stop the application on a closing window. */
|
|
||||||
protected void processWindowEvent( WindowEvent e ) {
|
|
||||||
super.processWindowEvent(e);
|
|
||||||
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
synchronized void classNamesJList_valueChanged( ListSelectionEvent e ) {
|
|
||||||
if (e.getValueIsAdjusting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
current_class = classNamesJList.getSelectedValue().toString();
|
|
||||||
try {
|
|
||||||
verify();
|
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
// FIXME: report the error using the GUI
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
classNamesJList.setSelectedValue(current_class, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void verify() throws ClassNotFoundException {
|
|
||||||
setTitle("PLEASE WAIT");
|
|
||||||
Verifier v = VerifierFactory.getVerifier(current_class);
|
|
||||||
v.flush(); // Don't cache the verification result for this class.
|
|
||||||
VerificationResult vr;
|
|
||||||
vr = v.doPass1();
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
pass1TextPane.setText(vr.getMessage());
|
|
||||||
pass1TextPane.setBackground(Color.red);
|
|
||||||
pass2TextPane.setText("");
|
|
||||||
pass2TextPane.setBackground(Color.yellow);
|
|
||||||
pass3aTextPane.setText("");
|
|
||||||
pass3aJList.setListData(new Object[0]);
|
|
||||||
pass3aTextPane.setBackground(Color.yellow);
|
|
||||||
pass3bTextPane.setText("");
|
|
||||||
pass3bJList.setListData(new Object[0]);
|
|
||||||
pass3bTextPane.setBackground(Color.yellow);
|
|
||||||
} else { // Must be VERIFIED_OK, Pass 1 does not know VERIFIED_NOTYET
|
|
||||||
pass1TextPane.setBackground(Color.green);
|
|
||||||
pass1TextPane.setText(vr.getMessage());
|
|
||||||
vr = v.doPass2();
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
pass2TextPane.setText(vr.getMessage());
|
|
||||||
pass2TextPane.setBackground(Color.red);
|
|
||||||
pass3aTextPane.setText("");
|
|
||||||
pass3aTextPane.setBackground(Color.yellow);
|
|
||||||
pass3aJList.setListData(new Object[0]);
|
|
||||||
pass3bTextPane.setText("");
|
|
||||||
pass3bTextPane.setBackground(Color.yellow);
|
|
||||||
pass3bJList.setListData(new Object[0]);
|
|
||||||
} else { // must be Verified_OK, because Pass1 was OK (cannot be Verified_NOTYET).
|
|
||||||
pass2TextPane.setText(vr.getMessage());
|
|
||||||
pass2TextPane.setBackground(Color.green);
|
|
||||||
JavaClass jc = Repository.lookupClass(current_class);
|
|
||||||
/*
|
|
||||||
boolean all3aok = true;
|
|
||||||
boolean all3bok = true;
|
|
||||||
String all3amsg = "";
|
|
||||||
String all3bmsg = "";
|
|
||||||
*/
|
|
||||||
String[] methodnames = new String[jc.getMethods().length];
|
|
||||||
for (int i = 0; i < jc.getMethods().length; i++) {
|
|
||||||
methodnames[i] = jc.getMethods()[i].toString().replace('\n', ' ').replace('\t',
|
|
||||||
' ');
|
|
||||||
}
|
|
||||||
pass3aJList.setListData(methodnames);
|
|
||||||
pass3aJList.setSelectionInterval(0, jc.getMethods().length - 1);
|
|
||||||
pass3bJList.setListData(methodnames);
|
|
||||||
pass3bJList.setSelectionInterval(0, jc.getMethods().length - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String[] msgs = v.getMessages();
|
|
||||||
messagesTextPane.setBackground(msgs.length == 0 ? Color.green : Color.yellow);
|
|
||||||
String allmsgs = "";
|
|
||||||
for (int i = 0; i < msgs.length; i++) {
|
|
||||||
msgs[i] = msgs[i].replace('\n', ' ');
|
|
||||||
allmsgs += msgs[i] + "\n\n";
|
|
||||||
}
|
|
||||||
messagesTextPane.setText(allmsgs);
|
|
||||||
setTitle(current_class + " - " + JUSTICE_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void newFileMenuItem_actionPerformed( ActionEvent e ) {
|
|
||||||
String classname = JOptionPane
|
|
||||||
.showInputDialog("Please enter the fully qualified name of a class or interface to verify:");
|
|
||||||
if ((classname == null) || (classname.equals(""))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VerifierFactory.getVerifier(classname); // let observers do the rest.
|
|
||||||
classNamesJList.setSelectedValue(classname, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
synchronized void pass3aJList_valueChanged( ListSelectionEvent e ) {
|
|
||||||
if (e.getValueIsAdjusting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Verifier v = VerifierFactory.getVerifier(current_class);
|
|
||||||
String all3amsg = "";
|
|
||||||
boolean all3aok = true;
|
|
||||||
boolean rejected = false;
|
|
||||||
for (int i = 0; i < pass3aJList.getModel().getSize(); i++) {
|
|
||||||
if (pass3aJList.isSelectedIndex(i)) {
|
|
||||||
VerificationResult vr = v.doPass3a(i);
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
all3aok = false;
|
|
||||||
rejected = true;
|
|
||||||
}
|
|
||||||
JavaClass jc = null;
|
|
||||||
try {
|
|
||||||
jc = Repository.lookupClass(v.getClassName());
|
|
||||||
all3amsg += "Method '" + jc.getMethods()[i] + "': "
|
|
||||||
+ vr.getMessage().replace('\n', ' ') + "\n\n";
|
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
// FIXME: handle the error
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass3aTextPane.setText(all3amsg);
|
|
||||||
pass3aTextPane.setBackground(all3aok ? Color.green : (rejected ? Color.red : Color.yellow));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
synchronized void pass3bJList_valueChanged( ListSelectionEvent e ) {
|
|
||||||
if (e.getValueIsAdjusting()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Verifier v = VerifierFactory.getVerifier(current_class);
|
|
||||||
String all3bmsg = "";
|
|
||||||
boolean all3bok = true;
|
|
||||||
boolean rejected = false;
|
|
||||||
for (int i = 0; i < pass3bJList.getModel().getSize(); i++) {
|
|
||||||
if (pass3bJList.isSelectedIndex(i)) {
|
|
||||||
VerificationResult vr = v.doPass3b(i);
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
all3bok = false;
|
|
||||||
rejected = true;
|
|
||||||
}
|
|
||||||
JavaClass jc = null;
|
|
||||||
try {
|
|
||||||
jc = Repository.lookupClass(v.getClassName());
|
|
||||||
all3bmsg += "Method '" + jc.getMethods()[i] + "': "
|
|
||||||
+ vr.getMessage().replace('\n', ' ') + "\n\n";
|
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
// FIXME: handle the error
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pass3bTextPane.setText(all3bmsg);
|
|
||||||
pass3bTextPane.setBackground(all3bok ? Color.green : (rejected ? Color.red : Color.yellow));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void aboutMenuItem_actionPerformed( ActionEvent e ) {
|
|
||||||
JOptionPane
|
|
||||||
.showMessageDialog(
|
|
||||||
this,
|
|
||||||
"JustIce is a Java class file verifier.\nIt was implemented by Enver Haase in 2001, 2002.\n<http://jakarta.apache.org/bcel/index.html>",
|
|
||||||
JUSTICE_VERSION, JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void whatisMenuItem_actionPerformed( ActionEvent e ) {
|
|
||||||
JOptionPane
|
|
||||||
.showMessageDialog(
|
|
||||||
this,
|
|
||||||
"The upper four boxes to the right reflect verification passes according to The Java Virtual Machine Specification.\nThese are (in that order): Pass one, Pass two, Pass three (before data flow analysis), Pass three (data flow analysis).\nThe bottom box to the right shows (warning) messages; warnings do not cause a class to be rejected.",
|
|
||||||
JUSTICE_VERSION, JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class produces instances of the Verifier class. Its purpose is to make
|
|
||||||
* sure that they are singleton instances with respect to the class name they
|
|
||||||
* operate on. That means, for every class (represented by a unique fully qualified
|
|
||||||
* class name) there is exactly one Verifier.
|
|
||||||
*
|
|
||||||
* @version $Id: VerifierFactory.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see org.apache.bcel.verifier.Verifier
|
|
||||||
*/
|
|
||||||
public class VerifierFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The HashMap that holds the data about the already-constructed Verifier instances.
|
|
||||||
*/
|
|
||||||
private static Map hashMap = new HashMap();
|
|
||||||
/**
|
|
||||||
* The VerifierFactoryObserver instances that observe the VerifierFactory.
|
|
||||||
*/
|
|
||||||
private static List observers = new Vector();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The VerifierFactory is not instantiable.
|
|
||||||
*/
|
|
||||||
private VerifierFactory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the (only) verifier responsible for the class with the given name.
|
|
||||||
* Possibly a new Verifier object is transparently created.
|
|
||||||
* @return the (only) verifier responsible for the class with the given name.
|
|
||||||
*/
|
|
||||||
public static Verifier getVerifier( String fully_qualified_classname ) {
|
|
||||||
Verifier v = (Verifier) (hashMap.get(fully_qualified_classname));
|
|
||||||
if (v == null) {
|
|
||||||
v = new Verifier(fully_qualified_classname);
|
|
||||||
hashMap.put(fully_qualified_classname, v);
|
|
||||||
notify(fully_qualified_classname);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the observers of a newly generated Verifier.
|
|
||||||
*/
|
|
||||||
private static void notify( String fully_qualified_classname ) {
|
|
||||||
// notify the observers
|
|
||||||
Iterator i = observers.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
VerifierFactoryObserver vfo = (VerifierFactoryObserver) i.next();
|
|
||||||
vfo.update(fully_qualified_classname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all Verifier instances created so far.
|
|
||||||
* This is useful when a Verifier recursively lets
|
|
||||||
* the VerifierFactory create other Verifier instances
|
|
||||||
* and if you want to verify the transitive hull of
|
|
||||||
* referenced class files.
|
|
||||||
*/
|
|
||||||
public static Verifier[] getVerifiers() {
|
|
||||||
Verifier[] vs = new Verifier[hashMap.values().size()];
|
|
||||||
return (Verifier[]) (hashMap.values().toArray(vs)); // Because vs is big enough, vs is used to store the values into and returned!
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the VerifierFactoryObserver o to the list of observers.
|
|
||||||
*/
|
|
||||||
public static void attach( VerifierFactoryObserver o ) {
|
|
||||||
observers.add(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the VerifierFactoryObserver o from the list of observers.
|
|
||||||
*/
|
|
||||||
public static void detach( VerifierFactoryObserver o ) {
|
|
||||||
observers.remove(o);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import javax.swing.event.ListDataEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements an adapter; it implements both a Swing ListModel and
|
|
||||||
* a VerifierFactoryObserver.
|
|
||||||
*
|
|
||||||
* @version $Id: VerifierFactoryListModel.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class VerifierFactoryListModel implements org.apache.bcel.verifier.VerifierFactoryObserver,
|
|
||||||
javax.swing.ListModel {
|
|
||||||
|
|
||||||
private java.util.ArrayList listeners = new java.util.ArrayList();
|
|
||||||
private java.util.TreeSet cache = new java.util.TreeSet();
|
|
||||||
|
|
||||||
|
|
||||||
public VerifierFactoryListModel() {
|
|
||||||
VerifierFactory.attach(this);
|
|
||||||
update(null); // fill cache.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized void update( String s ) {
|
|
||||||
int size = listeners.size();
|
|
||||||
Verifier[] verifiers = VerifierFactory.getVerifiers();
|
|
||||||
int num_of_verifiers = verifiers.length;
|
|
||||||
cache.clear();
|
|
||||||
for (int i = 0; i < num_of_verifiers; i++) {
|
|
||||||
cache.add(verifiers[i].getClassName());
|
|
||||||
}
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
ListDataEvent e = new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0,
|
|
||||||
num_of_verifiers - 1);
|
|
||||||
((javax.swing.event.ListDataListener) (listeners.get(i))).contentsChanged(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized void addListDataListener( javax.swing.event.ListDataListener l ) {
|
|
||||||
listeners.add(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized void removeListDataListener( javax.swing.event.ListDataListener l ) {
|
|
||||||
listeners.remove(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized int getSize() {
|
|
||||||
return cache.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized Object getElementAt( int index ) {
|
|
||||||
return (cache.toArray())[index];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VerifierFactoryObserver instances are notified when new Verifier
|
|
||||||
* instances are created.
|
|
||||||
*
|
|
||||||
* @version $Id: VerifierFactoryObserver.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*
|
|
||||||
* @see VerifierFactory#getVerifier(String)
|
|
||||||
* @see VerifierFactory#getVerifiers()
|
|
||||||
* @see VerifierFactory#attach(VerifierFactoryObserver)
|
|
||||||
* @see VerifierFactory#detach(VerifierFactoryObserver)
|
|
||||||
*/
|
|
||||||
public interface VerifierFactoryObserver {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VerifierFactoryObserver instances are notified invoking this method.
|
|
||||||
* The String argument is the fully qualified class name of a class a
|
|
||||||
* new Verifier instance created by the VerifierFactory operates on.
|
|
||||||
*/
|
|
||||||
public void update( String s );
|
|
||||||
}
|
|
@ -1,553 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier;
|
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import org.apache.bcel.Repository;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A class for simple graphical class file verification.
|
|
||||||
* Use the main(String []) method with fully qualified
|
|
||||||
* class names as arguments to use it as a stand-alone
|
|
||||||
* application.
|
|
||||||
* Use the VerifyDialog(String) constructor to use this
|
|
||||||
* class in your application.
|
|
||||||
* [This class was created using VisualAge for Java,
|
|
||||||
* but it does not work under VAJ itself (Version 3.02 JDK 1.2)]
|
|
||||||
* @version $Id: VerifyDialog.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see #main(String[])
|
|
||||||
* @see #VerifyDialog(String)
|
|
||||||
*/
|
|
||||||
public class VerifyDialog extends javax.swing.JDialog {
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel ivjJDialogContentPane = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel ivjPass1Panel = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel ivjPass2Panel = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel ivjPass3Panel = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton ivjPass1Button = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton ivjPass2Button = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton ivjPass3Button = null;
|
|
||||||
/** Machine-generated. */
|
|
||||||
IvjEventHandler ivjEventHandler = new IvjEventHandler();
|
|
||||||
/**
|
|
||||||
* The class to verify. Default set to 'java.lang.Object'
|
|
||||||
* in case this class is instantiated via one of the many
|
|
||||||
* machine-generated constructors.
|
|
||||||
*/
|
|
||||||
private String class_name = "java.lang.Object";
|
|
||||||
/**
|
|
||||||
* This field is here to count the number of open VerifyDialog
|
|
||||||
* instances so the JVM can be exited afer every Dialog had been
|
|
||||||
* closed.
|
|
||||||
*/
|
|
||||||
private static int classes_to_verify;
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
class IvjEventHandler implements java.awt.event.ActionListener {
|
|
||||||
|
|
||||||
public void actionPerformed( java.awt.event.ActionEvent e ) {
|
|
||||||
if (e.getSource() == VerifyDialog.this.getPass1Button()) {
|
|
||||||
connEtoC1(e);
|
|
||||||
}
|
|
||||||
if (e.getSource() == VerifyDialog.this.getPass2Button()) {
|
|
||||||
connEtoC2(e);
|
|
||||||
}
|
|
||||||
if (e.getSource() == VerifyDialog.this.getPass3Button()) {
|
|
||||||
connEtoC3(e);
|
|
||||||
}
|
|
||||||
if (e.getSource() == VerifyDialog.this.getFlushButton()) {
|
|
||||||
connEtoC4(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton ivjFlushButton = null;
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog() {
|
|
||||||
super();
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Dialog owner) {
|
|
||||||
super(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Dialog owner, String title) {
|
|
||||||
super(owner, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Dialog owner, String title, boolean modal) {
|
|
||||||
super(owner, title, modal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Dialog owner, boolean modal) {
|
|
||||||
super(owner, modal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Frame owner) {
|
|
||||||
super(owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Frame owner, String title) {
|
|
||||||
super(owner, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Frame owner, String title, boolean modal) {
|
|
||||||
super(owner, title, modal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public VerifyDialog(java.awt.Frame owner, boolean modal) {
|
|
||||||
super(owner, modal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this constructor if you want a possibility to verify other
|
|
||||||
* class files than java.lang.Object.
|
|
||||||
* @param fully_qualified_class_name java.lang.String
|
|
||||||
*/
|
|
||||||
public VerifyDialog(String fully_qualified_class_name) {
|
|
||||||
super();
|
|
||||||
int dotclasspos = fully_qualified_class_name.lastIndexOf(".class");
|
|
||||||
if (dotclasspos != -1) {
|
|
||||||
fully_qualified_class_name = fully_qualified_class_name.substring(0, dotclasspos);
|
|
||||||
}
|
|
||||||
fully_qualified_class_name = fully_qualified_class_name.replace('/', '.');
|
|
||||||
class_name = fully_qualified_class_name;
|
|
||||||
initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void connEtoC1( java.awt.event.ActionEvent arg1 ) {
|
|
||||||
try {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
this.pass1Button_ActionPerformed(arg1);
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {3}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void connEtoC2( java.awt.event.ActionEvent arg1 ) {
|
|
||||||
try {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
this.pass2Button_ActionPerformed(arg1);
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {3}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void connEtoC3( java.awt.event.ActionEvent arg1 ) {
|
|
||||||
try {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
this.pass4Button_ActionPerformed(arg1);
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {3}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void connEtoC4( java.awt.event.ActionEvent arg1 ) {
|
|
||||||
try {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
this.flushButton_ActionPerformed(arg1);
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {3}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public void flushButton_ActionPerformed( java.awt.event.ActionEvent actionEvent ) {
|
|
||||||
VerifierFactory.getVerifier(class_name).flush();
|
|
||||||
Repository.removeClass(class_name); // Make sure it will be reloaded.
|
|
||||||
getPass1Panel().setBackground(Color.gray);
|
|
||||||
getPass1Panel().repaint();
|
|
||||||
getPass2Panel().setBackground(Color.gray);
|
|
||||||
getPass2Panel().repaint();
|
|
||||||
getPass3Panel().setBackground(Color.gray);
|
|
||||||
getPass3Panel().repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton getFlushButton() {
|
|
||||||
if (ivjFlushButton == null) {
|
|
||||||
try {
|
|
||||||
ivjFlushButton = new javax.swing.JButton();
|
|
||||||
ivjFlushButton.setName("FlushButton");
|
|
||||||
ivjFlushButton.setText("Flush: Forget old verification results");
|
|
||||||
ivjFlushButton.setBackground(java.awt.SystemColor.controlHighlight);
|
|
||||||
ivjFlushButton.setBounds(60, 215, 300, 30);
|
|
||||||
ivjFlushButton.setForeground(java.awt.Color.red);
|
|
||||||
ivjFlushButton.setActionCommand("FlushButton");
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjFlushButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel getJDialogContentPane() {
|
|
||||||
if (ivjJDialogContentPane == null) {
|
|
||||||
try {
|
|
||||||
ivjJDialogContentPane = new javax.swing.JPanel();
|
|
||||||
ivjJDialogContentPane.setName("JDialogContentPane");
|
|
||||||
ivjJDialogContentPane.setLayout(null);
|
|
||||||
getJDialogContentPane().add(getPass1Panel(), getPass1Panel().getName());
|
|
||||||
getJDialogContentPane().add(getPass3Panel(), getPass3Panel().getName());
|
|
||||||
getJDialogContentPane().add(getPass2Panel(), getPass2Panel().getName());
|
|
||||||
getJDialogContentPane().add(getPass1Button(), getPass1Button().getName());
|
|
||||||
getJDialogContentPane().add(getPass2Button(), getPass2Button().getName());
|
|
||||||
getJDialogContentPane().add(getPass3Button(), getPass3Button().getName());
|
|
||||||
getJDialogContentPane().add(getFlushButton(), getFlushButton().getName());
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjJDialogContentPane;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton getPass1Button() {
|
|
||||||
if (ivjPass1Button == null) {
|
|
||||||
try {
|
|
||||||
ivjPass1Button = new javax.swing.JButton();
|
|
||||||
ivjPass1Button.setName("Pass1Button");
|
|
||||||
ivjPass1Button.setText("Pass1: Verify binary layout of .class file");
|
|
||||||
ivjPass1Button.setBackground(java.awt.SystemColor.controlHighlight);
|
|
||||||
ivjPass1Button.setBounds(100, 40, 300, 30);
|
|
||||||
ivjPass1Button.setActionCommand("Button1");
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass1Button;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel getPass1Panel() {
|
|
||||||
if (ivjPass1Panel == null) {
|
|
||||||
try {
|
|
||||||
ivjPass1Panel = new javax.swing.JPanel();
|
|
||||||
ivjPass1Panel.setName("Pass1Panel");
|
|
||||||
ivjPass1Panel.setLayout(null);
|
|
||||||
ivjPass1Panel.setBackground(java.awt.SystemColor.controlShadow);
|
|
||||||
ivjPass1Panel.setBounds(30, 30, 50, 50);
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass1Panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton getPass2Button() {
|
|
||||||
if (ivjPass2Button == null) {
|
|
||||||
try {
|
|
||||||
ivjPass2Button = new javax.swing.JButton();
|
|
||||||
ivjPass2Button.setName("Pass2Button");
|
|
||||||
ivjPass2Button.setText("Pass 2: Verify static .class file constraints");
|
|
||||||
ivjPass2Button.setBackground(java.awt.SystemColor.controlHighlight);
|
|
||||||
ivjPass2Button.setBounds(100, 100, 300, 30);
|
|
||||||
ivjPass2Button.setActionCommand("Button2");
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass2Button;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel getPass2Panel() {
|
|
||||||
if (ivjPass2Panel == null) {
|
|
||||||
try {
|
|
||||||
ivjPass2Panel = new javax.swing.JPanel();
|
|
||||||
ivjPass2Panel.setName("Pass2Panel");
|
|
||||||
ivjPass2Panel.setLayout(null);
|
|
||||||
ivjPass2Panel.setBackground(java.awt.SystemColor.controlShadow);
|
|
||||||
ivjPass2Panel.setBounds(30, 90, 50, 50);
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass2Panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JButton getPass3Button() {
|
|
||||||
if (ivjPass3Button == null) {
|
|
||||||
try {
|
|
||||||
ivjPass3Button = new javax.swing.JButton();
|
|
||||||
ivjPass3Button.setName("Pass3Button");
|
|
||||||
ivjPass3Button.setText("Passes 3a+3b: Verify code arrays");
|
|
||||||
ivjPass3Button.setBackground(java.awt.SystemColor.controlHighlight);
|
|
||||||
ivjPass3Button.setBounds(100, 160, 300, 30);
|
|
||||||
ivjPass3Button.setActionCommand("Button2");
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass3Button;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private javax.swing.JPanel getPass3Panel() {
|
|
||||||
if (ivjPass3Panel == null) {
|
|
||||||
try {
|
|
||||||
ivjPass3Panel = new javax.swing.JPanel();
|
|
||||||
ivjPass3Panel.setName("Pass3Panel");
|
|
||||||
ivjPass3Panel.setLayout(null);
|
|
||||||
ivjPass3Panel.setBackground(java.awt.SystemColor.controlShadow);
|
|
||||||
ivjPass3Panel.setBounds(30, 150, 50, 50);
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
// user code begin {2}
|
|
||||||
// user code end
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ivjPass3Panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void handleException( java.lang.Throwable exception ) {
|
|
||||||
/* Uncomment the following lines to print uncaught exceptions to stdout */
|
|
||||||
System.out.println("--------- UNCAUGHT EXCEPTION ---------");
|
|
||||||
exception.printStackTrace(System.out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void initConnections() throws java.lang.Exception {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
getPass1Button().addActionListener(ivjEventHandler);
|
|
||||||
getPass2Button().addActionListener(ivjEventHandler);
|
|
||||||
getPass3Button().addActionListener(ivjEventHandler);
|
|
||||||
getFlushButton().addActionListener(ivjEventHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
private void initialize() {
|
|
||||||
try {
|
|
||||||
// user code begin {1}
|
|
||||||
// user code end
|
|
||||||
setName("VerifyDialog");
|
|
||||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
|
||||||
setSize(430, 280);
|
|
||||||
setVisible(true);
|
|
||||||
setModal(true);
|
|
||||||
setResizable(false);
|
|
||||||
setContentPane(getJDialogContentPane());
|
|
||||||
initConnections();
|
|
||||||
} catch (java.lang.Throwable ivjExc) {
|
|
||||||
handleException(ivjExc);
|
|
||||||
}
|
|
||||||
// user code begin {2}
|
|
||||||
setTitle("'" + class_name + "' verification - JustIce / BCEL");
|
|
||||||
// user code end
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies one or more class files.
|
|
||||||
* Verification results are presented graphically: Red means 'rejected',
|
|
||||||
* green means 'passed' while yellow means 'could not be verified yet'.
|
|
||||||
* @param args java.lang.String[] fully qualified names of classes to verify.
|
|
||||||
*/
|
|
||||||
public static void main( java.lang.String[] args ) {
|
|
||||||
classes_to_verify = args.length;
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
try {
|
|
||||||
VerifyDialog aVerifyDialog;
|
|
||||||
aVerifyDialog = new VerifyDialog(args[i]);
|
|
||||||
aVerifyDialog.setModal(true);
|
|
||||||
aVerifyDialog.addWindowListener(new java.awt.event.WindowAdapter() {
|
|
||||||
|
|
||||||
public void windowClosing( java.awt.event.WindowEvent e ) {
|
|
||||||
classes_to_verify--;
|
|
||||||
if (classes_to_verify == 0) {
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
aVerifyDialog.setVisible(true);
|
|
||||||
} catch (Throwable exception) {
|
|
||||||
System.err.println("Exception occurred in main() of javax.swing.JDialog");
|
|
||||||
exception.printStackTrace(System.out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public void pass1Button_ActionPerformed( java.awt.event.ActionEvent actionEvent ) {
|
|
||||||
Verifier v = VerifierFactory.getVerifier(class_name);
|
|
||||||
VerificationResult vr = v.doPass1();
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
|
|
||||||
getPass1Panel().setBackground(Color.green);
|
|
||||||
getPass1Panel().repaint();
|
|
||||||
}
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
getPass1Panel().setBackground(Color.red);
|
|
||||||
getPass1Panel().repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public void pass2Button_ActionPerformed( java.awt.event.ActionEvent actionEvent ) {
|
|
||||||
pass1Button_ActionPerformed(actionEvent);
|
|
||||||
Verifier v = VerifierFactory.getVerifier(class_name);
|
|
||||||
VerificationResult vr = v.doPass2();
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
|
|
||||||
getPass2Panel().setBackground(Color.green);
|
|
||||||
getPass2Panel().repaint();
|
|
||||||
}
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_NOTYET) {
|
|
||||||
getPass2Panel().setBackground(Color.yellow);
|
|
||||||
getPass2Panel().repaint();
|
|
||||||
}
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_REJECTED) {
|
|
||||||
getPass2Panel().setBackground(Color.red);
|
|
||||||
getPass2Panel().repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Machine-generated. */
|
|
||||||
public void pass4Button_ActionPerformed( java.awt.event.ActionEvent actionEvent ) {
|
|
||||||
pass2Button_ActionPerformed(actionEvent);
|
|
||||||
Color color = Color.green;
|
|
||||||
Verifier v = VerifierFactory.getVerifier(class_name);
|
|
||||||
VerificationResult vr = v.doPass2();
|
|
||||||
if (vr.getStatus() == VerificationResult.VERIFIED_OK) {
|
|
||||||
JavaClass jc = null;
|
|
||||||
try {
|
|
||||||
jc = Repository.lookupClass(class_name);
|
|
||||||
int nr = jc.getMethods().length;
|
|
||||||
for (int i = 0; i < nr; i++) {
|
|
||||||
vr = v.doPass3b(i);
|
|
||||||
if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
|
|
||||||
color = Color.red;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException ex) {
|
|
||||||
// FIXME: report the error
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
color = Color.yellow;
|
|
||||||
}
|
|
||||||
getPass3Panel().setBackground(color);
|
|
||||||
getPass3Panel().repaint();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class should never be thrown. When such an instance is thrown,
|
|
||||||
* this is due to an INTERNAL ERROR of BCEL's class file verifier "JustIce".
|
|
||||||
*
|
|
||||||
* @version $Id: AssertionViolatedException.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public final class AssertionViolatedException extends RuntimeException{
|
|
||||||
/** The error message. */
|
|
||||||
private String detailMessage;
|
|
||||||
/** Constructs a new AssertionViolatedException with null as its error message string. */
|
|
||||||
public AssertionViolatedException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a new AssertionViolatedException with the specified error message preceded
|
|
||||||
* by "INTERNAL ERROR: ".
|
|
||||||
*/
|
|
||||||
public AssertionViolatedException(String message){
|
|
||||||
super(message = "INTERNAL ERROR: "+message); // Thanks to Java, the constructor call here must be first.
|
|
||||||
detailMessage=message;
|
|
||||||
}
|
|
||||||
/** Extends the error message with a string before ("pre") and after ("post") the
|
|
||||||
'old' error message. All of these three strings are allowed to be null, and null
|
|
||||||
is always replaced by the empty string (""). In particular, after invoking this
|
|
||||||
method, the error message of this object can no longer be null.
|
|
||||||
*/
|
|
||||||
public void extendMessage(String pre, String post){
|
|
||||||
if (pre == null) {
|
|
||||||
pre="";
|
|
||||||
}
|
|
||||||
if (detailMessage == null) {
|
|
||||||
detailMessage="";
|
|
||||||
}
|
|
||||||
if (post == null) {
|
|
||||||
post="";
|
|
||||||
}
|
|
||||||
detailMessage = pre+detailMessage+post;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns the error message string of this AssertionViolatedException object.
|
|
||||||
* @return the error message string of this AssertionViolatedException.
|
|
||||||
*/
|
|
||||||
public String getMessage(){
|
|
||||||
return detailMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DO NOT USE. It's for experimental testing during development only.
|
|
||||||
*/
|
|
||||||
public static void main(String[] args){
|
|
||||||
AssertionViolatedException ave = new AssertionViolatedException("Oops!");
|
|
||||||
ave.extendMessage("\nFOUND:\n\t","\nExiting!!\n");
|
|
||||||
throw ave;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce"
|
|
||||||
* when a class file to verify does not pass the verification pass 2 as described
|
|
||||||
* in the Java Virtual Machine specification, 2nd edition.
|
|
||||||
*
|
|
||||||
* @version $Id: ClassConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class ClassConstraintException extends VerificationException{
|
|
||||||
/**
|
|
||||||
* Constructs a new ClassConstraintException with null as its error message string.
|
|
||||||
*/
|
|
||||||
public ClassConstraintException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new ClassConstraintException with the specified error message.
|
|
||||||
*/
|
|
||||||
public ClassConstraintException(String message){
|
|
||||||
super (message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file does not pass the verification pass 3. Note that the pass 3 used by
|
|
||||||
* "JustIce" involves verification that is usually delayed to pass 4.
|
|
||||||
*
|
|
||||||
* @version $Id: CodeConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public abstract class CodeConstraintException extends VerificationException{
|
|
||||||
/**
|
|
||||||
* Constructs a new CodeConstraintException with null as its error message string.
|
|
||||||
*/
|
|
||||||
CodeConstraintException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a new CodeConstraintException with the specified error message.
|
|
||||||
*/
|
|
||||||
CodeConstraintException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce"
|
|
||||||
* when the verification of a method is requested that does not exist.
|
|
||||||
*
|
|
||||||
* @version $Id: InvalidMethodException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class InvalidMethodException extends RuntimeException{
|
|
||||||
|
|
||||||
/** Constructs an InvalidMethodException with the specified detail message. */
|
|
||||||
public InvalidMethodException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file to verify does not pass the verification pass 3 because of a violation
|
|
||||||
* of a constraint that is usually only verified at run-time (pass 4).
|
|
||||||
* The Java Virtual Machine Specification, 2nd edition, states that certain constraints
|
|
||||||
* are usually verified at run-time for performance reasons (the verification of those
|
|
||||||
* constraints requires loading in and recursively verifying referenced classes) that
|
|
||||||
* conceptually belong to pass 3; to be precise, that conceptually belong to the
|
|
||||||
* data flow analysis of pass 3 (called pass 3b in JustIce).
|
|
||||||
* These are the checks necessary for resolution: Compare pages 142-143 ("4.9.1 The
|
|
||||||
* Verification Process") and pages 50-51 ("2.17.3 Linking: Verification, Preparation,
|
|
||||||
* and Resolution") of the above mentioned book.
|
|
||||||
* <B>TODO: At this time, this class is not used in JustIce.</B>
|
|
||||||
*
|
|
||||||
* @version $Id: LinkingConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LinkingConstraintException extends StructuralCodeConstraintException{
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When loading a class file, BCEL will throw an instance of LoadingException if
|
|
||||||
* the class file is malformed; so it is not conforming to the "Pass 1" verification
|
|
||||||
* process as described in the Java Virtual Machine specification, 2nd. edition.
|
|
||||||
* @version $Id: LoadingException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LoadingException extends VerifierConstraintViolatedException{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LoadingException with null as its error message string.
|
|
||||||
*/
|
|
||||||
public LoadingException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LoadingException with the specified error message.
|
|
||||||
*/
|
|
||||||
public LoadingException(String message){
|
|
||||||
super (message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A LocalVariableInfoInconsistentException instance is thrown by
|
|
||||||
* the LocalVariableInfo class when it detects that the information
|
|
||||||
* it holds is inconsistent; this is normally due to inconsistent
|
|
||||||
* LocalVariableTable entries in the Code attribute of a certain
|
|
||||||
* Method object.
|
|
||||||
*
|
|
||||||
* @version $Id: LocalVariableInfoInconsistentException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LocalVariableInfoInconsistentException extends ClassConstraintException{
|
|
||||||
/**
|
|
||||||
* Constructs a new LocalVariableInfoInconsistentException with null as its error message string.
|
|
||||||
*/
|
|
||||||
public LocalVariableInfoInconsistentException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LocalVariableInfoInconsistentException with the specified error message.
|
|
||||||
*/
|
|
||||||
public LocalVariableInfoInconsistentException(String message){
|
|
||||||
super (message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file to verify does not pass the verification pass 3 because of a violation
|
|
||||||
* of a static constraint as described in the Java Virtual Machine Specification,
|
|
||||||
* 2nd edition, 4.8.1, pages 133-137. The static constraints checking part of pass 3
|
|
||||||
* is called pass 3a in JustIce.
|
|
||||||
*
|
|
||||||
* @version $Id: StaticCodeConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public abstract class StaticCodeConstraintException extends CodeConstraintException{
|
|
||||||
public StaticCodeConstraintException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file to verify does not pass the verification pass 3 because of a violation
|
|
||||||
* of a static constraint as described in the Java Virtual Machine Specification,
|
|
||||||
* Second edition, 4.8.1, pages 133-137. The static constraints checking part of pass 3
|
|
||||||
* is called pass 3a in JustIce.
|
|
||||||
* Static constraints on the instructions in the code array are checked early in
|
|
||||||
* pass 3a and are described on page 134 in the Java Virtual Machine Specification,
|
|
||||||
* Second Edition.
|
|
||||||
*
|
|
||||||
* @version $Id: StaticCodeInstructionConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class StaticCodeInstructionConstraintException extends StaticCodeConstraintException{
|
|
||||||
public StaticCodeInstructionConstraintException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file to verify does not pass the verification pass 3 because of a violation
|
|
||||||
* of a static constraint as described in the Java Virtual Machine Specification,
|
|
||||||
* Second edition, 4.8.1, pages 133-137. The static constraints checking part of pass 3
|
|
||||||
* is called pass 3a in JustIce.
|
|
||||||
* Static constraints on the operands of instructions in the code array are checked late in
|
|
||||||
* pass 3a and are described on page 134-137 in the Java Virtual Machine Specification,
|
|
||||||
* Second Edition.
|
|
||||||
*
|
|
||||||
* @version $Id: StaticCodeInstructionOperandConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class StaticCodeInstructionOperandConstraintException extends StaticCodeConstraintException{
|
|
||||||
public StaticCodeInstructionOperandConstraintException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when
|
|
||||||
* a class file to verify does not pass the verification pass 3 because of a violation
|
|
||||||
* of a structural constraint as described in the Java Virtual Machine Specification,
|
|
||||||
* 2nd edition, 4.8.2, pages 137-139.
|
|
||||||
* Note that the notion of a "structural" constraint is somewhat misleading. Structural
|
|
||||||
* constraints are constraints on relationships between Java virtual machine instructions.
|
|
||||||
* These are the constraints where data-flow analysis is needed to verify if they hold.
|
|
||||||
* The data flow analysis of pass 3 is called pass 3b in JustIce.
|
|
||||||
*
|
|
||||||
* @version $Id: StructuralCodeConstraintException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class StructuralCodeConstraintException extends CodeConstraintException{
|
|
||||||
/**
|
|
||||||
* Constructs a new StructuralCodeConstraintException with the specified error message.
|
|
||||||
*/
|
|
||||||
public StructuralCodeConstraintException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a new StructuralCodeConstraintException with null as its error message string.
|
|
||||||
*/
|
|
||||||
public StructuralCodeConstraintException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class providing convenience methods concerning Throwable instances.
|
|
||||||
* @version $Id: Utility.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see java.lang.Throwable
|
|
||||||
*/
|
|
||||||
public final class Utility{
|
|
||||||
/** This class is not instantiable. */
|
|
||||||
private Utility(){}
|
|
||||||
|
|
||||||
/** This method returns the stack trace of a Throwable instance as a String. */
|
|
||||||
public static String getStackTrace(Throwable t){
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
|
||||||
t.printStackTrace(pw);
|
|
||||||
return sw.toString();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce" when a
|
|
||||||
* class file to verify does not pass one of the verification passes 2 or 3.
|
|
||||||
* Note that the pass 3 used by "JustIce" involves verification that is usually
|
|
||||||
* delayed to pass 4.
|
|
||||||
* The name of this class is justified by the Java Virtual Machine Specification, 2nd
|
|
||||||
* edition, page 164, 5.4.1 where verification as a part of the linking process is
|
|
||||||
* defined to be the verification happening in passes 2 and 3.
|
|
||||||
*
|
|
||||||
* @version $Id: VerificationException.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public abstract class VerificationException extends VerifierConstraintViolatedException{
|
|
||||||
/**
|
|
||||||
* Constructs a new VerificationException with null as its error message string.
|
|
||||||
*/
|
|
||||||
VerificationException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a new VerificationException with the specified error message.
|
|
||||||
*/
|
|
||||||
VerificationException(String message){
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.exc;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class are thrown by BCEL's class file verifier "JustIce"
|
|
||||||
* whenever
|
|
||||||
* verification proves that some constraint of a class file (as stated in the
|
|
||||||
* Java Virtual Machine Specification, Edition 2) is violated.
|
|
||||||
* This is roughly equivalent to the VerifyError the JVM-internal verifiers
|
|
||||||
* throw.
|
|
||||||
*
|
|
||||||
* @version $Id: VerifierConstraintViolatedException.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public abstract class VerifierConstraintViolatedException extends RuntimeException{
|
|
||||||
// /** The name of the offending class that did not pass the verifier. */
|
|
||||||
// String name_of_offending_class;
|
|
||||||
|
|
||||||
/** The specified error message. */
|
|
||||||
private String detailMessage;
|
|
||||||
/**
|
|
||||||
* Constructs a new VerifierConstraintViolatedException with null as its error message string.
|
|
||||||
*/
|
|
||||||
VerifierConstraintViolatedException(){
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Constructs a new VerifierConstraintViolatedException with the specified error message.
|
|
||||||
*/
|
|
||||||
VerifierConstraintViolatedException(String message){
|
|
||||||
super(message); // Not that important
|
|
||||||
detailMessage = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Extends the error message with a string before ("pre") and after ("post") the
|
|
||||||
'old' error message. All of these three strings are allowed to be null, and null
|
|
||||||
is always replaced by the empty string (""). In particular, after invoking this
|
|
||||||
method, the error message of this object can no longer be null.
|
|
||||||
*/
|
|
||||||
public void extendMessage(String pre, String post){
|
|
||||||
if (pre == null) {
|
|
||||||
pre="";
|
|
||||||
}
|
|
||||||
if (detailMessage == null) {
|
|
||||||
detailMessage="";
|
|
||||||
}
|
|
||||||
if (post == null) {
|
|
||||||
post="";
|
|
||||||
}
|
|
||||||
detailMessage = pre+detailMessage+post;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns the error message string of this VerifierConstraintViolatedException object.
|
|
||||||
* @return the error message string of this VerifierConstraintViolatedException.
|
|
||||||
*/
|
|
||||||
public String getMessage(){
|
|
||||||
return detailMessage;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
|
||||||
$Id: package.html 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
-->
|
|
||||||
</head>
|
|
||||||
<body bgcolor="white">
|
|
||||||
|
|
||||||
Exception classes used by JustIce, mostly used internally. You don't need to bother with them.
|
|
||||||
|
|
||||||
<h2>Package Specification</h2>
|
|
||||||
|
|
||||||
Contained in this package are Exception classes for use with the JustIce verifier.
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,18 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
|
||||||
$Id: package.html 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
-->
|
|
||||||
</head>
|
|
||||||
<body bgcolor="white">
|
|
||||||
|
|
||||||
BCEL's verifier JustIce is there to help you dump correct Java class files created or modified with BCEL.
|
|
||||||
|
|
||||||
<h2>Package Specification</h2>
|
|
||||||
|
|
||||||
This is the top-level package of the JustIce verifier. To actually use it, have a look at the VerifierFactory and
|
|
||||||
Verifier classes.
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents the upper half of a DOUBLE variable.
|
|
||||||
* @version $Id: DOUBLE_Upper.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public final class DOUBLE_Upper extends Type{
|
|
||||||
|
|
||||||
/** The one and only instance of this class. */
|
|
||||||
private static DOUBLE_Upper singleInstance = new DOUBLE_Upper();
|
|
||||||
|
|
||||||
/** The constructor; this class must not be instantiated from the outside. */
|
|
||||||
private DOUBLE_Upper(){
|
|
||||||
super(Constants.T_UNKNOWN, "Long_Upper");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use this method to get the single instance of this class. */
|
|
||||||
public static DOUBLE_Upper theInstance(){
|
|
||||||
return singleInstance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A small utility class representing a set of basic int values.
|
|
||||||
*
|
|
||||||
* @version $Id: IntList.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class IntList{
|
|
||||||
/** The int are stored as Integer objects here. */
|
|
||||||
private List theList;
|
|
||||||
/** This constructor creates an empty list. */
|
|
||||||
IntList(){
|
|
||||||
theList = new ArrayList();
|
|
||||||
}
|
|
||||||
/** Adds an element to the list. */
|
|
||||||
void add(int i){
|
|
||||||
theList.add(new Integer(i));
|
|
||||||
}
|
|
||||||
/** Checks if the specified int is already in the list. */
|
|
||||||
boolean contains(int i){
|
|
||||||
Integer[] ints = new Integer[theList.size()];
|
|
||||||
theList.toArray(ints);
|
|
||||||
for (int j=0; j<ints.length; j++){
|
|
||||||
if (i == ints[j].intValue()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents the upper half of a LONG variable.
|
|
||||||
* @version $Id: LONG_Upper.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public final class LONG_Upper extends Type{
|
|
||||||
|
|
||||||
/** The one and only instance of this class. */
|
|
||||||
private static LONG_Upper singleInstance = new LONG_Upper();
|
|
||||||
|
|
||||||
/** The constructor; this class must not be instantiated from the outside. */
|
|
||||||
private LONG_Upper(){
|
|
||||||
super(Constants.T_UNKNOWN, "Long_Upper");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use this method to get the single instance of this class. */
|
|
||||||
public static LONG_Upper theInstance(){
|
|
||||||
return singleInstance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
import org.apache.bcel.verifier.exc.LocalVariableInfoInconsistentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class holding the information about
|
|
||||||
* the name and the type of a local variable in
|
|
||||||
* a given slot (== index). This information
|
|
||||||
* often changes in course of byte code offsets.
|
|
||||||
*
|
|
||||||
* @version $Id: LocalVariableInfo.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LocalVariableInfo{
|
|
||||||
|
|
||||||
/** The types database. KEY: String representing the offset integer. */
|
|
||||||
private Hashtable types = new Hashtable();
|
|
||||||
/** The names database. KEY: String representing the offset integer. */
|
|
||||||
private Hashtable names = new Hashtable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a name of a local variable and a certain slot to our 'names'
|
|
||||||
* (Hashtable) database.
|
|
||||||
*/
|
|
||||||
private void setName(int offset, String name){
|
|
||||||
names.put( ((Integer.toString(offset))), name);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Adds a type of a local variable and a certain slot to our 'types'
|
|
||||||
* (Hashtable) database.
|
|
||||||
*/
|
|
||||||
private void setType(int offset, Type t){
|
|
||||||
types.put( ((Integer.toString(offset))), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the local variable that uses this local
|
|
||||||
* variable slot at the given bytecode offset.
|
|
||||||
* Care for legal bytecode offsets yourself, otherwise the return value
|
|
||||||
* might be wrong.
|
|
||||||
* May return 'null' if nothing is known about the type of this local
|
|
||||||
* variable slot at the given bytecode offset.
|
|
||||||
*/
|
|
||||||
public Type getType(int offset){
|
|
||||||
return (Type) types.get(Integer.toString(offset));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns the name of the local variable that uses this local
|
|
||||||
* variable slot at the given bytecode offset.
|
|
||||||
* Care for legal bytecode offsets yourself, otherwise the return value
|
|
||||||
* might be wrong.
|
|
||||||
* May return 'null' if nothing is known about the type of this local
|
|
||||||
* variable slot at the given bytecode offset.
|
|
||||||
*/
|
|
||||||
public String getName(int offset){
|
|
||||||
return (String) (names.get(Integer.toString(offset)));
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Adds some information about this local variable (slot).
|
|
||||||
* @throws LocalVariableInfoInconsistentException if the new information conflicts
|
|
||||||
* with already gathered information.
|
|
||||||
*/
|
|
||||||
public void add(String name, int startpc, int length, Type t) throws LocalVariableInfoInconsistentException{
|
|
||||||
for (int i=startpc; i<=startpc+length; i++){ // incl/incl-notation!
|
|
||||||
add(i,name,t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds information about name and type for a given offset.
|
|
||||||
* @throws LocalVariableInfoInconsistentException if the new information conflicts
|
|
||||||
* with already gathered information.
|
|
||||||
*/
|
|
||||||
private void add(int offset, String name, Type t) throws LocalVariableInfoInconsistentException{
|
|
||||||
if (getName(offset) != null){
|
|
||||||
if (! getName(offset).equals(name)){
|
|
||||||
throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different names: '"+getName(offset)+"' and '"+name+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (getType(offset) != null){
|
|
||||||
if (! getType(offset).equals(t)){
|
|
||||||
throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different types: '"+getType(offset)+"' and '"+t+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setName(offset, name);
|
|
||||||
setType(offset, t);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.LocalVariableInfoInconsistentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility class holding the information about
|
|
||||||
* the names and the types of the local variables in
|
|
||||||
* a given method.
|
|
||||||
*
|
|
||||||
* @version $Id: LocalVariablesInfo.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LocalVariablesInfo{
|
|
||||||
|
|
||||||
/** The information about the local variables is stored here. */
|
|
||||||
private LocalVariableInfo[] localVariableInfos;
|
|
||||||
|
|
||||||
/** The constructor. */
|
|
||||||
LocalVariablesInfo(int max_locals){
|
|
||||||
localVariableInfos = new LocalVariableInfo[max_locals];
|
|
||||||
for (int i=0; i<max_locals; i++){
|
|
||||||
localVariableInfos[i] = new LocalVariableInfo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the LocalVariableInfo for the given slot. */
|
|
||||||
public LocalVariableInfo getLocalVariableInfo(int slot){
|
|
||||||
if (slot < 0 || slot >= localVariableInfos.length){
|
|
||||||
throw new AssertionViolatedException("Slot number for local variable information out of range.");
|
|
||||||
}
|
|
||||||
return localVariableInfos[slot];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds information about the local variable in slot 'slot'. Automatically
|
|
||||||
* adds information for slot+1 if 't' is Type.LONG or Type.DOUBLE.
|
|
||||||
* @throws LocalVariableInfoInconsistentException if the new information conflicts
|
|
||||||
* with already gathered information.
|
|
||||||
*/
|
|
||||||
public void add(int slot, String name, int startpc, int length, Type t) throws LocalVariableInfoInconsistentException{
|
|
||||||
// The add operation on LocalVariableInfo may throw the '...Inconsistent...' exception, we don't throw it explicitely here.
|
|
||||||
|
|
||||||
if (slot < 0 || slot >= localVariableInfos.length){
|
|
||||||
throw new AssertionViolatedException("Slot number for local variable information out of range.");
|
|
||||||
}
|
|
||||||
|
|
||||||
localVariableInfos[slot].add(name, startpc, length, t);
|
|
||||||
if (t == Type.LONG) {
|
|
||||||
localVariableInfos[slot+1].add(name, startpc, length, LONG_Upper.theInstance());
|
|
||||||
}
|
|
||||||
if (t == Type.DOUBLE) {
|
|
||||||
localVariableInfos[slot+1].add(name, startpc, length, DOUBLE_Upper.theInstance());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.Repository;
|
|
||||||
import org.apache.bcel.classfile.ClassFormatException;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.verifier.PassVerifier;
|
|
||||||
import org.apache.bcel.verifier.VerificationResult;
|
|
||||||
import org.apache.bcel.verifier.Verifier;
|
|
||||||
import org.apache.bcel.verifier.exc.LoadingException;
|
|
||||||
import org.apache.bcel.verifier.exc.Utility;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This PassVerifier verifies a class file according to pass 1 as
|
|
||||||
* described in The Java Virtual Machine Specification, 2nd edition.
|
|
||||||
* More detailed information is to be found at the do_verify() method's
|
|
||||||
* documentation.
|
|
||||||
*
|
|
||||||
* @version $Id: Pass1Verifier.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see #do_verify()
|
|
||||||
*/
|
|
||||||
public final class Pass1Verifier extends PassVerifier{
|
|
||||||
/**
|
|
||||||
* DON'T USE THIS EVEN PRIVATELY! USE getJavaClass() INSTEAD.
|
|
||||||
* @see #getJavaClass()
|
|
||||||
*/
|
|
||||||
private JavaClass jc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Verifier that created this.
|
|
||||||
*/
|
|
||||||
private Verifier myOwner;
|
|
||||||
|
|
||||||
/** Used to load in and return the myOwner-matching JavaClass object when needed. Avoids loading in a class file when it's not really needed! */
|
|
||||||
private JavaClass getJavaClass(){
|
|
||||||
if (jc == null){
|
|
||||||
try {
|
|
||||||
jc = Repository.lookupClass(myOwner.getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// FIXME: currently, Pass1Verifier treats jc == null as a special
|
|
||||||
// case, so we don't need to do anything here. A better solution
|
|
||||||
// would be to simply throw the ClassNotFoundException
|
|
||||||
// out of this method.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Should only be instantiated by a Verifier.
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.verifier.Verifier
|
|
||||||
*/
|
|
||||||
public Pass1Verifier(Verifier owner){
|
|
||||||
myOwner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass-one verification basically means loading in a class file.
|
|
||||||
* The Java Virtual Machine Specification is not too precise about
|
|
||||||
* what makes the difference between passes one and two.
|
|
||||||
* The answer is that only pass one is performed on a class file as
|
|
||||||
* long as its resolution is not requested; whereas pass two and
|
|
||||||
* pass three are performed during the resolution process.
|
|
||||||
* Only four constraints to be checked are explicitely stated by
|
|
||||||
* The Java Virtual Machine Specification, 2nd edition:
|
|
||||||
* <UL>
|
|
||||||
* <LI>The first four bytes must contain the right magic number (0xCAFEBABE).
|
|
||||||
* <LI>All recognized attributes must be of the proper length.
|
|
||||||
* <LI>The class file must not be truncated or have extra bytes at the end.
|
|
||||||
* <LI>The constant pool must not contain any superficially unrecognizable information.
|
|
||||||
* </UL>
|
|
||||||
* A more in-depth documentation of what pass one should do was written by
|
|
||||||
* <A HREF=mailto:pwfong@cs.sfu.ca>Philip W. L. Fong</A>:
|
|
||||||
* <UL>
|
|
||||||
* <LI> the file should not be truncated.
|
|
||||||
* <LI> the file should not have extra bytes at the end.
|
|
||||||
* <LI> all variable-length structures should be well-formatted:
|
|
||||||
* <UL>
|
|
||||||
* <LI> there should only be constant_pool_count-1 many entries in the constant pool.
|
|
||||||
* <LI> all constant pool entries should have size the same as indicated by their type tag.
|
|
||||||
* <LI> there are exactly interfaces_count many entries in the interfaces array of the class file.
|
|
||||||
* <LI> there are exactly fields_count many entries in the fields array of the class file.
|
|
||||||
* <LI> there are exactly methods_count many entries in the methods array of the class file.
|
|
||||||
* <LI> there are exactly attributes_count many entries in the attributes array of the class file, fields, methods, and code attribute.
|
|
||||||
* <LI> there should be exactly attribute_length many bytes in each attribute. Inconsistency between attribute_length and the actually size of the attribute content should be uncovered. For example, in an Exceptions attribute, the actual number of exceptions as required by the number_of_exceptions field might yeild an attribute size that doesn't match the attribute_length. Such an anomaly should be detected.
|
|
||||||
* <LI> all attributes should have proper length. In particular, under certain context (e.g. while parsing method_info), recognizable attributes (e.g. "Code" attribute) should have correct format (e.g. attribute_length is 2).
|
|
||||||
* </UL>
|
|
||||||
* <LI> Also, certain constant values are checked for validity:
|
|
||||||
* <UL>
|
|
||||||
* <LI> The magic number should be 0xCAFEBABE.
|
|
||||||
* <LI> The major and minor version numbers are valid.
|
|
||||||
* <LI> All the constant pool type tags are recognizable.
|
|
||||||
* <LI> All undocumented access flags are masked off before use. Strictly speaking, this is not really a check.
|
|
||||||
* <LI> The field this_class should point to a string that represents a legal non-array class name, and this name should be the same as the class file being loaded.
|
|
||||||
* <LI> the field super_class should point to a string that represents a legal non-array class name.
|
|
||||||
* <LI> Because some of the above checks require cross referencing the constant pool entries, guards are set up to make sure that the referenced entries are of the right type and the indices are within the legal range (0 < index < constant_pool_count).
|
|
||||||
* </UL>
|
|
||||||
* <LI> Extra checks done in pass 1:
|
|
||||||
* <UL>
|
|
||||||
* <LI> the constant values of static fields should have the same type as the fields.
|
|
||||||
* <LI> the number of words in a parameter list does not exceed 255 and locals_max.
|
|
||||||
* <LI> the name and signature of fields and methods are verified to be of legal format.
|
|
||||||
* </UL>
|
|
||||||
* </UL>
|
|
||||||
* (From the Paper <A HREF=http://www.cs.sfu.ca/people/GradStudents/pwfong/personal/JVM/pass1/>The Mysterious Pass One, first draft, September 2, 1997</A>.)
|
|
||||||
* </BR>
|
|
||||||
* However, most of this is done by parsing a class file or generating a class file into BCEL's internal data structure.
|
|
||||||
* <B>Therefore, all that is really done here is look up the class file from BCEL's repository.</B>
|
|
||||||
* This is also motivated by the fact that some omitted things
|
|
||||||
* (like the check for extra bytes at the end of the class file) are handy when actually using BCEL to repair a class file (otherwise you would not be
|
|
||||||
* able to load it into BCEL).
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.Repository
|
|
||||||
*/
|
|
||||||
public VerificationResult do_verify(){
|
|
||||||
JavaClass jc;
|
|
||||||
try{
|
|
||||||
jc = getJavaClass(); //loads in the class file if not already done.
|
|
||||||
|
|
||||||
if (jc != null){
|
|
||||||
/* If we find more constraints to check, we should do this in an own method. */
|
|
||||||
if (! myOwner.getClassName().equals(jc.getClassName())){
|
|
||||||
// This should maybe caught by BCEL: In case of renamed .class files we get wrong
|
|
||||||
// JavaClass objects here.
|
|
||||||
throw new LoadingException("Wrong name: the internal name of the .class file '"+jc.getClassName()+"' does not match the file's name '"+myOwner.getClassName()+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(LoadingException e){
|
|
||||||
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, e.getMessage());
|
|
||||||
}
|
|
||||||
catch(ClassFormatException e){
|
|
||||||
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, e.getMessage());
|
|
||||||
}
|
|
||||||
catch(RuntimeException e){
|
|
||||||
// BCEL does not catch every possible RuntimeException; e.g. if
|
|
||||||
// a constant pool index is referenced that does not exist.
|
|
||||||
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Parsing via BCEL did not succeed. "+e.getClass().getName()+" occured:\n"+Utility.getStackTrace(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jc != null){
|
|
||||||
return VerificationResult.VR_OK;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//TODO: Maybe change Repository's behaviour to throw a LoadingException instead of just returning "null"
|
|
||||||
// if a class file cannot be found or in another way be looked up.
|
|
||||||
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, "Repository.lookup() failed. FILE NOT FOUND?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently this returns an empty array of String.
|
|
||||||
* One could parse the error messages of BCEL
|
|
||||||
* (written to java.lang.System.err) when loading
|
|
||||||
* a class file such as detecting unknown attributes
|
|
||||||
* or trailing garbage at the end of a class file.
|
|
||||||
* However, Markus Dahm does not like the idea so this
|
|
||||||
* method is currently useless and therefore marked as
|
|
||||||
* <B>TODO</B>.
|
|
||||||
*/
|
|
||||||
public String[] getMessages(){
|
|
||||||
// This method is only here to override the javadoc-comment.
|
|
||||||
return super.getMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,249 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.statics;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.classfile.Code;
|
|
||||||
import org.apache.bcel.classfile.CodeException;
|
|
||||||
import org.apache.bcel.classfile.ConstantClass;
|
|
||||||
import org.apache.bcel.classfile.ConstantDouble;
|
|
||||||
import org.apache.bcel.classfile.ConstantFieldref;
|
|
||||||
import org.apache.bcel.classfile.ConstantFloat;
|
|
||||||
import org.apache.bcel.classfile.ConstantInteger;
|
|
||||||
import org.apache.bcel.classfile.ConstantInterfaceMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantLong;
|
|
||||||
import org.apache.bcel.classfile.ConstantMethodref;
|
|
||||||
import org.apache.bcel.classfile.ConstantNameAndType;
|
|
||||||
import org.apache.bcel.classfile.ConstantPool;
|
|
||||||
import org.apache.bcel.classfile.ConstantString;
|
|
||||||
import org.apache.bcel.classfile.ConstantUtf8;
|
|
||||||
import org.apache.bcel.classfile.ConstantValue;
|
|
||||||
import org.apache.bcel.classfile.Deprecated;
|
|
||||||
import org.apache.bcel.classfile.ExceptionTable;
|
|
||||||
import org.apache.bcel.classfile.Field;
|
|
||||||
import org.apache.bcel.classfile.InnerClass;
|
|
||||||
import org.apache.bcel.classfile.InnerClasses;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.classfile.LineNumber;
|
|
||||||
import org.apache.bcel.classfile.LineNumberTable;
|
|
||||||
import org.apache.bcel.classfile.LocalVariable;
|
|
||||||
import org.apache.bcel.classfile.LocalVariableTable;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.classfile.Node;
|
|
||||||
import org.apache.bcel.classfile.Signature;
|
|
||||||
import org.apache.bcel.classfile.SourceFile;
|
|
||||||
import org.apache.bcel.classfile.StackMap;
|
|
||||||
import org.apache.bcel.classfile.Synthetic;
|
|
||||||
import org.apache.bcel.classfile.Unknown;
|
|
||||||
import org.apache.bcel.classfile.Visitor;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BCEL's Node classes (those from the classfile API that <B>accept()</B> Visitor
|
|
||||||
* instances) have <B>toString()</B> methods that were not designed to be robust,
|
|
||||||
* this gap is closed by this class.
|
|
||||||
* When performing class file verification, it may be useful to output which
|
|
||||||
* entity (e.g. a <B>Code</B> instance) is not satisfying the verifier's
|
|
||||||
* constraints, but in this case it could be possible for the <B>toString()</B>
|
|
||||||
* method to throw a RuntimeException.
|
|
||||||
* A (new StringRepresentation(Node n)).toString() never throws any exception.
|
|
||||||
* Note that this class also serves as a placeholder for more sophisticated message
|
|
||||||
* handling in future versions of JustIce.
|
|
||||||
*
|
|
||||||
* @version $Id: StringRepresentation.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class StringRepresentation extends org.apache.bcel.classfile.EmptyVisitor implements Visitor {
|
|
||||||
/** The string representation, created by a visitXXX() method, output by toString(). */
|
|
||||||
private String tostring;
|
|
||||||
/** The node we ask for its string representation. Not really needed; only for debug output. */
|
|
||||||
private Node n;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new StringRepresentation object which is the representation of n.
|
|
||||||
*
|
|
||||||
* @see #toString()
|
|
||||||
*/
|
|
||||||
public StringRepresentation(Node n) {
|
|
||||||
this.n = n;
|
|
||||||
n.accept(this); // assign a string representation to field 'tostring' if we know n's class.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the String representation.
|
|
||||||
*/
|
|
||||||
public String toString() {
|
|
||||||
// The run-time check below is needed because we don't want to omit inheritance
|
|
||||||
// of "EmptyVisitor" and provide a thousand empty methods.
|
|
||||||
// However, in terms of performance this would be a better idea.
|
|
||||||
// If some new "Node" is defined in BCEL (such as some concrete "Attribute"), we
|
|
||||||
// want to know that this class has also to be adapted.
|
|
||||||
if (tostring == null) {
|
|
||||||
throw new AssertionViolatedException("Please adapt '" + getClass() + "' to deal with objects of class '" + n.getClass() + "'.");
|
|
||||||
}
|
|
||||||
return tostring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the String representation of the Node object obj;
|
|
||||||
* this is obj.toString() if it does not throw any RuntimeException,
|
|
||||||
* or else it is a string derived only from obj's class name.
|
|
||||||
*/
|
|
||||||
private String toString(Node obj) {
|
|
||||||
String ret;
|
|
||||||
try {
|
|
||||||
ret = obj.toString();
|
|
||||||
}
|
|
||||||
catch (RuntimeException e) { // including ClassFormatException, trying to convert the "signature" of a ReturnaddressType LocalVariable (shouldn't occur, but people do crazy things)
|
|
||||||
String s = obj.getClass().getName();
|
|
||||||
s = s.substring(s.lastIndexOf(".") + 1);
|
|
||||||
ret = "<<" + s + ">>";
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Visitor methods start here //
|
|
||||||
////////////////////////////////
|
|
||||||
// We don't of course need to call some default implementation:
|
|
||||||
// e.g. we could also simply output "Code" instead of a possibly
|
|
||||||
// lengthy Code attribute's toString().
|
|
||||||
public void visitCode(Code obj) {
|
|
||||||
//tostring = toString(obj);
|
|
||||||
tostring = "<CODE>"; // We don't need real code outputs.
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitCodeException(CodeException obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantClass(ConstantClass obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantDouble(ConstantDouble obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantFieldref(ConstantFieldref obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantFloat(ConstantFloat obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantInteger(ConstantInteger obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantInterfaceMethodref(ConstantInterfaceMethodref obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantLong(ConstantLong obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantMethodref(ConstantMethodref obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantNameAndType(ConstantNameAndType obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantPool(ConstantPool obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantString(ConstantString obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantUtf8(ConstantUtf8 obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitConstantValue(ConstantValue obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitDeprecated(Deprecated obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitExceptionTable(ExceptionTable obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitField(Field obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitInnerClass(InnerClass obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitInnerClasses(InnerClasses obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitJavaClass(JavaClass obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLineNumber(LineNumber obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLineNumberTable(LineNumberTable obj) {
|
|
||||||
tostring = "<LineNumberTable: " + toString(obj) + ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLocalVariable(LocalVariable obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitLocalVariableTable(LocalVariableTable obj) {
|
|
||||||
tostring = "<LocalVariableTable: " + toString(obj) + ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitMethod(Method obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitSignature(Signature obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitSourceFile(SourceFile obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitStackMap(StackMap obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitSynthetic(Synthetic obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitUnknown(Unknown obj) {
|
|
||||||
tostring = toString(obj);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
|
||||||
$Id: package.html 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
-->
|
|
||||||
</head>
|
|
||||||
<body bgcolor="white">
|
|
||||||
|
|
||||||
Provides PassVerifier classes used internally by JustIce. You don't need to bother with them.
|
|
||||||
|
|
||||||
<h2>Package Specification</h2>
|
|
||||||
|
|
||||||
Contained in this package are PassVerifier classes for use with the JustIce verifier.
|
|
||||||
Only the passes performing what Sun calls 'static constraints' have PassVerifier classes
|
|
||||||
here.
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,460 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.bcel.generic.ATHROW;
|
|
||||||
import org.apache.bcel.generic.BranchInstruction;
|
|
||||||
import org.apache.bcel.generic.GotoInstruction;
|
|
||||||
import org.apache.bcel.generic.Instruction;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.JsrInstruction;
|
|
||||||
import org.apache.bcel.generic.MethodGen;
|
|
||||||
import org.apache.bcel.generic.RET;
|
|
||||||
import org.apache.bcel.generic.ReturnInstruction;
|
|
||||||
import org.apache.bcel.generic.Select;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents a control flow graph of a method.
|
|
||||||
*
|
|
||||||
* @version $Id: ControlFlowGraph.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class ControlFlowGraph{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Objects of this class represent a node in a ControlFlowGraph.
|
|
||||||
* These nodes are instructions, not basic blocks.
|
|
||||||
*/
|
|
||||||
private class InstructionContextImpl implements InstructionContext{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The TAG field is here for external temporary flagging, such
|
|
||||||
* as graph colouring.
|
|
||||||
*
|
|
||||||
* @see #getTag()
|
|
||||||
* @see #setTag(int)
|
|
||||||
*/
|
|
||||||
private int TAG;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The InstructionHandle this InstructionContext is wrapped around.
|
|
||||||
*/
|
|
||||||
private InstructionHandle instruction;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The 'incoming' execution Frames.
|
|
||||||
*/
|
|
||||||
private Map inFrames; // key: the last-executed JSR
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The 'outgoing' execution Frames.
|
|
||||||
*/
|
|
||||||
private Map outFrames; // key: the last-executed JSR
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The 'execution predecessors' - a list of type InstructionContext
|
|
||||||
* of those instances that have been execute()d before in that order.
|
|
||||||
*/
|
|
||||||
private ArrayList executionPredecessors = null; // Type: InstructionContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an InstructionHandleImpl object from an InstructionHandle.
|
|
||||||
* Creation of one per InstructionHandle suffices. Don't create more.
|
|
||||||
*/
|
|
||||||
public InstructionContextImpl(InstructionHandle inst){
|
|
||||||
if (inst == null) {
|
|
||||||
throw new AssertionViolatedException("Cannot instantiate InstructionContextImpl from NULL.");
|
|
||||||
}
|
|
||||||
|
|
||||||
instruction = inst;
|
|
||||||
inFrames = new java.util.HashMap();
|
|
||||||
outFrames = new java.util.HashMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Satisfies InstructionContext.getTag(). */
|
|
||||||
public int getTag(){
|
|
||||||
return TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Satisfies InstructionContext.setTag(int). */
|
|
||||||
public void setTag(int tag){
|
|
||||||
TAG = tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the exception handlers of this instruction.
|
|
||||||
*/
|
|
||||||
public ExceptionHandler[] getExceptionHandlers(){
|
|
||||||
return exceptionhandlers.getExceptionHandlers(getInstruction());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a clone of the "outgoing" frame situation with respect to the given ExecutionChain.
|
|
||||||
*/
|
|
||||||
public Frame getOutFrame(ArrayList execChain){
|
|
||||||
executionPredecessors = execChain;
|
|
||||||
|
|
||||||
Frame org;
|
|
||||||
|
|
||||||
InstructionContext jsr = lastExecutionJSR();
|
|
||||||
|
|
||||||
org = (Frame) outFrames.get(jsr);
|
|
||||||
|
|
||||||
if (org == null){
|
|
||||||
throw new AssertionViolatedException("outFrame not set! This:\n"+this+"\nExecutionChain: "+getExecutionChain()+"\nOutFrames: '"+outFrames+"'.");
|
|
||||||
}
|
|
||||||
return org.getClone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Frame getInFrame() {
|
|
||||||
Frame org;
|
|
||||||
|
|
||||||
InstructionContext jsr = lastExecutionJSR();
|
|
||||||
|
|
||||||
org = (Frame) inFrames.get(jsr);
|
|
||||||
|
|
||||||
if (org == null){
|
|
||||||
throw new AssertionViolatedException("inFrame not set! This:\n"+this+"\nInFrames: '"+inFrames+"'.");
|
|
||||||
}
|
|
||||||
return org.getClone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "Merges in" (vmspec2, page 146) the "incoming" frame situation;
|
|
||||||
* executes the instructions symbolically
|
|
||||||
* and therefore calculates the "outgoing" frame situation.
|
|
||||||
* Returns: True iff the "incoming" frame situation changed after
|
|
||||||
* merging with "inFrame".
|
|
||||||
* The execPreds ArrayList must contain the InstructionContext
|
|
||||||
* objects executed so far in the correct order. This is just
|
|
||||||
* one execution path [out of many]. This is needed to correctly
|
|
||||||
* "merge" in the special case of a RET's successor.
|
|
||||||
* <B>The InstConstraintVisitor and ExecutionVisitor instances
|
|
||||||
* must be set up correctly.</B>
|
|
||||||
* @return true - if and only if the "outgoing" frame situation
|
|
||||||
* changed from the one before execute()ing.
|
|
||||||
*/
|
|
||||||
public boolean execute(Frame inFrame, ArrayList execPreds, InstConstraintVisitor icv, ExecutionVisitor ev){
|
|
||||||
|
|
||||||
executionPredecessors = (ArrayList) execPreds.clone();
|
|
||||||
|
|
||||||
//sanity check
|
|
||||||
if ( (lastExecutionJSR() == null) && (subroutines.subroutineOf(getInstruction()) != subroutines.getTopLevel() ) ){
|
|
||||||
throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
|
|
||||||
}
|
|
||||||
if ( (lastExecutionJSR() != null) && (subroutines.subroutineOf(getInstruction()) == subroutines.getTopLevel() ) ){
|
|
||||||
throw new AssertionViolatedException("Huh?! Am I '"+this+"' part of a subroutine or not?");
|
|
||||||
}
|
|
||||||
|
|
||||||
Frame inF = (Frame) inFrames.get(lastExecutionJSR());
|
|
||||||
if (inF == null){// no incoming frame was set, so set it.
|
|
||||||
inFrames.put(lastExecutionJSR(), inFrame);
|
|
||||||
inF = inFrame;
|
|
||||||
}
|
|
||||||
else{// if there was an "old" inFrame
|
|
||||||
if (inF.equals(inFrame)){ //shortcut: no need to merge equal frames.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (! mergeInFrames(inFrame)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we're sure the inFrame has changed!
|
|
||||||
|
|
||||||
// new inFrame is already merged in, see above.
|
|
||||||
Frame workingFrame = inF.getClone();
|
|
||||||
|
|
||||||
try{
|
|
||||||
// This verifies the InstructionConstraint for the current
|
|
||||||
// instruction, but does not modify the workingFrame object.
|
|
||||||
//InstConstraintVisitor icv = InstConstraintVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
|
|
||||||
icv.setFrame(workingFrame);
|
|
||||||
getInstruction().accept(icv);
|
|
||||||
}
|
|
||||||
catch(StructuralCodeConstraintException ce){
|
|
||||||
ce.extendMessage("","\nInstructionHandle: "+getInstruction()+"\n");
|
|
||||||
ce.extendMessage("","\nExecution Frame:\n"+workingFrame);
|
|
||||||
extendMessageWithFlow(ce);
|
|
||||||
throw ce;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This executes the Instruction.
|
|
||||||
// Therefore the workingFrame object is modified.
|
|
||||||
//ExecutionVisitor ev = ExecutionVisitor.getInstance(VerifierFactory.getVerifier(method_gen.getClassName()));
|
|
||||||
ev.setFrame(workingFrame);
|
|
||||||
getInstruction().accept(ev);
|
|
||||||
//getInstruction().accept(ExecutionVisitor.withFrame(workingFrame));
|
|
||||||
outFrames.put(lastExecutionJSR(), workingFrame);
|
|
||||||
|
|
||||||
return true; // new inFrame was different from old inFrame so merging them
|
|
||||||
// yielded a different this.inFrame.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a simple String representation of this InstructionContext.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
//TODO: Put information in the brackets, e.g.
|
|
||||||
// Is this an ExceptionHandler? Is this a RET? Is this the start of
|
|
||||||
// a subroutine?
|
|
||||||
String ret = getInstruction().toString(false)+"\t[InstructionContext]";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does the actual merging (vmspec2, page 146).
|
|
||||||
* Returns true IFF this.inFrame was changed in course of merging with inFrame.
|
|
||||||
*/
|
|
||||||
private boolean mergeInFrames(Frame inFrame){
|
|
||||||
// TODO: Can be performance-improved.
|
|
||||||
Frame inF = (Frame) inFrames.get(lastExecutionJSR());
|
|
||||||
OperandStack oldstack = inF.getStack().getClone();
|
|
||||||
LocalVariables oldlocals = inF.getLocals().getClone();
|
|
||||||
try{
|
|
||||||
inF.getStack().merge(inFrame.getStack());
|
|
||||||
inF.getLocals().merge(inFrame.getLocals());
|
|
||||||
}
|
|
||||||
catch (StructuralCodeConstraintException sce){
|
|
||||||
extendMessageWithFlow(sce);
|
|
||||||
throw sce;
|
|
||||||
}
|
|
||||||
if ( oldstack.equals(inF.getStack()) &&
|
|
||||||
oldlocals.equals(inF.getLocals()) ){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the control flow execution chain. This is built
|
|
||||||
* while execute(Frame, ArrayList)-ing the code represented
|
|
||||||
* by the surrounding ControlFlowGraph.
|
|
||||||
*/
|
|
||||||
private String getExecutionChain(){
|
|
||||||
String s = this.toString();
|
|
||||||
for (int i=executionPredecessors.size()-1; i>=0; i--){
|
|
||||||
s = executionPredecessors.get(i)+"\n" + s;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extends the StructuralCodeConstraintException ("e") object with an at-the-end-extended message.
|
|
||||||
* This extended message will then reflect the execution flow needed to get to the constraint
|
|
||||||
* violation that triggered the throwing of the "e" object.
|
|
||||||
*/
|
|
||||||
private void extendMessageWithFlow(StructuralCodeConstraintException e){
|
|
||||||
String s = "Execution flow:\n";
|
|
||||||
e.extendMessage("", s+getExecutionChain());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fulfils the contract of InstructionContext.getInstruction().
|
|
||||||
*/
|
|
||||||
public InstructionHandle getInstruction(){
|
|
||||||
return instruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the InstructionContextImpl with an JSR/JSR_W
|
|
||||||
* that was last in the ExecutionChain, without
|
|
||||||
* a corresponding RET, i.e.
|
|
||||||
* we were called by this one.
|
|
||||||
* Returns null if we were called from the top level.
|
|
||||||
*/
|
|
||||||
private InstructionContextImpl lastExecutionJSR(){
|
|
||||||
|
|
||||||
int size = executionPredecessors.size();
|
|
||||||
int retcount = 0;
|
|
||||||
|
|
||||||
for (int i=size-1; i>=0; i--){
|
|
||||||
InstructionContextImpl current = (InstructionContextImpl) (executionPredecessors.get(i));
|
|
||||||
Instruction currentlast = current.getInstruction().getInstruction();
|
|
||||||
if (currentlast instanceof RET) {
|
|
||||||
retcount++;
|
|
||||||
}
|
|
||||||
if (currentlast instanceof JsrInstruction){
|
|
||||||
retcount--;
|
|
||||||
if (retcount == -1) {
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Satisfies InstructionContext.getSuccessors(). */
|
|
||||||
public InstructionContext[] getSuccessors(){
|
|
||||||
return contextsOf(_getSuccessors());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility method that calculates the successors of a given InstructionHandle
|
|
||||||
* That means, a RET does have successors as defined here.
|
|
||||||
* A JsrInstruction has its target as its successor
|
|
||||||
* (opposed to its physical successor) as defined here.
|
|
||||||
*/
|
|
||||||
// TODO: implement caching!
|
|
||||||
private InstructionHandle[] _getSuccessors(){
|
|
||||||
final InstructionHandle[] empty = new InstructionHandle[0];
|
|
||||||
final InstructionHandle[] single = new InstructionHandle[1];
|
|
||||||
final InstructionHandle[] pair = new InstructionHandle[2];
|
|
||||||
|
|
||||||
Instruction inst = getInstruction().getInstruction();
|
|
||||||
|
|
||||||
if (inst instanceof RET){
|
|
||||||
Subroutine s = subroutines.subroutineOf(getInstruction());
|
|
||||||
if (s==null){ //return empty; // RET in dead code. "empty" would be the correct answer, but we know something about the surrounding project...
|
|
||||||
throw new AssertionViolatedException("Asking for successors of a RET in dead code?!");
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: remove. Only JustIce must not use it, but foreign users of the ControlFlowGraph
|
|
||||||
// will want it. Thanks Johannes Wust.
|
|
||||||
//throw new AssertionViolatedException("DID YOU REALLY WANT TO ASK FOR RET'S SUCCS?");
|
|
||||||
|
|
||||||
InstructionHandle[] jsrs = s.getEnteringJsrInstructions();
|
|
||||||
InstructionHandle[] ret = new InstructionHandle[jsrs.length];
|
|
||||||
for (int i=0; i<jsrs.length; i++){
|
|
||||||
ret[i] = jsrs[i].getNext();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminates method normally.
|
|
||||||
if (inst instanceof ReturnInstruction){
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminates method abnormally, because JustIce mandates
|
|
||||||
// subroutines not to be protected by exception handlers.
|
|
||||||
if (inst instanceof ATHROW){
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See method comment.
|
|
||||||
if (inst instanceof JsrInstruction){
|
|
||||||
single[0] = ((JsrInstruction) inst).getTarget();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inst instanceof GotoInstruction){
|
|
||||||
single[0] = ((GotoInstruction) inst).getTarget();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inst instanceof BranchInstruction){
|
|
||||||
if (inst instanceof Select){
|
|
||||||
// BCEL's getTargets() returns only the non-default targets,
|
|
||||||
// thanks to Eli Tilevich for reporting.
|
|
||||||
InstructionHandle[] matchTargets = ((Select) inst).getTargets();
|
|
||||||
InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
|
|
||||||
ret[0] = ((Select) inst).getTarget();
|
|
||||||
System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
pair[0] = getInstruction().getNext();
|
|
||||||
pair[1] = ((BranchInstruction) inst).getTarget();
|
|
||||||
return pair;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// default case: Fall through.
|
|
||||||
single[0] = getInstruction().getNext();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End Inner InstructionContextImpl Class.
|
|
||||||
|
|
||||||
/** The MethodGen object we're working on. */
|
|
||||||
private final MethodGen method_gen;
|
|
||||||
|
|
||||||
/** The Subroutines object for the method whose control flow is represented by this ControlFlowGraph. */
|
|
||||||
private final Subroutines subroutines;
|
|
||||||
|
|
||||||
/** The ExceptionHandlers object for the method whose control flow is represented by this ControlFlowGraph. */
|
|
||||||
private final ExceptionHandlers exceptionhandlers;
|
|
||||||
|
|
||||||
/** All InstructionContext instances of this ControlFlowGraph. */
|
|
||||||
private Hashtable instructionContexts = new Hashtable(); //keys: InstructionHandle, values: InstructionContextImpl
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Control Flow Graph.
|
|
||||||
*/
|
|
||||||
public ControlFlowGraph(MethodGen method_gen){
|
|
||||||
subroutines = new Subroutines(method_gen);
|
|
||||||
exceptionhandlers = new ExceptionHandlers(method_gen);
|
|
||||||
|
|
||||||
InstructionHandle[] instructionhandles = method_gen.getInstructionList().getInstructionHandles();
|
|
||||||
for (int i=0; i<instructionhandles.length; i++){
|
|
||||||
instructionContexts.put(instructionhandles[i], new InstructionContextImpl(instructionhandles[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.method_gen = method_gen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the InstructionContext of a given instruction.
|
|
||||||
*/
|
|
||||||
public InstructionContext contextOf(InstructionHandle inst){
|
|
||||||
InstructionContext ic = (InstructionContext) instructionContexts.get(inst);
|
|
||||||
if (ic == null){
|
|
||||||
throw new AssertionViolatedException("InstructionContext requested for an InstructionHandle that's not known!");
|
|
||||||
}
|
|
||||||
return ic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the InstructionContext[] of a given InstructionHandle[],
|
|
||||||
* in a naturally ordered manner.
|
|
||||||
*/
|
|
||||||
public InstructionContext[] contextsOf(InstructionHandle[] insts){
|
|
||||||
InstructionContext[] ret = new InstructionContext[insts.length];
|
|
||||||
for (int i=0; i<insts.length; i++){
|
|
||||||
ret[i] = contextOf(insts[i]);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an InstructionContext[] with all the InstructionContext instances
|
|
||||||
* for the method whose control flow is represented by this ControlFlowGraph
|
|
||||||
* <B>(NOT ORDERED!)</B>.
|
|
||||||
*/
|
|
||||||
public InstructionContext[] getInstructionContexts(){
|
|
||||||
InstructionContext[] ret = new InstructionContext[instructionContexts.values().size()];
|
|
||||||
return (InstructionContext[]) instructionContexts.values().toArray(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if and only if the said instruction is not reachable; that means,
|
|
||||||
* if it is not part of this ControlFlowGraph.
|
|
||||||
*/
|
|
||||||
public boolean isDead(InstructionHandle i){
|
|
||||||
return subroutines.subroutineOf(i) == null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.ObjectType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents an exception handler; that is, an ObjectType
|
|
||||||
* representing a subclass of java.lang.Throwable and the instruction
|
|
||||||
* the handler starts off (represented by an InstructionContext).
|
|
||||||
*
|
|
||||||
* @version $Id: ExceptionHandler.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class ExceptionHandler{
|
|
||||||
/** The type of the exception to catch. NULL means ANY. */
|
|
||||||
private ObjectType catchtype;
|
|
||||||
|
|
||||||
/** The InstructionHandle where the handling begins. */
|
|
||||||
private InstructionHandle handlerpc;
|
|
||||||
|
|
||||||
/** Leave instance creation to JustIce. */
|
|
||||||
ExceptionHandler(ObjectType catch_type, InstructionHandle handler_pc){
|
|
||||||
catchtype = catch_type;
|
|
||||||
handlerpc = handler_pc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the exception that's handled. <B>'null' means 'ANY'.</B>
|
|
||||||
*/
|
|
||||||
public ObjectType getExceptionType(){
|
|
||||||
return catchtype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the InstructionHandle where the handler starts off.
|
|
||||||
*/
|
|
||||||
public InstructionHandle getHandlerStart(){
|
|
||||||
return handlerpc;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.apache.bcel.generic.CodeExceptionGen;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.MethodGen;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class allows easy access to ExceptionHandler objects.
|
|
||||||
*
|
|
||||||
* @version $Id: ExceptionHandlers.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class ExceptionHandlers{
|
|
||||||
/**
|
|
||||||
* The ExceptionHandler instances.
|
|
||||||
* Key: InstructionHandle objects, Values: HashSet<ExceptionHandler> instances.
|
|
||||||
*/
|
|
||||||
private Hashtable exceptionhandlers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor. Creates a new ExceptionHandlers instance.
|
|
||||||
*/
|
|
||||||
public ExceptionHandlers(MethodGen mg){
|
|
||||||
exceptionhandlers = new Hashtable();
|
|
||||||
CodeExceptionGen[] cegs = mg.getExceptionHandlers();
|
|
||||||
for (int i=0; i<cegs.length; i++){
|
|
||||||
ExceptionHandler eh = new ExceptionHandler(cegs[i].getCatchType(), cegs[i].getHandlerPC());
|
|
||||||
for (InstructionHandle ih=cegs[i].getStartPC(); ih != cegs[i].getEndPC().getNext(); ih=ih.getNext()){
|
|
||||||
Set hs;
|
|
||||||
hs = (Set) exceptionhandlers.get(ih);
|
|
||||||
if (hs == null){
|
|
||||||
hs = new HashSet();
|
|
||||||
exceptionhandlers.put(ih, hs);
|
|
||||||
}
|
|
||||||
hs.add(eh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all the ExceptionHandler instances representing exception
|
|
||||||
* handlers that protect the instruction ih.
|
|
||||||
*/
|
|
||||||
public ExceptionHandler[] getExceptionHandlers(InstructionHandle ih){
|
|
||||||
Set hs = (Set) exceptionhandlers.get(ih);
|
|
||||||
if (hs == null) {
|
|
||||||
return new ExceptionHandler[0];
|
|
||||||
} else{
|
|
||||||
ExceptionHandler[] ret = new ExceptionHandler[hs.size()];
|
|
||||||
return (ExceptionHandler[]) (hs.toArray(ret));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents a JVM execution frame; that means,
|
|
||||||
* a local variable array and an operand stack.
|
|
||||||
*
|
|
||||||
* @version $Id: Frame.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Frame{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For instance initialization methods, it is important to remember
|
|
||||||
* which instance it is that is not initialized yet. It will be
|
|
||||||
* initialized invoking another constructor later.
|
|
||||||
* NULL means the instance already *is* initialized.
|
|
||||||
*/
|
|
||||||
protected static UninitializedObjectType _this;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private LocalVariables locals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private OperandStack stack;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Frame(int maxLocals, int maxStack){
|
|
||||||
locals = new LocalVariables(maxLocals);
|
|
||||||
stack = new OperandStack(maxStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Frame(LocalVariables locals, OperandStack stack){
|
|
||||||
this.locals = locals;
|
|
||||||
this.stack = stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected Object clone(){
|
|
||||||
Frame f = new Frame(locals.getClone(), stack.getClone());
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Frame getClone(){
|
|
||||||
return (Frame) clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public LocalVariables getLocals(){
|
|
||||||
return locals;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public OperandStack getStack(){
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a hash code value for the object.
|
|
||||||
*/
|
|
||||||
public int hashCode() { return stack.hashCode() ^ locals.hashCode(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public boolean equals(Object o){
|
|
||||||
if (!(o instanceof Frame)) {
|
|
||||||
return false; // implies "null" is non-equal.
|
|
||||||
}
|
|
||||||
Frame f = (Frame) o;
|
|
||||||
return this.stack.equals(f.stack) && this.locals.equals(f.locals);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of the Frame instance.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
String s="Local Variables:\n";
|
|
||||||
s += locals;
|
|
||||||
s += "OperandStack:\n";
|
|
||||||
s += stack;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder class that can be used to create an ObjectType of which
|
|
||||||
* has some of the properties arrays have. They implement java.lang.Cloneable
|
|
||||||
* and java.io.Serializable and they extend java.lang.Object.
|
|
||||||
*
|
|
||||||
* @version $Id: GenericArray.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class GenericArray extends java.lang.Object implements java.lang.Cloneable, java.io.Serializable{
|
|
||||||
|
|
||||||
protected Object clone() throws CloneNotSupportedException {
|
|
||||||
return super.clone();
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An InstructionContext offers convenient access
|
|
||||||
* to information like control flow successors and
|
|
||||||
* such.
|
|
||||||
*
|
|
||||||
* @version $Id: InstructionContext.java 382272 2006-03-02 03:31:46Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public interface InstructionContext{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The getTag and setTag methods may be used for
|
|
||||||
* temporary flagging, such as graph colouring.
|
|
||||||
* Nothing in the InstructionContext object depends
|
|
||||||
* on the value of the tag. JustIce does not use it.
|
|
||||||
*
|
|
||||||
* @see #setTag(int tag)
|
|
||||||
*/
|
|
||||||
public int getTag();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The getTag and setTag methods may be used for
|
|
||||||
* temporary flagging, such as graph colouring.
|
|
||||||
* Nothing in the InstructionContext object depends
|
|
||||||
* on the value of the tag. JustIce does not use it.
|
|
||||||
*
|
|
||||||
* @see #getTag()
|
|
||||||
*/
|
|
||||||
public void setTag(int tag);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method symbolically executes the Instruction
|
|
||||||
* held in the InstructionContext.
|
|
||||||
* It "merges in" the incoming execution frame situation
|
|
||||||
* (see The Java Virtual Machine Specification, 2nd
|
|
||||||
* edition, page 146).
|
|
||||||
* By so doing, the outgoing execution frame situation
|
|
||||||
* is calculated.
|
|
||||||
*
|
|
||||||
* This method is JustIce-specific and is usually of
|
|
||||||
* no sense for users of the ControlFlowGraph class.
|
|
||||||
* They should use getInstruction().accept(Visitor),
|
|
||||||
* possibly in conjunction with the ExecutionVisitor.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @see ControlFlowGraph
|
|
||||||
* @see ExecutionVisitor
|
|
||||||
* @see #getOutFrame(ArrayList)
|
|
||||||
* @return true - if and only if the "outgoing" frame situation
|
|
||||||
* changed from the one before execute()ing.
|
|
||||||
*/
|
|
||||||
boolean execute(Frame inFrame, ArrayList executionPredecessors, InstConstraintVisitor icv, ExecutionVisitor ev);
|
|
||||||
|
|
||||||
Frame getInFrame();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the outgoing execution frame situation;
|
|
||||||
* therefore <B>it has to be calculated by execute(Frame, ArrayList)
|
|
||||||
* first.</B>
|
|
||||||
*
|
|
||||||
* @see #execute(Frame, ArrayList, InstConstraintVisitor, ExecutionVisitor)
|
|
||||||
*/
|
|
||||||
Frame getOutFrame(ArrayList executionPredecessors);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the InstructionHandle this InstructionContext is wrapped around.
|
|
||||||
*
|
|
||||||
* @return The InstructionHandle this InstructionContext is wrapped around.
|
|
||||||
*/
|
|
||||||
InstructionHandle getInstruction();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the usual control flow successors.
|
|
||||||
* @see #getExceptionHandlers()
|
|
||||||
*/
|
|
||||||
InstructionContext[] getSuccessors();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the exception handlers that protect this instruction.
|
|
||||||
* They are special control flow successors.
|
|
||||||
*/
|
|
||||||
ExceptionHandler[] getExceptionHandlers();
|
|
||||||
}
|
|
@ -1,209 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.generic.ReferenceType;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements an array of local variables used for symbolic JVM
|
|
||||||
* simulation.
|
|
||||||
*
|
|
||||||
* @version $Id: LocalVariables.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class LocalVariables{
|
|
||||||
/** The Type[] containing the local variable slots. */
|
|
||||||
private Type[] locals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new LocalVariables object.
|
|
||||||
*/
|
|
||||||
public LocalVariables(int maxLocals){
|
|
||||||
locals = new Type[maxLocals];
|
|
||||||
for (int i=0; i<maxLocals; i++){
|
|
||||||
locals[i] = Type.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a deep copy of this object; i.e. the clone
|
|
||||||
* operates on a new local variable array.
|
|
||||||
* However, the Type objects in the array are shared.
|
|
||||||
*/
|
|
||||||
protected Object clone(){
|
|
||||||
LocalVariables lvs = new LocalVariables(locals.length);
|
|
||||||
for (int i=0; i<locals.length; i++){
|
|
||||||
lvs.locals[i] = this.locals[i];
|
|
||||||
}
|
|
||||||
return lvs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of the local variable slot i.
|
|
||||||
*/
|
|
||||||
public Type get(int i){
|
|
||||||
return locals[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a (correctly typed) clone of this object.
|
|
||||||
* This is equivalent to ((LocalVariables) this.clone()).
|
|
||||||
*/
|
|
||||||
public LocalVariables getClone(){
|
|
||||||
return (LocalVariables) this.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of local variable slots this
|
|
||||||
* LocalVariables instance has.
|
|
||||||
*/
|
|
||||||
public int maxLocals(){
|
|
||||||
return locals.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a new Type for the given local variable slot.
|
|
||||||
*/
|
|
||||||
public void set(int i, Type type){
|
|
||||||
if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){
|
|
||||||
throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead.");
|
|
||||||
}
|
|
||||||
locals[i] = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a hash code value for the object.
|
|
||||||
*/
|
|
||||||
public int hashCode() { return locals.length; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fulfills the general contract of Object.equals().
|
|
||||||
*/
|
|
||||||
public boolean equals(Object o){
|
|
||||||
if (!(o instanceof LocalVariables)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LocalVariables lv = (LocalVariables) o;
|
|
||||||
if (this.locals.length != lv.locals.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i=0; i<this.locals.length; i++){
|
|
||||||
if (!this.locals[i].equals(lv.locals[i])){
|
|
||||||
//System.out.println(this.locals[i]+" is not "+lv.locals[i]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges two local variables sets as described in the Java Virtual Machine Specification,
|
|
||||||
* Second Edition, section 4.9.2, page 146.
|
|
||||||
*/
|
|
||||||
public void merge(LocalVariables lv){
|
|
||||||
|
|
||||||
if (this.locals.length != lv.locals.length){
|
|
||||||
throw new AssertionViolatedException("Merging LocalVariables of different size?!? From different methods or what?!?");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<locals.length; i++){
|
|
||||||
merge(lv, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges a single local variable.
|
|
||||||
*
|
|
||||||
* @see #merge(LocalVariables)
|
|
||||||
*/
|
|
||||||
private void merge(LocalVariables lv, int i){
|
|
||||||
try {
|
|
||||||
|
|
||||||
// We won't accept an unitialized object if we know it was initialized;
|
|
||||||
// compare vmspec2, 4.9.4, last paragraph.
|
|
||||||
if ( (!(locals[i] instanceof UninitializedObjectType)) && (lv.locals[i] instanceof UninitializedObjectType) ){
|
|
||||||
throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
|
|
||||||
}
|
|
||||||
// Even harder, what about _different_ uninitialized object types?!
|
|
||||||
if ( (!(locals[i].equals(lv.locals[i]))) && (locals[i] instanceof UninitializedObjectType) && (lv.locals[i] instanceof UninitializedObjectType) ){
|
|
||||||
throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object in the local variables detected.");
|
|
||||||
}
|
|
||||||
// If we just didn't know that it was initialized, we have now learned.
|
|
||||||
if (locals[i] instanceof UninitializedObjectType){
|
|
||||||
if (! (lv.locals[i] instanceof UninitializedObjectType)){
|
|
||||||
locals[i] = ((UninitializedObjectType) locals[i]).getInitialized();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((locals[i] instanceof ReferenceType) && (lv.locals[i] instanceof ReferenceType)){
|
|
||||||
if (! locals[i].equals(lv.locals[i])){ // needed in case of two UninitializedObjectType instances
|
|
||||||
Type sup = ((ReferenceType) locals[i]).getFirstCommonSuperclass((ReferenceType) (lv.locals[i]));
|
|
||||||
|
|
||||||
if (sup != null){
|
|
||||||
locals[i] = sup;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// We should have checked this in Pass2!
|
|
||||||
throw new AssertionViolatedException("Could not load all the super classes of '"+locals[i]+"' and '"+lv.locals[i]+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if (! (locals[i].equals(lv.locals[i])) ){
|
|
||||||
/*TODO
|
|
||||||
if ((locals[i] instanceof org.apache.bcel.generic.ReturnaddressType) && (lv.locals[i] instanceof org.apache.bcel.generic.ReturnaddressType)){
|
|
||||||
//System.err.println("merging "+locals[i]+" and "+lv.locals[i]);
|
|
||||||
throw new AssertionViolatedException("Merging different ReturnAddresses: '"+locals[i]+"' and '"+lv.locals[i]+"'.");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
locals[i] = Type.UNKNOWN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// FIXME: maybe not the best way to handle this
|
|
||||||
throw new AssertionViolatedException("Missing class: " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of this object.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
for (int i=0; i<locals.length; i++){
|
|
||||||
sb.append(Integer.toString(i));
|
|
||||||
sb.append(": ");
|
|
||||||
sb.append(locals[i]);
|
|
||||||
sb.append("\n");
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces all occurences of u in this local variables set
|
|
||||||
* with an "initialized" ObjectType.
|
|
||||||
*/
|
|
||||||
public void initializeObject(UninitializedObjectType u){
|
|
||||||
for (int i=0; i<locals.length; i++){
|
|
||||||
if (locals[i] == u){
|
|
||||||
locals[i] = u.getInitialized();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,263 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import org.apache.bcel.generic.ObjectType;
|
|
||||||
import org.apache.bcel.generic.ReferenceType;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements a stack used for symbolic JVM stack simulation.
|
|
||||||
* [It's used an an operand stack substitute.]
|
|
||||||
* Elements of this stack are org.apache.bcel.generic.Type objects.
|
|
||||||
*
|
|
||||||
* @version $Id: OperandStack.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class OperandStack{
|
|
||||||
|
|
||||||
/** We hold the stack information here. */
|
|
||||||
private ArrayList stack = new ArrayList();
|
|
||||||
|
|
||||||
/** The maximum number of stack slots this OperandStack instance may hold. */
|
|
||||||
private int maxStack;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an empty stack with a maximum of maxStack slots.
|
|
||||||
*/
|
|
||||||
public OperandStack(int maxStack){
|
|
||||||
this.maxStack = maxStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an otherwise empty stack with a maximum of maxStack slots and
|
|
||||||
* the ObjectType 'obj' at the top.
|
|
||||||
*/
|
|
||||||
public OperandStack(int maxStack, ObjectType obj){
|
|
||||||
this.maxStack = maxStack;
|
|
||||||
this.push(obj);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Returns a deep copy of this object; that means, the clone operates
|
|
||||||
* on a new stack. However, the Type objects on the stack are
|
|
||||||
* shared.
|
|
||||||
*/
|
|
||||||
protected Object clone(){
|
|
||||||
OperandStack newstack = new OperandStack(this.maxStack);
|
|
||||||
newstack.stack = (ArrayList) this.stack.clone();
|
|
||||||
return newstack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the stack.
|
|
||||||
*/
|
|
||||||
public void clear(){
|
|
||||||
stack = new ArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a hash code value for the object.
|
|
||||||
*/
|
|
||||||
public int hashCode() { return stack.hashCode(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if and only if this OperandStack
|
|
||||||
* equals another, meaning equal lengths and equal
|
|
||||||
* objects on the stacks.
|
|
||||||
*/
|
|
||||||
public boolean equals(Object o){
|
|
||||||
if (!(o instanceof OperandStack)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
OperandStack s = (OperandStack) o;
|
|
||||||
return this.stack.equals(s.stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a (typed!) clone of this.
|
|
||||||
*
|
|
||||||
* @see #clone()
|
|
||||||
*/
|
|
||||||
public OperandStack getClone(){
|
|
||||||
return (OperandStack) this.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true IFF this OperandStack is empty.
|
|
||||||
*/
|
|
||||||
public boolean isEmpty(){
|
|
||||||
return stack.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of stack slots this stack can hold.
|
|
||||||
*/
|
|
||||||
public int maxStack(){
|
|
||||||
return this.maxStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the element on top of the stack. The element is not popped off the stack!
|
|
||||||
*/
|
|
||||||
public Type peek(){
|
|
||||||
return peek(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the element that's i elements below the top element; that means,
|
|
||||||
* iff i==0 the top element is returned. The element is not popped off the stack!
|
|
||||||
*/
|
|
||||||
public Type peek(int i){
|
|
||||||
return (Type) stack.get(size()-i-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the element on top of the stack. The element is popped off the stack.
|
|
||||||
*/
|
|
||||||
public Type pop(){
|
|
||||||
Type e = (Type) stack.remove(size()-1);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pops i elements off the stack. ALWAYS RETURNS "null"!!!
|
|
||||||
*/
|
|
||||||
public Type pop(int i){
|
|
||||||
for (int j=0; j<i; j++){
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pushes a Type object onto the stack.
|
|
||||||
*/
|
|
||||||
public void push(Type type){
|
|
||||||
if (type == null) {
|
|
||||||
throw new AssertionViolatedException("Cannot push NULL onto OperandStack.");
|
|
||||||
}
|
|
||||||
if (type == Type.BOOLEAN || type == Type.CHAR || type == Type.BYTE || type == Type.SHORT){
|
|
||||||
throw new AssertionViolatedException("The OperandStack does not know about '"+type+"'; use Type.INT instead.");
|
|
||||||
}
|
|
||||||
if (slotsUsed() >= maxStack){
|
|
||||||
throw new AssertionViolatedException("OperandStack too small, should have thrown proper Exception elsewhere. Stack: "+this);
|
|
||||||
}
|
|
||||||
stack.add(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the size of this OperandStack; that means, how many Type objects there are.
|
|
||||||
*/
|
|
||||||
public int size(){
|
|
||||||
return stack.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of stack slots used.
|
|
||||||
* @see #maxStack()
|
|
||||||
*/
|
|
||||||
public int slotsUsed(){
|
|
||||||
/* XXX change this to a better implementation using a variable
|
|
||||||
that keeps track of the actual slotsUsed()-value monitoring
|
|
||||||
all push()es and pop()s.
|
|
||||||
*/
|
|
||||||
int slots = 0;
|
|
||||||
for (int i=0; i<stack.size(); i++){
|
|
||||||
slots += peek(i).getSize();
|
|
||||||
}
|
|
||||||
return slots;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of this OperandStack instance.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
sb.append("Slots used: ");
|
|
||||||
sb.append(slotsUsed());
|
|
||||||
sb.append(" MaxStack: ");
|
|
||||||
sb.append(maxStack);
|
|
||||||
sb.append(".\n");
|
|
||||||
for (int i=0; i<size(); i++){
|
|
||||||
sb.append(peek(i));
|
|
||||||
sb.append(" (Size: ");
|
|
||||||
sb.append(String.valueOf(peek(i).getSize()));
|
|
||||||
sb.append(")\n");
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merges another stack state into this instance's stack state.
|
|
||||||
* See the Java Virtual Machine Specification, Second Edition, page 146: 4.9.2
|
|
||||||
* for details.
|
|
||||||
*/
|
|
||||||
public void merge(OperandStack s){
|
|
||||||
try {
|
|
||||||
if ( (slotsUsed() != s.slotsUsed()) || (size() != s.size()) ) {
|
|
||||||
throw new StructuralCodeConstraintException("Cannot merge stacks of different size:\nOperandStack A:\n"+this+"\nOperandStack B:\n"+s);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<size(); i++){
|
|
||||||
// If the object _was_ initialized and we're supposed to merge
|
|
||||||
// in some uninitialized object, we reject the code (see vmspec2, 4.9.4, last paragraph).
|
|
||||||
if ( (! (stack.get(i) instanceof UninitializedObjectType)) && (s.stack.get(i) instanceof UninitializedObjectType) ){
|
|
||||||
throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
|
|
||||||
}
|
|
||||||
// Even harder, we're not initialized but are supposed to broaden
|
|
||||||
// the known object type
|
|
||||||
if ( (!(stack.get(i).equals(s.stack.get(i)))) && (stack.get(i) instanceof UninitializedObjectType) && (!(s.stack.get(i) instanceof UninitializedObjectType))){
|
|
||||||
throw new StructuralCodeConstraintException("Backwards branch with an uninitialized object on the stack detected.");
|
|
||||||
}
|
|
||||||
// on the other hand...
|
|
||||||
if (stack.get(i) instanceof UninitializedObjectType){ //if we have an uninitialized object here
|
|
||||||
if (! (s.stack.get(i) instanceof UninitializedObjectType)){ //that has been initialized by now
|
|
||||||
stack.set(i, ((UninitializedObjectType) (stack.get(i))).getInitialized() ); //note that.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! stack.get(i).equals(s.stack.get(i))){
|
|
||||||
if ( (stack.get(i) instanceof ReferenceType) &&
|
|
||||||
(s.stack.get(i) instanceof ReferenceType) ){
|
|
||||||
stack.set(i, ((ReferenceType) stack.get(i)).getFirstCommonSuperclass((ReferenceType) (s.stack.get(i))));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw new StructuralCodeConstraintException("Cannot merge stacks of different types:\nStack A:\n"+this+"\nStack B:\n"+s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// FIXME: maybe not the best way to handle this
|
|
||||||
throw new AssertionViolatedException("Missing class: " + e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces all occurences of u in this OperandStack instance
|
|
||||||
* with an "initialized" ObjectType.
|
|
||||||
*/
|
|
||||||
public void initializeObject(UninitializedObjectType u){
|
|
||||||
for (int i=0; i<stack.size(); i++){
|
|
||||||
if (stack.get(i) == u){
|
|
||||||
stack.set(i, u.getInitialized());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,347 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Vector;
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.Repository;
|
|
||||||
import org.apache.bcel.classfile.JavaClass;
|
|
||||||
import org.apache.bcel.classfile.Method;
|
|
||||||
import org.apache.bcel.generic.ConstantPoolGen;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.JsrInstruction;
|
|
||||||
import org.apache.bcel.generic.MethodGen;
|
|
||||||
import org.apache.bcel.generic.ObjectType;
|
|
||||||
import org.apache.bcel.generic.RET;
|
|
||||||
import org.apache.bcel.generic.ReturnInstruction;
|
|
||||||
import org.apache.bcel.generic.ReturnaddressType;
|
|
||||||
import org.apache.bcel.generic.Type;
|
|
||||||
import org.apache.bcel.verifier.PassVerifier;
|
|
||||||
import org.apache.bcel.verifier.VerificationResult;
|
|
||||||
import org.apache.bcel.verifier.Verifier;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.VerifierConstraintViolatedException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This PassVerifier verifies a method of class file according to pass 3,
|
|
||||||
* so-called structural verification as described in The Java Virtual Machine
|
|
||||||
* Specification, 2nd edition.
|
|
||||||
* More detailed information is to be found at the do_verify() method's
|
|
||||||
* documentation.
|
|
||||||
*
|
|
||||||
* @version $Id: Pass3bVerifier.java 384759 2006-03-10 10:38:59Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see #do_verify()
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class Pass3bVerifier extends PassVerifier{
|
|
||||||
/* TODO: Throughout pass 3b, upper halves of LONG and DOUBLE
|
|
||||||
are represented by Type.UNKNOWN. This should be changed
|
|
||||||
in favour of LONG_Upper and DOUBLE_Upper as in pass 2. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An InstructionContextQueue is a utility class that holds
|
|
||||||
* (InstructionContext, ArrayList) pairs in a Queue data structure.
|
|
||||||
* This is used to hold information about InstructionContext objects
|
|
||||||
* externally --- i.e. that information is not saved inside the
|
|
||||||
* InstructionContext object itself. This is useful to save the
|
|
||||||
* execution path of the symbolic execution of the
|
|
||||||
* Pass3bVerifier - this is not information
|
|
||||||
* that belongs into the InstructionContext object itself.
|
|
||||||
* Only at "execute()"ing
|
|
||||||
* time, an InstructionContext object will get the current information
|
|
||||||
* we have about its symbolic execution predecessors.
|
|
||||||
*/
|
|
||||||
private static final class InstructionContextQueue{
|
|
||||||
private List ics = new Vector(); // Type: InstructionContext
|
|
||||||
private List ecs = new Vector(); // Type: ArrayList (of InstructionContext)
|
|
||||||
public void add(InstructionContext ic, ArrayList executionChain){
|
|
||||||
ics.add(ic);
|
|
||||||
ecs.add(executionChain);
|
|
||||||
}
|
|
||||||
public boolean isEmpty(){
|
|
||||||
return ics.isEmpty();
|
|
||||||
}
|
|
||||||
public void remove(){
|
|
||||||
this.remove(0);
|
|
||||||
}
|
|
||||||
public void remove(int i){
|
|
||||||
ics.remove(i);
|
|
||||||
ecs.remove(i);
|
|
||||||
}
|
|
||||||
public InstructionContext getIC(int i){
|
|
||||||
return (InstructionContext) ics.get(i);
|
|
||||||
}
|
|
||||||
public ArrayList getEC(int i){
|
|
||||||
return (ArrayList) ecs.get(i);
|
|
||||||
}
|
|
||||||
public int size(){
|
|
||||||
return ics.size();
|
|
||||||
}
|
|
||||||
} // end Inner Class InstructionContextQueue
|
|
||||||
|
|
||||||
/** In DEBUG mode, the verification algorithm is not randomized. */
|
|
||||||
private static final boolean DEBUG = true;
|
|
||||||
|
|
||||||
/** The Verifier that created this. */
|
|
||||||
private Verifier myOwner;
|
|
||||||
|
|
||||||
/** The method number to verify. */
|
|
||||||
private int method_no;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class should only be instantiated by a Verifier.
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.verifier.Verifier
|
|
||||||
*/
|
|
||||||
public Pass3bVerifier(Verifier owner, int method_no){
|
|
||||||
myOwner = owner;
|
|
||||||
this.method_no = method_no;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whenever the outgoing frame
|
|
||||||
* situation of an InstructionContext changes, all its successors are
|
|
||||||
* put [back] into the queue [as if they were unvisited].
|
|
||||||
* The proof of termination is about the existence of a
|
|
||||||
* fix point of frame merging.
|
|
||||||
*/
|
|
||||||
private void circulationPump(ControlFlowGraph cfg, InstructionContext start, Frame vanillaFrame, InstConstraintVisitor icv, ExecutionVisitor ev){
|
|
||||||
final Random random = new Random();
|
|
||||||
InstructionContextQueue icq = new InstructionContextQueue();
|
|
||||||
|
|
||||||
start.execute(vanillaFrame, new ArrayList(), icv, ev); // new ArrayList() <=> no Instruction was executed before
|
|
||||||
// => Top-Level routine (no jsr call before)
|
|
||||||
icq.add(start, new ArrayList());
|
|
||||||
|
|
||||||
// LOOP!
|
|
||||||
while (!icq.isEmpty()){
|
|
||||||
InstructionContext u;
|
|
||||||
ArrayList ec;
|
|
||||||
if (!DEBUG){
|
|
||||||
int r = random.nextInt(icq.size());
|
|
||||||
u = icq.getIC(r);
|
|
||||||
ec = icq.getEC(r);
|
|
||||||
icq.remove(r);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
u = icq.getIC(0);
|
|
||||||
ec = icq.getEC(0);
|
|
||||||
icq.remove(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList oldchain = (ArrayList) (ec.clone());
|
|
||||||
ArrayList newchain = (ArrayList) (ec.clone());
|
|
||||||
newchain.add(u);
|
|
||||||
|
|
||||||
if ((u.getInstruction().getInstruction()) instanceof RET){
|
|
||||||
//System.err.println(u);
|
|
||||||
// We can only follow _one_ successor, the one after the
|
|
||||||
// JSR that was recently executed.
|
|
||||||
RET ret = (RET) (u.getInstruction().getInstruction());
|
|
||||||
ReturnaddressType t = (ReturnaddressType) u.getOutFrame(oldchain).getLocals().get(ret.getIndex());
|
|
||||||
InstructionContext theSuccessor = cfg.contextOf(t.getTarget());
|
|
||||||
|
|
||||||
// Sanity check
|
|
||||||
InstructionContext lastJSR = null;
|
|
||||||
int skip_jsr = 0;
|
|
||||||
for (int ss=oldchain.size()-1; ss >= 0; ss--){
|
|
||||||
if (skip_jsr < 0){
|
|
||||||
throw new AssertionViolatedException("More RET than JSR in execution chain?!");
|
|
||||||
}
|
|
||||||
//System.err.println("+"+oldchain.get(ss));
|
|
||||||
if (((InstructionContext) oldchain.get(ss)).getInstruction().getInstruction() instanceof JsrInstruction){
|
|
||||||
if (skip_jsr == 0){
|
|
||||||
lastJSR = (InstructionContext) oldchain.get(ss);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
skip_jsr--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (((InstructionContext) oldchain.get(ss)).getInstruction().getInstruction() instanceof RET){
|
|
||||||
skip_jsr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lastJSR == null){
|
|
||||||
throw new AssertionViolatedException("RET without a JSR before in ExecutionChain?! EC: '"+oldchain+"'.");
|
|
||||||
}
|
|
||||||
JsrInstruction jsr = (JsrInstruction) (lastJSR.getInstruction().getInstruction());
|
|
||||||
if ( theSuccessor != (cfg.contextOf(jsr.physicalSuccessor())) ){
|
|
||||||
throw new AssertionViolatedException("RET '"+u.getInstruction()+"' info inconsistent: jump back to '"+theSuccessor+"' or '"+cfg.contextOf(jsr.physicalSuccessor())+"'?");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theSuccessor.execute(u.getOutFrame(oldchain), newchain, icv, ev)){
|
|
||||||
icq.add(theSuccessor, (ArrayList) newchain.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{// "not a ret"
|
|
||||||
|
|
||||||
// Normal successors. Add them to the queue of successors.
|
|
||||||
InstructionContext[] succs = u.getSuccessors();
|
|
||||||
for (int s=0; s<succs.length; s++){
|
|
||||||
InstructionContext v = succs[s];
|
|
||||||
if (v.execute(u.getOutFrame(oldchain), newchain, icv, ev)){
|
|
||||||
icq.add(v, (ArrayList) newchain.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}// end "not a ret"
|
|
||||||
|
|
||||||
// Exception Handlers. Add them to the queue of successors.
|
|
||||||
// [subroutines are never protected; mandated by JustIce]
|
|
||||||
ExceptionHandler[] exc_hds = u.getExceptionHandlers();
|
|
||||||
for (int s=0; s<exc_hds.length; s++){
|
|
||||||
InstructionContext v = cfg.contextOf(exc_hds[s].getHandlerStart());
|
|
||||||
// TODO: the "oldchain" and "newchain" is used to determine the subroutine
|
|
||||||
// we're in (by searching for the last JSR) by the InstructionContext
|
|
||||||
// implementation. Therefore, we should not use this chain mechanism
|
|
||||||
// when dealing with exception handlers.
|
|
||||||
// Example: a JSR with an exception handler as its successor does not
|
|
||||||
// mean we're in a subroutine if we go to the exception handler.
|
|
||||||
// We should address this problem later; by now we simply "cut" the chain
|
|
||||||
// by using an empty chain for the exception handlers.
|
|
||||||
//if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(), new OperandStack (u.getOutFrame().getStack().maxStack(), (exc_hds[s].getExceptionType()==null? Type.THROWABLE : exc_hds[s].getExceptionType())) ), newchain), icv, ev){
|
|
||||||
//icq.add(v, (ArrayList) newchain.clone());
|
|
||||||
if (v.execute(new Frame(u.getOutFrame(oldchain).getLocals(), new OperandStack (u.getOutFrame(oldchain).getStack().maxStack(), (exc_hds[s].getExceptionType()==null? Type.THROWABLE : exc_hds[s].getExceptionType())) ), new ArrayList(), icv, ev)){
|
|
||||||
icq.add(v, new ArrayList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}// while (!icq.isEmpty()) END
|
|
||||||
|
|
||||||
InstructionHandle ih = start.getInstruction();
|
|
||||||
do{
|
|
||||||
if ((ih.getInstruction() instanceof ReturnInstruction) && (!(cfg.isDead(ih)))) {
|
|
||||||
InstructionContext ic = cfg.contextOf(ih);
|
|
||||||
Frame f = ic.getOutFrame(new ArrayList()); // TODO: This is buggy, we check only the top-level return instructions this way. Maybe some maniac returns from a method when in a subroutine?
|
|
||||||
LocalVariables lvs = f.getLocals();
|
|
||||||
for (int i=0; i<lvs.maxLocals(); i++){
|
|
||||||
if (lvs.get(i) instanceof UninitializedObjectType){
|
|
||||||
this.addMessage("Warning: ReturnInstruction '"+ic+"' may leave method with an uninitialized object in the local variables array '"+lvs+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OperandStack os = f.getStack();
|
|
||||||
for (int i=0; i<os.size(); i++){
|
|
||||||
if (os.peek(i) instanceof UninitializedObjectType){
|
|
||||||
this.addMessage("Warning: ReturnInstruction '"+ic+"' may leave method with an uninitialized object on the operand stack '"+os+"'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}while ((ih = ih.getNext()) != null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass 3b implements the data flow analysis as described in the Java Virtual
|
|
||||||
* Machine Specification, Second Edition.
|
|
||||||
* Later versions will use LocalVariablesInfo objects to verify if the
|
|
||||||
* verifier-inferred types and the class file's debug information (LocalVariables
|
|
||||||
* attributes) match [TODO].
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.verifier.statics.LocalVariablesInfo
|
|
||||||
* @see org.apache.bcel.verifier.statics.Pass2Verifier#getLocalVariablesInfo(int)
|
|
||||||
*/
|
|
||||||
public VerificationResult do_verify(){
|
|
||||||
if (! myOwner.doPass3a(method_no).equals(VerificationResult.VR_OK)){
|
|
||||||
return VerificationResult.VR_NOTYET;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass 3a ran before, so it's safe to assume the JavaClass object is
|
|
||||||
// in the BCEL repository.
|
|
||||||
JavaClass jc;
|
|
||||||
try {
|
|
||||||
jc = Repository.lookupClass(myOwner.getClassName());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// FIXME: maybe not the best way to handle this
|
|
||||||
throw new AssertionViolatedException("Missing class: " + e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstantPoolGen constantPoolGen = new ConstantPoolGen(jc.getConstantPool());
|
|
||||||
// Init Visitors
|
|
||||||
InstConstraintVisitor icv = new InstConstraintVisitor();
|
|
||||||
icv.setConstantPoolGen(constantPoolGen);
|
|
||||||
|
|
||||||
ExecutionVisitor ev = new ExecutionVisitor();
|
|
||||||
ev.setConstantPoolGen(constantPoolGen);
|
|
||||||
|
|
||||||
Method[] methods = jc.getMethods(); // Method no "method_no" exists, we ran Pass3a before on it!
|
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
MethodGen mg = new MethodGen(methods[method_no], myOwner.getClassName(), constantPoolGen);
|
|
||||||
|
|
||||||
icv.setMethodGen(mg);
|
|
||||||
|
|
||||||
////////////// DFA BEGINS HERE ////////////////
|
|
||||||
if (! (mg.isAbstract() || mg.isNative()) ){ // IF mg HAS CODE (See pass 2)
|
|
||||||
|
|
||||||
ControlFlowGraph cfg = new ControlFlowGraph(mg);
|
|
||||||
|
|
||||||
// Build the initial frame situation for this method.
|
|
||||||
Frame f = new Frame(mg.getMaxLocals(),mg.getMaxStack());
|
|
||||||
if ( !mg.isStatic() ){
|
|
||||||
if (mg.getName().equals(Constants.CONSTRUCTOR_NAME)){
|
|
||||||
Frame._this = new UninitializedObjectType(new ObjectType(jc.getClassName()));
|
|
||||||
f.getLocals().set(0, Frame._this);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Frame._this = null;
|
|
||||||
f.getLocals().set(0, new ObjectType(jc.getClassName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Type[] argtypes = mg.getArgumentTypes();
|
|
||||||
int twoslotoffset = 0;
|
|
||||||
for (int j=0; j<argtypes.length; j++){
|
|
||||||
if (argtypes[j] == Type.SHORT || argtypes[j] == Type.BYTE || argtypes[j] == Type.CHAR || argtypes[j] == Type.BOOLEAN){
|
|
||||||
argtypes[j] = Type.INT;
|
|
||||||
}
|
|
||||||
f.getLocals().set(twoslotoffset + j + (mg.isStatic()?0:1), argtypes[j]);
|
|
||||||
if (argtypes[j].getSize() == 2){
|
|
||||||
twoslotoffset++;
|
|
||||||
f.getLocals().set(twoslotoffset + j + (mg.isStatic()?0:1), Type.UNKNOWN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
circulationPump(cfg, cfg.contextOf(mg.getInstructionList().getStart()), f, icv, ev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (VerifierConstraintViolatedException ce){
|
|
||||||
ce.extendMessage("Constraint violated in method '"+methods[method_no]+"':\n","");
|
|
||||||
return new VerificationResult(VerificationResult.VERIFIED_REJECTED, ce.getMessage());
|
|
||||||
}
|
|
||||||
catch (RuntimeException re){
|
|
||||||
// These are internal errors
|
|
||||||
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
|
||||||
re.printStackTrace(pw);
|
|
||||||
|
|
||||||
throw new AssertionViolatedException("Some RuntimeException occured while verify()ing class '"+jc.getClassName()+"', method '"+methods[method_no]+"'. Original RuntimeException's stack trace:\n---\n"+sw+"---\n");
|
|
||||||
}
|
|
||||||
return VerificationResult.VR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the method number as supplied when instantiating. */
|
|
||||||
public int getMethodNo(){
|
|
||||||
return method_no;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface defines properties of JVM bytecode subroutines.
|
|
||||||
* Note that it is 'abused' to maintain the top-level code in a
|
|
||||||
* consistent fashion, too.
|
|
||||||
*
|
|
||||||
* @version $Id: Subroutine.java 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public interface Subroutine{
|
|
||||||
/**
|
|
||||||
* Returns all the JsrInstructions that have the
|
|
||||||
* first instruction of this subroutine as their target.
|
|
||||||
* <B>Must not be invoked on the 'top-level subroutine'.</B>
|
|
||||||
*/
|
|
||||||
public InstructionHandle[] getEnteringJsrInstructions();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the one and only RET that leaves the subroutine.
|
|
||||||
* Note that JustIce has a pretty rigid notion of a subroutine.
|
|
||||||
* <B>Must not be invoked on the 'top-level subroutine'.</B>
|
|
||||||
*
|
|
||||||
* @see org.apache.bcel.verifier.structurals.Subroutines
|
|
||||||
*/
|
|
||||||
public InstructionHandle getLeavingRET();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all instructions that together form this subroutine.
|
|
||||||
* Note that an instruction is part of exactly one subroutine
|
|
||||||
* (the top-level code is considered to be a special subroutine) -
|
|
||||||
* else it is not reachable at all (dead code).
|
|
||||||
*/
|
|
||||||
public InstructionHandle[] getInstructions();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns if the given InstructionHandle refers to an instruction
|
|
||||||
* that is part of this subroutine. This is a convenience method
|
|
||||||
* that saves iteration over the InstructionHandle objects returned
|
|
||||||
* by getInstructions().
|
|
||||||
*
|
|
||||||
* @see #getInstructions()
|
|
||||||
*/
|
|
||||||
public boolean contains(InstructionHandle inst);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an int[] containing the indices of the local variable slots
|
|
||||||
* accessed by this Subroutine (read-accessed, write-accessed or both);
|
|
||||||
* local variables referenced by subroutines of this subroutine are
|
|
||||||
* not included.
|
|
||||||
*
|
|
||||||
* @see #getRecursivelyAccessedLocalsIndices()
|
|
||||||
*/
|
|
||||||
public int[] getAccessedLocalsIndices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an int[] containing the indices of the local variable slots
|
|
||||||
* accessed by this Subroutine (read-accessed, write-accessed or both);
|
|
||||||
* local variables referenced by subroutines of this subroutine are
|
|
||||||
* included.
|
|
||||||
*
|
|
||||||
* @see #getAccessedLocalsIndices()
|
|
||||||
*/
|
|
||||||
public int[] getRecursivelyAccessedLocalsIndices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the subroutines that are directly called from this subroutine.
|
|
||||||
*/
|
|
||||||
public Subroutine[] subSubs();
|
|
||||||
}
|
|
@ -1,651 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
import org.apache.bcel.generic.ASTORE;
|
|
||||||
import org.apache.bcel.generic.ATHROW;
|
|
||||||
import org.apache.bcel.generic.BranchInstruction;
|
|
||||||
import org.apache.bcel.generic.CodeExceptionGen;
|
|
||||||
import org.apache.bcel.generic.GotoInstruction;
|
|
||||||
import org.apache.bcel.generic.IndexedInstruction;
|
|
||||||
import org.apache.bcel.generic.Instruction;
|
|
||||||
import org.apache.bcel.generic.InstructionHandle;
|
|
||||||
import org.apache.bcel.generic.JsrInstruction;
|
|
||||||
import org.apache.bcel.generic.LocalVariableInstruction;
|
|
||||||
import org.apache.bcel.generic.MethodGen;
|
|
||||||
import org.apache.bcel.generic.RET;
|
|
||||||
import org.apache.bcel.generic.ReturnInstruction;
|
|
||||||
import org.apache.bcel.generic.Select;
|
|
||||||
import org.apache.bcel.verifier.exc.AssertionViolatedException;
|
|
||||||
import org.apache.bcel.verifier.exc.StructuralCodeConstraintException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instances of this class contain information about the subroutines
|
|
||||||
* found in a code array of a method.
|
|
||||||
* This implementation considers the top-level (the instructions
|
|
||||||
* reachable without a JSR or JSR_W starting off from the first
|
|
||||||
* instruction in a code array of a method) being a special subroutine;
|
|
||||||
* see getTopLevel() for that.
|
|
||||||
* Please note that the definition of subroutines in the Java Virtual
|
|
||||||
* Machine Specification, Second Edition is somewhat incomplete.
|
|
||||||
* Therefore, JustIce uses an own, more rigid notion.
|
|
||||||
* Basically, a subroutine is a piece of code that starts at the target
|
|
||||||
* of a JSR of JSR_W instruction and ends at a corresponding RET
|
|
||||||
* instruction. Note also that the control flow of a subroutine
|
|
||||||
* may be complex and non-linear; and that subroutines may be nested.
|
|
||||||
* JustIce also mandates subroutines not to be protected by exception
|
|
||||||
* handling code (for the sake of control flow predictability).
|
|
||||||
* To understand JustIce's notion of subroutines, please read
|
|
||||||
*
|
|
||||||
* TODO: refer to the paper.
|
|
||||||
*
|
|
||||||
* @version $Id: Subroutines.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
* @see #getTopLevel()
|
|
||||||
*/
|
|
||||||
public class Subroutines{
|
|
||||||
/**
|
|
||||||
* This inner class implements the Subroutine interface.
|
|
||||||
*/
|
|
||||||
private class SubroutineImpl implements Subroutine{
|
|
||||||
/**
|
|
||||||
* UNSET, a symbol for an uninitialized localVariable
|
|
||||||
* field. This is used for the "top-level" Subroutine;
|
|
||||||
* i.e. no subroutine.
|
|
||||||
*/
|
|
||||||
private static final int UNSET = -1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Local Variable slot where the first
|
|
||||||
* instruction of this subroutine (an ASTORE) stores
|
|
||||||
* the JsrInstruction's ReturnAddress in and
|
|
||||||
* the RET of this subroutine operates on.
|
|
||||||
*/
|
|
||||||
private int localVariable = UNSET;
|
|
||||||
|
|
||||||
/** The instructions that belong to this subroutine. */
|
|
||||||
private Set instructions = new HashSet(); // Elements: InstructionHandle
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refer to the Subroutine interface for documentation.
|
|
||||||
*/
|
|
||||||
public boolean contains(InstructionHandle inst){
|
|
||||||
return instructions.contains(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The JSR or JSR_W instructions that define this
|
|
||||||
* subroutine by targeting it.
|
|
||||||
*/
|
|
||||||
private Set theJSRs = new HashSet();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The RET instruction that leaves this subroutine.
|
|
||||||
*/
|
|
||||||
private InstructionHandle theRET;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of this object, merely
|
|
||||||
* for debugging purposes.
|
|
||||||
* (Internal) Warning: Verbosity on a problematic subroutine may cause
|
|
||||||
* stack overflow errors due to recursive subSubs() calls.
|
|
||||||
* Don't use this, then.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
String ret = "Subroutine: Local variable is '"+localVariable+"', JSRs are '"+theJSRs+"', RET is '"+theRET+"', Instructions: '"+instructions.toString()+"'.";
|
|
||||||
|
|
||||||
ret += " Accessed local variable slots: '";
|
|
||||||
int[] alv = getAccessedLocalsIndices();
|
|
||||||
for (int i=0; i<alv.length; i++){
|
|
||||||
ret += alv[i]+" ";
|
|
||||||
}
|
|
||||||
ret+="'.";
|
|
||||||
|
|
||||||
ret += " Recursively (via subsub...routines) accessed local variable slots: '";
|
|
||||||
alv = getRecursivelyAccessedLocalsIndices();
|
|
||||||
for (int i=0; i<alv.length; i++){
|
|
||||||
ret += alv[i]+" ";
|
|
||||||
}
|
|
||||||
ret+="'.";
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the leaving RET instruction. Must be invoked after all instructions are added.
|
|
||||||
* Must not be invoked for top-level 'subroutine'.
|
|
||||||
*/
|
|
||||||
void setLeavingRET(){
|
|
||||||
if (localVariable == UNSET){
|
|
||||||
throw new AssertionViolatedException("setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");
|
|
||||||
}
|
|
||||||
Iterator iter = instructions.iterator();
|
|
||||||
InstructionHandle ret = null;
|
|
||||||
while(iter.hasNext()){
|
|
||||||
InstructionHandle actual = (InstructionHandle) iter.next();
|
|
||||||
if (actual.getInstruction() instanceof RET){
|
|
||||||
if (ret != null){
|
|
||||||
throw new StructuralCodeConstraintException("Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
ret = actual;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ret == null){
|
|
||||||
throw new StructuralCodeConstraintException("Subroutine without a RET detected.");
|
|
||||||
}
|
|
||||||
if (((RET) ret.getInstruction()).getIndex() != localVariable){
|
|
||||||
throw new StructuralCodeConstraintException("Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");
|
|
||||||
}
|
|
||||||
theRET = ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refer to the Subroutine interface for documentation.
|
|
||||||
*/
|
|
||||||
public InstructionHandle[] getEnteringJsrInstructions(){
|
|
||||||
if (this == TOPLEVEL) {
|
|
||||||
throw new AssertionViolatedException("getLeavingRET() called on top level pseudo-subroutine.");
|
|
||||||
}
|
|
||||||
InstructionHandle[] jsrs = new InstructionHandle[theJSRs.size()];
|
|
||||||
return (InstructionHandle[]) (theJSRs.toArray(jsrs));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new JSR or JSR_W that has this subroutine as its target.
|
|
||||||
*/
|
|
||||||
public void addEnteringJsrInstruction(InstructionHandle jsrInst){
|
|
||||||
if ( (jsrInst == null) || (! (jsrInst.getInstruction() instanceof JsrInstruction))){
|
|
||||||
throw new AssertionViolatedException("Expecting JsrInstruction InstructionHandle.");
|
|
||||||
}
|
|
||||||
if (localVariable == UNSET){
|
|
||||||
throw new AssertionViolatedException("Set the localVariable first!");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// Something is wrong when an ASTORE is targeted that does not operate on the same local variable than the rest of the
|
|
||||||
// JsrInstruction-targets and the RET.
|
|
||||||
// (We don't know out leader here so we cannot check if we're really targeted!)
|
|
||||||
if (localVariable != ((ASTORE) (((JsrInstruction) jsrInst.getInstruction()).getTarget().getInstruction())).getIndex()){
|
|
||||||
throw new AssertionViolatedException("Setting a wrong JsrInstruction.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
theJSRs.add(jsrInst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refer to the Subroutine interface for documentation.
|
|
||||||
*/
|
|
||||||
public InstructionHandle getLeavingRET(){
|
|
||||||
if (this == TOPLEVEL) {
|
|
||||||
throw new AssertionViolatedException("getLeavingRET() called on top level pseudo-subroutine.");
|
|
||||||
}
|
|
||||||
return theRET;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Refer to the Subroutine interface for documentation.
|
|
||||||
*/
|
|
||||||
public InstructionHandle[] getInstructions(){
|
|
||||||
InstructionHandle[] ret = new InstructionHandle[instructions.size()];
|
|
||||||
return (InstructionHandle[]) instructions.toArray(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adds an instruction to this subroutine.
|
|
||||||
* All instructions must have been added before invoking setLeavingRET().
|
|
||||||
* @see #setLeavingRET
|
|
||||||
*/
|
|
||||||
void addInstruction(InstructionHandle ih){
|
|
||||||
if (theRET != null){
|
|
||||||
throw new AssertionViolatedException("All instructions must have been added before invoking setLeavingRET().");
|
|
||||||
}
|
|
||||||
instructions.add(ih);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Satisfies Subroutine.getRecursivelyAccessedLocalsIndices(). */
|
|
||||||
public int[] getRecursivelyAccessedLocalsIndices(){
|
|
||||||
Set s = new HashSet();
|
|
||||||
int[] lvs = getAccessedLocalsIndices();
|
|
||||||
for (int j=0; j<lvs.length; j++){
|
|
||||||
s.add(new Integer(lvs[j]));
|
|
||||||
}
|
|
||||||
_getRecursivelyAccessedLocalsIndicesHelper(s, this.subSubs());
|
|
||||||
int[] ret = new int[s.size()];
|
|
||||||
Iterator i = s.iterator();
|
|
||||||
int j=-1;
|
|
||||||
while (i.hasNext()){
|
|
||||||
j++;
|
|
||||||
ret[j] = ((Integer) i.next()).intValue();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A recursive helper method for getRecursivelyAccessedLocalsIndices().
|
|
||||||
* @see #getRecursivelyAccessedLocalsIndices()
|
|
||||||
*/
|
|
||||||
private void _getRecursivelyAccessedLocalsIndicesHelper(Set s, Subroutine[] subs){
|
|
||||||
for (int i=0; i<subs.length; i++){
|
|
||||||
int[] lvs = subs[i].getAccessedLocalsIndices();
|
|
||||||
for (int j=0; j<lvs.length; j++){
|
|
||||||
s.add(new Integer(lvs[j]));
|
|
||||||
}
|
|
||||||
if(subs[i].subSubs().length != 0){
|
|
||||||
_getRecursivelyAccessedLocalsIndicesHelper(s, subs[i].subSubs());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Satisfies Subroutine.getAccessedLocalIndices().
|
|
||||||
*/
|
|
||||||
public int[] getAccessedLocalsIndices(){
|
|
||||||
//TODO: Implement caching.
|
|
||||||
Set acc = new HashSet();
|
|
||||||
if (theRET == null && this != TOPLEVEL){
|
|
||||||
throw new AssertionViolatedException("This subroutine object must be built up completely before calculating accessed locals.");
|
|
||||||
}
|
|
||||||
Iterator i = instructions.iterator();
|
|
||||||
while (i.hasNext()){
|
|
||||||
InstructionHandle ih = (InstructionHandle) i.next();
|
|
||||||
// RET is not a LocalVariableInstruction in the current version of BCEL.
|
|
||||||
if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET){
|
|
||||||
int idx = ((IndexedInstruction) (ih.getInstruction())).getIndex();
|
|
||||||
acc.add(new Integer(idx));
|
|
||||||
// LONG? DOUBLE?.
|
|
||||||
try{
|
|
||||||
// LocalVariableInstruction instances are typed without the need to look into
|
|
||||||
// the constant pool.
|
|
||||||
if (ih.getInstruction() instanceof LocalVariableInstruction){
|
|
||||||
int s = ((LocalVariableInstruction) ih.getInstruction()).getType(null).getSize();
|
|
||||||
if (s==2) {
|
|
||||||
acc.add(new Integer(idx+1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(RuntimeException re){
|
|
||||||
throw new AssertionViolatedException("Oops. BCEL did not like NULL as a ConstantPoolGen object.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int[] ret = new int[acc.size()];
|
|
||||||
i = acc.iterator();
|
|
||||||
int j=-1;
|
|
||||||
while (i.hasNext()){
|
|
||||||
j++;
|
|
||||||
ret[j] = ((Integer) i.next()).intValue();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Satisfies Subroutine.subSubs().
|
|
||||||
*/
|
|
||||||
public Subroutine[] subSubs(){
|
|
||||||
Set h = new HashSet();
|
|
||||||
|
|
||||||
Iterator i = instructions.iterator();
|
|
||||||
while (i.hasNext()){
|
|
||||||
Instruction inst = ((InstructionHandle) i.next()).getInstruction();
|
|
||||||
if (inst instanceof JsrInstruction){
|
|
||||||
InstructionHandle targ = ((JsrInstruction) inst).getTarget();
|
|
||||||
h.add(getSubroutine(targ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Subroutine[] ret = new Subroutine[h.size()];
|
|
||||||
return (Subroutine[]) h.toArray(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sets the local variable slot the ASTORE that is targeted
|
|
||||||
* by the JsrInstructions of this subroutine operates on.
|
|
||||||
* This subroutine's RET operates on that same local variable
|
|
||||||
* slot, of course.
|
|
||||||
*/
|
|
||||||
void setLocalVariable(int i){
|
|
||||||
if (localVariable != UNSET){
|
|
||||||
throw new AssertionViolatedException("localVariable set twice.");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
localVariable = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default constructor.
|
|
||||||
*/
|
|
||||||
public SubroutineImpl(){
|
|
||||||
}
|
|
||||||
|
|
||||||
}// end Inner Class SubrouteImpl
|
|
||||||
|
|
||||||
//Node coloring constants
|
|
||||||
private static final Integer WHITE = new Integer(0);
|
|
||||||
private static final Integer GRAY = new Integer(1);
|
|
||||||
private static final Integer BLACK = new Integer(2);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Hashtable containing the subroutines found.
|
|
||||||
* Key: InstructionHandle of the leader of the subroutine.
|
|
||||||
* Elements: SubroutineImpl objects.
|
|
||||||
*/
|
|
||||||
private Hashtable subroutines = new Hashtable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is referring to a special subroutine, namely the
|
|
||||||
* top level. This is not really a subroutine but we use
|
|
||||||
* it to distinguish between top level instructions and
|
|
||||||
* unreachable instructions.
|
|
||||||
*/
|
|
||||||
public final Subroutine TOPLEVEL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
* @param mg A MethodGen object representing method to
|
|
||||||
* create the Subroutine objects of.
|
|
||||||
*/
|
|
||||||
public Subroutines(MethodGen mg){
|
|
||||||
|
|
||||||
InstructionHandle[] all = mg.getInstructionList().getInstructionHandles();
|
|
||||||
CodeExceptionGen[] handlers = mg.getExceptionHandlers();
|
|
||||||
|
|
||||||
// Define our "Toplevel" fake subroutine.
|
|
||||||
TOPLEVEL = new SubroutineImpl();
|
|
||||||
|
|
||||||
// Calculate "real" subroutines.
|
|
||||||
Set sub_leaders = new HashSet(); // Elements: InstructionHandle
|
|
||||||
for (int i=0; i<all.length; i++){
|
|
||||||
Instruction inst = all[i].getInstruction();
|
|
||||||
if (inst instanceof JsrInstruction){
|
|
||||||
sub_leaders.add(((JsrInstruction) inst).getTarget());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build up the database.
|
|
||||||
Iterator iter = sub_leaders.iterator();
|
|
||||||
while (iter.hasNext()){
|
|
||||||
SubroutineImpl sr = new SubroutineImpl();
|
|
||||||
InstructionHandle astore = (InstructionHandle) (iter.next());
|
|
||||||
sr.setLocalVariable( ((ASTORE) (astore.getInstruction())).getIndex() );
|
|
||||||
subroutines.put(astore, sr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fake it a bit. We want a virtual "TopLevel" subroutine.
|
|
||||||
subroutines.put(all[0], TOPLEVEL);
|
|
||||||
sub_leaders.add(all[0]);
|
|
||||||
|
|
||||||
// Tell the subroutines about their JsrInstructions.
|
|
||||||
// Note that there cannot be a JSR targeting the top-level
|
|
||||||
// since "Jsr 0" is disallowed in Pass 3a.
|
|
||||||
// Instructions shared by a subroutine and the toplevel are
|
|
||||||
// disallowed and checked below, after the BFS.
|
|
||||||
for (int i=0; i<all.length; i++){
|
|
||||||
Instruction inst = all[i].getInstruction();
|
|
||||||
if (inst instanceof JsrInstruction){
|
|
||||||
InstructionHandle leader = ((JsrInstruction) inst).getTarget();
|
|
||||||
((SubroutineImpl) getSubroutine(leader)).addEnteringJsrInstruction(all[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now do a BFS from every subroutine leader to find all the
|
|
||||||
// instructions that belong to a subroutine.
|
|
||||||
Set instructions_assigned = new HashSet(); // we don't want to assign an instruction to two or more Subroutine objects.
|
|
||||||
|
|
||||||
Hashtable colors = new Hashtable(); //Graph colouring. Key: InstructionHandle, Value: Integer .
|
|
||||||
|
|
||||||
iter = sub_leaders.iterator();
|
|
||||||
while (iter.hasNext()){
|
|
||||||
// Do some BFS with "actual" as the root of the graph.
|
|
||||||
InstructionHandle actual = (InstructionHandle) (iter.next());
|
|
||||||
// Init colors
|
|
||||||
for (int i=0; i<all.length; i++){
|
|
||||||
colors.put(all[i], WHITE);
|
|
||||||
}
|
|
||||||
colors.put(actual, GRAY);
|
|
||||||
// Init Queue
|
|
||||||
ArrayList Q = new ArrayList();
|
|
||||||
Q.add(actual); // add(Obj) adds to the end, remove(0) removes from the start.
|
|
||||||
|
|
||||||
/* BFS ALGORITHM MODIFICATION: Start out with multiple "root" nodes, as exception handlers are starting points of top-level code, too. [why top-level? TODO: Refer to the special JustIce notion of subroutines.]*/
|
|
||||||
if (actual == all[0]){
|
|
||||||
for (int j=0; j<handlers.length; j++){
|
|
||||||
colors.put(handlers[j].getHandlerPC(), GRAY);
|
|
||||||
Q.add(handlers[j].getHandlerPC());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* CONTINUE NORMAL BFS ALGORITHM */
|
|
||||||
|
|
||||||
// Loop until Queue is empty
|
|
||||||
while (Q.size() != 0){
|
|
||||||
InstructionHandle u = (InstructionHandle) Q.remove(0);
|
|
||||||
InstructionHandle[] successors = getSuccessors(u);
|
|
||||||
for (int i=0; i<successors.length; i++){
|
|
||||||
if (((Integer) colors.get(successors[i])) == WHITE){
|
|
||||||
colors.put(successors[i], GRAY);
|
|
||||||
Q.add(successors[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
colors.put(u, BLACK);
|
|
||||||
}
|
|
||||||
// BFS ended above.
|
|
||||||
for (int i=0; i<all.length; i++){
|
|
||||||
if (colors.get(all[i]) == BLACK){
|
|
||||||
((SubroutineImpl) (actual==all[0]?getTopLevel():getSubroutine(actual))).addInstruction(all[i]);
|
|
||||||
if (instructions_assigned.contains(all[i])){
|
|
||||||
throw new StructuralCodeConstraintException("Instruction '"+all[i]+"' is part of more than one subroutine (or of the top level and a subroutine).");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
instructions_assigned.add(all[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (actual != all[0]){// If we don't deal with the top-level 'subroutine'
|
|
||||||
((SubroutineImpl) getSubroutine(actual)).setLeavingRET();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now make sure no instruction of a Subroutine is protected by exception handling code
|
|
||||||
// as is mandated by JustIces notion of subroutines.
|
|
||||||
for (int i=0; i<handlers.length; i++){
|
|
||||||
InstructionHandle _protected = handlers[i].getStartPC();
|
|
||||||
while (_protected != handlers[i].getEndPC().getNext()){// Note the inclusive/inclusive notation of "generic API" exception handlers!
|
|
||||||
Iterator subs = subroutines.values().iterator();
|
|
||||||
while (subs.hasNext()){
|
|
||||||
Subroutine sub = (Subroutine) subs.next();
|
|
||||||
if (sub != subroutines.get(all[0])){ // We don't want to forbid top-level exception handlers.
|
|
||||||
if (sub.contains(_protected)){
|
|
||||||
throw new StructuralCodeConstraintException("Subroutine instruction '"+_protected+"' is protected by an exception handler, '"+handlers[i]+"'. This is forbidden by the JustIce verifier due to its clear definition of subroutines.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_protected = _protected.getNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now make sure no subroutine is calling a subroutine
|
|
||||||
// that uses the same local variable for the RET as themselves
|
|
||||||
// (recursively).
|
|
||||||
// This includes that subroutines may not call themselves
|
|
||||||
// recursively, even not through intermediate calls to other
|
|
||||||
// subroutines.
|
|
||||||
noRecursiveCalls(getTopLevel(), new HashSet());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This (recursive) utility method makes sure that
|
|
||||||
* no subroutine is calling a subroutine
|
|
||||||
* that uses the same local variable for the RET as themselves
|
|
||||||
* (recursively).
|
|
||||||
* This includes that subroutines may not call themselves
|
|
||||||
* recursively, even not through intermediate calls to other
|
|
||||||
* subroutines.
|
|
||||||
*
|
|
||||||
* @throws StructuralCodeConstraintException if the above constraint is not satisfied.
|
|
||||||
*/
|
|
||||||
private void noRecursiveCalls(Subroutine sub, Set set){
|
|
||||||
Subroutine[] subs = sub.subSubs();
|
|
||||||
|
|
||||||
for (int i=0; i<subs.length; i++){
|
|
||||||
int index = ((RET) (subs[i].getLeavingRET().getInstruction())).getIndex();
|
|
||||||
|
|
||||||
if (!set.add(new Integer(index))){
|
|
||||||
// Don't use toString() here because of possibly infinite recursive subSubs() calls then.
|
|
||||||
SubroutineImpl si = (SubroutineImpl) subs[i];
|
|
||||||
throw new StructuralCodeConstraintException("Subroutine with local variable '"+si.localVariable+"', JSRs '"+si.theJSRs+"', RET '"+si.theRET+"' is called by a subroutine which uses the same local variable index as itself; maybe even a recursive call? JustIce's clean definition of a subroutine forbids both.");
|
|
||||||
}
|
|
||||||
|
|
||||||
noRecursiveCalls(subs[i], set);
|
|
||||||
|
|
||||||
set.remove(new Integer(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Subroutine object associated with the given
|
|
||||||
* leader (that is, the first instruction of the subroutine).
|
|
||||||
* You must not use this to get the top-level instructions
|
|
||||||
* modeled as a Subroutine object.
|
|
||||||
*
|
|
||||||
* @see #getTopLevel()
|
|
||||||
*/
|
|
||||||
public Subroutine getSubroutine(InstructionHandle leader){
|
|
||||||
Subroutine ret = (Subroutine) subroutines.get(leader);
|
|
||||||
|
|
||||||
if (ret == null){
|
|
||||||
throw new AssertionViolatedException("Subroutine requested for an InstructionHandle that is not a leader of a subroutine.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == TOPLEVEL){
|
|
||||||
throw new AssertionViolatedException("TOPLEVEL special subroutine requested; use getTopLevel().");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the subroutine object associated with the
|
|
||||||
* given instruction. This is a costly operation, you
|
|
||||||
* should consider using getSubroutine(InstructionHandle).
|
|
||||||
* Returns 'null' if the given InstructionHandle lies
|
|
||||||
* in so-called 'dead code', i.e. code that can never
|
|
||||||
* be executed.
|
|
||||||
*
|
|
||||||
* @see #getSubroutine(InstructionHandle)
|
|
||||||
* @see #getTopLevel()
|
|
||||||
*/
|
|
||||||
public Subroutine subroutineOf(InstructionHandle any){
|
|
||||||
Iterator i = subroutines.values().iterator();
|
|
||||||
while (i.hasNext()){
|
|
||||||
Subroutine s = (Subroutine) i.next();
|
|
||||||
if (s.contains(any)) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.err.println("DEBUG: Please verify '"+any+"' lies in dead code.");
|
|
||||||
return null;
|
|
||||||
//throw new AssertionViolatedException("No subroutine for InstructionHandle found (DEAD CODE?).");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For easy handling, the piece of code that is <B>not</B> a
|
|
||||||
* subroutine, the top-level, is also modeled as a Subroutine
|
|
||||||
* object.
|
|
||||||
* It is a special Subroutine object where <B>you must not invoke
|
|
||||||
* getEnteringJsrInstructions() or getLeavingRET()</B>.
|
|
||||||
*
|
|
||||||
* @see Subroutine#getEnteringJsrInstructions()
|
|
||||||
* @see Subroutine#getLeavingRET()
|
|
||||||
*/
|
|
||||||
public Subroutine getTopLevel(){
|
|
||||||
return TOPLEVEL;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* A utility method that calculates the successors of a given InstructionHandle
|
|
||||||
* <B>in the same subroutine</B>. That means, a RET does not have any successors
|
|
||||||
* as defined here. A JsrInstruction has its physical successor as its successor
|
|
||||||
* (opposed to its target) as defined here.
|
|
||||||
*/
|
|
||||||
private static InstructionHandle[] getSuccessors(InstructionHandle instruction){
|
|
||||||
final InstructionHandle[] empty = new InstructionHandle[0];
|
|
||||||
final InstructionHandle[] single = new InstructionHandle[1];
|
|
||||||
final InstructionHandle[] pair = new InstructionHandle[2];
|
|
||||||
|
|
||||||
Instruction inst = instruction.getInstruction();
|
|
||||||
|
|
||||||
if (inst instanceof RET){
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminates method normally.
|
|
||||||
if (inst instanceof ReturnInstruction){
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminates method abnormally, because JustIce mandates
|
|
||||||
// subroutines not to be protected by exception handlers.
|
|
||||||
if (inst instanceof ATHROW){
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See method comment.
|
|
||||||
if (inst instanceof JsrInstruction){
|
|
||||||
single[0] = instruction.getNext();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inst instanceof GotoInstruction){
|
|
||||||
single[0] = ((GotoInstruction) inst).getTarget();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inst instanceof BranchInstruction){
|
|
||||||
if (inst instanceof Select){
|
|
||||||
// BCEL's getTargets() returns only the non-default targets,
|
|
||||||
// thanks to Eli Tilevich for reporting.
|
|
||||||
InstructionHandle[] matchTargets = ((Select) inst).getTargets();
|
|
||||||
InstructionHandle[] ret = new InstructionHandle[matchTargets.length+1];
|
|
||||||
ret[0] = ((Select) inst).getTarget();
|
|
||||||
System.arraycopy(matchTargets, 0, ret, 1, matchTargets.length);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
pair[0] = instruction.getNext();
|
|
||||||
pair[1] = ((BranchInstruction) inst).getTarget();
|
|
||||||
return pair;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// default case: Fall through.
|
|
||||||
single[0] = instruction.getNext();
|
|
||||||
return single;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a String representation of this object; merely for debugging puposes.
|
|
||||||
*/
|
|
||||||
public String toString(){
|
|
||||||
return "---\n"+subroutines.toString()+"\n---\n";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2000-2004 The Apache Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package org.apache.bcel.verifier.structurals;
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.bcel.Constants;
|
|
||||||
import org.apache.bcel.generic.ObjectType;
|
|
||||||
import org.apache.bcel.generic.ReferenceType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class represents an uninitialized object type; see The Java
|
|
||||||
* Virtual Machine Specification, Second Edition, page 147: 4.9.4 for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* @version $Id: UninitializedObjectType.java 386056 2006-03-15 11:31:56Z tcurdt $
|
|
||||||
* @author Enver Haase
|
|
||||||
*/
|
|
||||||
public class UninitializedObjectType extends ReferenceType implements Constants{
|
|
||||||
|
|
||||||
/** The "initialized" version. */
|
|
||||||
private ObjectType initialized;
|
|
||||||
|
|
||||||
/** Creates a new instance. */
|
|
||||||
public UninitializedObjectType(ObjectType t){
|
|
||||||
super(T_UNKNOWN, "<UNINITIALIZED OBJECT OF TYPE '"+t.getClassName()+"'>");
|
|
||||||
initialized = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the ObjectType of the same class as the one of the uninitialized object
|
|
||||||
* represented by this UninitializedObjectType instance.
|
|
||||||
*/
|
|
||||||
public ObjectType getInitialized(){
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a hash code value for the object.
|
|
||||||
*/
|
|
||||||
public int hashCode() { return initialized.hashCode(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true on equality of this and o.
|
|
||||||
* Equality means the ObjectType instances of "initialized"
|
|
||||||
* equal one another in this and the o instance.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public boolean equals(Object o){
|
|
||||||
if (! (o instanceof UninitializedObjectType)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return initialized.equals(((UninitializedObjectType)o).initialized);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<!--
|
|
||||||
$Id: package.html 371539 2006-01-23 14:08:00Z tcurdt $
|
|
||||||
-->
|
|
||||||
</head>
|
|
||||||
<body bgcolor="white">
|
|
||||||
|
|
||||||
Provides a PassVerifier class mostly used internally by JustIce, yielding a control flow graph for public use as
|
|
||||||
a nice side effect.
|
|
||||||
|
|
||||||
<h2>Package Specification</h2>
|
|
||||||
|
|
||||||
Contained in this package is a PassVerifier class for use with the JustIce verifier and its utility classes.
|
|
||||||
Only the pass performing what Sun calls "Structural Constraints on Java Virtual Machine Code"
|
|
||||||
has a PassVerifier class here. JustIce calls this pass "Pass 3b".
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue
Block a user