?? preverificationclassnode.java
字號(hào):
/**
* Copyright (c) 2003-2004 Craig Setera
* All Rights Reserved.
* Licensed under the Eclipse Public License - v 1.0
* For more information see http://www.eclipse.org/legal/epl-v10.html
*/
package eclipseme.preverifier.internal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import eclipseme.preverifier.IPreverificationPolicy;
import eclipseme.preverifier.internal.results.ClassNodeErrorInformation;
import eclipseme.preverifier.internal.results.FieldErrorInformation;
import eclipseme.preverifier.internal.results.MethodNodeErrorInformation;
import eclipseme.preverifier.results.PreverificationError;
import eclipseme.preverifier.results.PreverificationErrorLocation;
import eclipseme.preverifier.results.PreverificationErrorLocationType;
import eclipseme.preverifier.results.PreverificationErrorType;
/**
* A class visitor that provides necessary functionality
* for traversing and handling the structure changes required by
* the preverifier to a class.
* <p />
* Copyright (c) 2003-2004 Craig Setera<br>
* All Rights Reserved.<br>
* Licensed under the Eclipse Public License - v 1.0<p/>
* <br>
* $Revision: 1.4 $
* <br>
* $Date: 2006/02/11 21:26:41 $
* <br>
* @author Craig Setera
*/
public class PreverificationClassNode extends ClassNode {
// Type definitions
private static final Type BOOLEAN_TYPE = Type.getType("Ljava/lang/Boolean;");
private static final Type CHARACTER_TYPE = Type.getType("Ljava/lang/Character;");
private static final Type BYTE_TYPE = Type.getType("Ljava/lang/Byte;");
private static final Type SHORT_TYPE = Type.getType("Ljava/lang/Short;");
private static final Type INTEGER_TYPE = Type.getType("Ljava/lang/Integer;");
private static final Type FLOAT_TYPE = Type.getType("Ljava/lang/Float;");
private static final Type LONG_TYPE = Type.getType("Ljava/lang/Long;");
private static final Type DOUBLE_TYPE = Type.getType("Ljava/lang/Double;");
// Implementation
private IPreverificationPolicy preverificationPolicy;
private ArrayList errorList;
private ClassLoader classLoader;
private Map validTypes;
// Some class instances in the correct classloader
private Class objectClass;
private Class floatClass;
private Class doubleClass;
/**
* Construct a class adapter for preverification.
*
* @param preverificationPolicy
* @param classpath
*/
public PreverificationClassNode(
IPreverificationPolicy preverificationPolicy,
ClassLoader classloader)
{
this.preverificationPolicy = preverificationPolicy;
this.errorList = new ArrayList();
this.classLoader = classloader;
validTypes = new HashMap();
// Capture some class instances in the specified classloader
try {
objectClass = Class.forName("java.lang.Object", true, classLoader);
floatClass = Class.forName("java.lang.Float", true, classLoader);
doubleClass = Class.forName("java.lang.Double", true, classLoader);
} catch (ClassNotFoundException e) {
// Shouldn't happen
}
}
/**
* Return the list of errors accumulated during the traversal.
* @return
*/
public List getErrorList() {
return errorList;
}
/**
* Return a boolean indicating whether or not this class node has any errors.
*
* @return
*/
public boolean hasError() {
return errorList.size() > 0;
}
/**
* @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
*/
public FieldVisitor visitField(
final int access,
final String name,
final String desc,
final String signature,
final Object value)
{
FieldVisitor fieldVisitor = null;
Type type = Type.getType(desc);
PreverificationErrorType error = validateType(type);
if (error == PreverificationErrorType.NO_ERROR) {
// To match up with the WTK output, we want to make sure to strip
// off potential constant values from non-static fields.
Object constantValue = ((access & Opcodes.ACC_STATIC) != 0) ? value : null;
fieldVisitor = super.visitField(access, name, desc, signature, constantValue);
} else {
ClassNodeErrorInformation classInfo = new ClassNodeErrorInformation(this);
FieldErrorInformation fieldInfo = new FieldErrorInformation(name, desc);
PreverificationErrorLocation location = new PreverificationErrorLocation(
PreverificationErrorLocationType.CLASS_FIELD,
classInfo, null, fieldInfo, -1);
PreverificationError fieldError =
new PreverificationError(error, location, null);
getErrorList().add(fieldError);
}
return fieldVisitor;
}
/**
* @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
*/
public MethodVisitor visitMethod(
final int access,
final String name,
final String desc,
final String signature,
final String[] exceptions)
{
MethodNode mn = new PreverifierMethodNode(this, access, name, desc, signature, exceptions);
boolean isNativeError =
!preverificationPolicy.areNativeMethodsAllowed() &&
((access & Opcodes.ACC_NATIVE) != 0);
boolean isFinalizerError =
!preverificationPolicy.areFinalizersAllowed() &&
name.equals("finalize") &&
(Type.getArgumentTypes(desc).length == 0);
PreverificationErrorType signatureErrorType = getMethodSignatureError(desc);
boolean isInvalidMethodSignature = (signatureErrorType != PreverificationErrorType.NO_ERROR);
if (isNativeError || isFinalizerError || isInvalidMethodSignature) {
ClassNodeErrorInformation classInfo = new ClassNodeErrorInformation(this);
MethodNodeErrorInformation methodInfo =
new MethodNodeErrorInformation(classInfo, mn);
PreverificationErrorLocation location = new PreverificationErrorLocation(
PreverificationErrorLocationType.METHOD_SIGNATURE,
classInfo, methodInfo, null, -1);
if (isNativeError) {
PreverificationError error =
new PreverificationError(PreverificationErrorType.NATIVE, location, null);
getErrorList().add(error);
}
if (isFinalizerError) {
PreverificationError error =
new PreverificationError(PreverificationErrorType.FINALIZERS, location, null);
getErrorList().add(error);
}
if (isInvalidMethodSignature) {
PreverificationError error =
new PreverificationError(signatureErrorType, location, null);
getErrorList().add(error);
}
}
return mn;
}
/**
* Return the root type of the specified type, stripping away
* the array and primitive wrappers.
*
* @param type
* @return
*/
private Type getObjectType(Type type) {
Type objectType = type;
switch (type.getSort())
{
// Convert primitive types to object types
case Type.BOOLEAN:
objectType = BOOLEAN_TYPE;
break;
case Type.CHAR:
objectType = CHARACTER_TYPE;
break;
case Type.BYTE:
objectType = BYTE_TYPE;
break;
case Type.SHORT:
objectType = SHORT_TYPE;
break;
case Type.INT:
objectType = INTEGER_TYPE;
break;
case Type.FLOAT:
objectType = FLOAT_TYPE;
break;
case Type.LONG:
objectType = LONG_TYPE;
break;
case Type.DOUBLE:
objectType = DOUBLE_TYPE;
break;
case Type.VOID:
objectType = VOID_TYPE;
break;
case Type.ARRAY:
objectType = getObjectType(type.getElementType());
break;
}
return objectType;
}
/**
* Return a classloader for the verification classpath.
*
* @return
*/
ClassLoader getClassLoader() {
return classLoader;
}
/**
* Return the preverification policy in use.
*
* @return
*/
IPreverificationPolicy getPreverificationPolicy() {
return preverificationPolicy;
}
/**
* Attempt to locate the class that defines the specified type
* instance.
*
* @param objectType
* @return
* @throws ClassNotFoundException
*/
private Class getTypeClass(Type objectType)
throws ClassNotFoundException
{
String dottedName = objectType.getInternalName().replace('/', '.');
return Class.forName(dottedName, true, classLoader);
}
/**
* Return a boolean indicating whether or not the specified
* type is disallowed.
*
* @param clazz
* @return
*/
private boolean isDisallowedType(Class clazz) {
boolean disallowed = false;
if (!getPreverificationPolicy().isFloatingPointAllowed()) {
disallowed = isFloatingPointType(clazz);
}
return disallowed;
}
/**
* Return a boolean indicating whether or not the specified type
* is a floating point type.
*
* @param clazz
* @return
*/
private boolean isFloatingPointType(Class clazz) {
return (clazz == floatClass) || (clazz == doubleClass);
}
/**
* Return a boolean indicating whether the method signature is invalid.
*
* @param desc
* @return
*/
private PreverificationErrorType getMethodSignatureError(String desc) {
Type returnType = Type.getReturnType(desc);
PreverificationErrorType errorType = validateType(returnType);
if (errorType != PreverificationErrorType.NO_ERROR) {
Type[] paramTypes = Type.getArgumentTypes(desc);
for (
int i = 0;
(i < paramTypes.length) &&
(errorType != PreverificationErrorType.NO_ERROR);
i++)
{
errorType = validateType(paramTypes[i]);
}
}
return errorType;
}
/**
* Return an error code concerning the validity of
* the specified type.
*
* @param type
* @return
*/
PreverificationErrorType validateType(Type type) {
PreverificationErrorType errorCode =
(PreverificationErrorType) validTypes.get(type);
if (errorCode == null) {
Type objectType = getObjectType(type);
try {
Class clazz = getTypeClass(objectType);
errorCode = validateHierarchy(clazz);
} catch (ClassNotFoundException e) {
errorCode = PreverificationErrorType.MISSING_TYPE;
}
validTypes.put(type, errorCode);
}
return errorCode;
}
/**
* Validate the hierarchy to see if it is ok.
*
* @param clazz
* @return
*/
private PreverificationErrorType validateHierarchy(Class clazz) {
PreverificationErrorType error = null;
if ((clazz == null) || (clazz == objectClass)) {
error = PreverificationErrorType.NO_ERROR;
} else {
if (isDisallowedType(clazz)) {
// Assumption is that the only disallowed types are floating point types
error = PreverificationErrorType.FLOATING_POINT;
} else {
error = validateHierarchy(clazz.getSuperclass());
}
}
return error;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -