⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preverificationclassnode.java

📁 eclipseme的最新版本的source,欢迎j2me程序员使用
💻 JAVA
字号:
/**
 * 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;");
	private static final Type VOID_TYPE = Type.getType("Ljava/lang/Void;");
	
	// 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;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -