/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package java.lang.reflect;
import org.jikesrvm.objectmodel.VM_ObjectModel;
import org.jikesrvm.runtime.VM_Runtime;
import org.jikesrvm.classloader.*;
/**
* Library support interface of Jikes RVM
*/
public class JikesRVMSupport {
/**
* Convert from "vm" type system to "jdk" type system.
*/
static Class<?>[] typesToClasses(VM_TypeReference[] types) {
Class<?>[] classes = new Class[types.length];
for (int i = 0; i < types.length; i++) {
}
return classes;
}
// Make possibly wrapped method argument compatible with expected type
// throwing IllegalArgumentException if it cannot be.
//
@SuppressWarnings({"UnnecessaryBoxing","PMD.IntegerInstantiation"})
static Object makeArgumentCompatible(VM_Type expectedType, Object arg) {
if (expectedType.isPrimitiveType()) {
if (arg instanceof java.lang.Void) {
if (expectedType.isVoidType()) return arg;
} else if (arg instanceof java.lang.Boolean) {
if (expectedType.isBooleanType()) return arg;
} else if (arg instanceof java.lang.Byte) {
if (expectedType.isByteType()) return arg;
if (expectedType.isShortType()) return new Short((Byte) arg);
if (expectedType.isIntType()) return new Integer((Byte) arg);
if (expectedType.isLongType()) return new Long((Byte) arg);
} else if (arg instanceof java.lang.Short) {
if (expectedType.isShortType()) return arg;
if (expectedType.isIntType()) return new Integer((Short) arg);
if (expectedType.isLongType()) return new Long((Short) arg);
} else if (arg instanceof java.lang.Character) {
if (expectedType.isCharType()) return arg;
if (expectedType.isIntType()) return new Integer((Character) arg);
if (expectedType.isLongType()) return new Long((Character) arg);
} else if (arg instanceof java.lang.Integer) {
if (expectedType.isIntType()) return arg;
if (expectedType.isLongType()) return new Long((Integer) arg);
} else if (arg instanceof java.lang.Long) {
if (expectedType.isLongType()) return arg;
} else if (arg instanceof java.lang.Float) {
if (expectedType.isFloatType()) return arg;
if (expectedType.isDoubleType()) return new Double((Float) arg);
} else if (arg instanceof java.lang.Double) {
if (expectedType.isDoubleType()) return arg;
}
} else {
if (arg == null) return arg; // null is always ok
VM_Type actualType = VM_ObjectModel.getObjectType(arg);
if (expectedType == actualType ||
expectedType == VM_Type.JavaLangObjectType ||
VM_Runtime.isAssignableWith(expectedType, actualType)) {
return arg;
}
}
throw new IllegalArgumentException();
}
public static Field createField(VM_Field m) {
return new Field(m);
}
public static Method createMethod(VM_Method m) {
return new Method(m);
}
@SuppressWarnings("unchecked") // Can't type-check this without <T> type<T>, which breaks javac
public static Constructor<?> createConstructor(VM_Method m) {
return new Constructor(m);
}
public static VM_Field getFieldOf(Field f) {
return f.field;
}
public static VM_Method getMethodOf(Method f) {
return f.method;
}
public static VM_Method getMethodOf(Constructor<?> f) {
return f.constructor;
}
/**
* Check to see if a method declared by the accessingClass
* should be allowed to access the argument VM_Member.
* Assumption: member is not public. This trivial case should
* be approved by the caller without needing to call this method.
*/
public static void checkAccess(VM_Member member, VM_Class accessingClass) throws IllegalAccessException {
VM_Class declaringClass = member.getDeclaringClass();
if (member.isPrivate()) {
// access from the declaringClass is allowed
if (accessingClass == declaringClass) return;
} else if (member.isProtected()) {
// access within the package is allowed.
if (declaringClass.getClassLoader() == accessingClass.getClassLoader() && declaringClass.getPackageName().equals(accessingClass.getPackageName())) return;
// access by subclasses is allowed.
for (VM_Class cls = accessingClass; cls != null; cls = cls.getSuperClass()) {
if (accessingClass == declaringClass) return;
}
} else {
// default: access within package is allowed
if (declaringClass.getClassLoader() == accessingClass.getClassLoader() && declaringClass.getPackageName().equals(accessingClass.getPackageName())) return;
}
throw new IllegalAccessException("Access to "+member+" is denied to "+accessingClass);
}
}