311 lines
13 KiB
Java
311 lines
13 KiB
Java
/*
|
|
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation. Oracle designates this
|
|
* particular file as subject to the "Classpath" exception as provided
|
|
* by Oracle in the LICENSE file that accompanied this code.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*IKVM*/
|
|
/*
|
|
* May 29, 2007 Modified for IKVM.NET by Jeroen Frijters
|
|
*
|
|
*/
|
|
|
|
package sun.reflect;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Modifier;
|
|
import java.security.AccessController;
|
|
import java.security.Permission;
|
|
import java.security.PrivilegedAction;
|
|
|
|
/** <P> The master factory for all reflective objects, both those in
|
|
java.lang.reflect (Fields, Methods, Constructors) as well as their
|
|
delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
|
|
</P>
|
|
|
|
<P> The methods in this class are extremely unsafe and can cause
|
|
subversion of both the language and the verifier. For this reason,
|
|
they are all instance methods, and access to the constructor of
|
|
this factory is guarded by a security check, in similar style to
|
|
{@link sun.misc.Unsafe}. </P>
|
|
*/
|
|
|
|
public class ReflectionFactory {
|
|
|
|
private static Permission reflectionFactoryAccessPerm
|
|
= new RuntimePermission("reflectionFactoryAccess");
|
|
private static ReflectionFactory soleInstance = new ReflectionFactory();
|
|
// Provides access to package-private mechanisms in java.lang.reflect
|
|
private static volatile LangReflectAccess langReflectAccess;
|
|
|
|
private ReflectionFactory() {
|
|
}
|
|
|
|
/**
|
|
* A convenience class for acquiring the capability to instantiate
|
|
* reflective objects. Use this instead of a raw call to {@link
|
|
* #getReflectionFactory} in order to avoid being limited by the
|
|
* permissions of your callers.
|
|
*
|
|
* <p>An instance of this class can be used as the argument of
|
|
* <code>AccessController.doPrivileged</code>.
|
|
*/
|
|
public static final class GetReflectionFactoryAction
|
|
implements PrivilegedAction<ReflectionFactory> {
|
|
public ReflectionFactory run() {
|
|
return getReflectionFactory();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Provides the caller with the capability to instantiate reflective
|
|
* objects.
|
|
*
|
|
* <p> First, if there is a security manager, its
|
|
* <code>checkPermission</code> method is called with a {@link
|
|
* java.lang.RuntimePermission} with target
|
|
* <code>"reflectionFactoryAccess"</code>. This may result in a
|
|
* security exception.
|
|
*
|
|
* <p> The returned <code>ReflectionFactory</code> object should be
|
|
* carefully guarded by the caller, since it can be used to read and
|
|
* write private data and invoke private methods, as well as to load
|
|
* unverified bytecodes. It must never be passed to untrusted code.
|
|
*
|
|
* @exception SecurityException if a security manager exists and its
|
|
* <code>checkPermission</code> method doesn't allow
|
|
* access to the RuntimePermission "reflectionFactoryAccess". */
|
|
public static ReflectionFactory getReflectionFactory() {
|
|
SecurityManager security = System.getSecurityManager();
|
|
if (security != null) {
|
|
// TO DO: security.checkReflectionFactoryAccess();
|
|
security.checkPermission(reflectionFactoryAccessPerm);
|
|
}
|
|
return soleInstance;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Routines used by java.lang.reflect
|
|
//
|
|
//
|
|
|
|
/** Called only by java.lang.reflect.Modifier's static initializer */
|
|
public void setLangReflectAccess(LangReflectAccess access) {
|
|
langReflectAccess = access;
|
|
}
|
|
|
|
/**
|
|
* Note: this routine can cause the declaring class for the field
|
|
* be initialized and therefore must not be called until the
|
|
* first get/set of this field.
|
|
* @param field the field
|
|
* @param override true if caller has overridden aaccessibility
|
|
*/
|
|
public native FieldAccessor newFieldAccessor(Field field, boolean override);
|
|
|
|
public native MethodAccessor newMethodAccessor(Method method);
|
|
|
|
private native ConstructorAccessor newConstructorAccessor0(Constructor c);
|
|
|
|
public ConstructorAccessor newConstructorAccessor(Constructor c) {
|
|
Class<?> declaringClass = c.getDeclaringClass();
|
|
if (Modifier.isAbstract(declaringClass.getModifiers())) {
|
|
return new InstantiationExceptionConstructorAccessorImpl(null);
|
|
}
|
|
if (declaringClass == Class.class) {
|
|
return new InstantiationExceptionConstructorAccessorImpl
|
|
("Can not instantiate java.lang.Class");
|
|
}
|
|
return newConstructorAccessor0(c);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Routines used by java.lang
|
|
//
|
|
//
|
|
|
|
/** Creates a new java.lang.reflect.Field. Access checks as per
|
|
java.lang.reflect.AccessibleObject are not overridden. */
|
|
public Field newField(Class<?> declaringClass,
|
|
String name,
|
|
Class<?> type,
|
|
int modifiers,
|
|
int slot,
|
|
String signature,
|
|
byte[] annotations)
|
|
{
|
|
return langReflectAccess().newField(declaringClass,
|
|
name,
|
|
type,
|
|
modifiers,
|
|
slot,
|
|
signature,
|
|
annotations);
|
|
}
|
|
|
|
/** Creates a new java.lang.reflect.Method. Access checks as per
|
|
java.lang.reflect.AccessibleObject are not overridden. */
|
|
public Method newMethod(Class<?> declaringClass,
|
|
String name,
|
|
Class<?>[] parameterTypes,
|
|
Class<?> returnType,
|
|
Class<?>[] checkedExceptions,
|
|
int modifiers,
|
|
int slot,
|
|
String signature,
|
|
byte[] annotations,
|
|
byte[] parameterAnnotations,
|
|
byte[] annotationDefault)
|
|
{
|
|
return langReflectAccess().newMethod(declaringClass,
|
|
name,
|
|
parameterTypes,
|
|
returnType,
|
|
checkedExceptions,
|
|
modifiers,
|
|
slot,
|
|
signature,
|
|
annotations,
|
|
parameterAnnotations,
|
|
annotationDefault);
|
|
}
|
|
|
|
/** Creates a new java.lang.reflect.Constructor. Access checks as
|
|
per java.lang.reflect.AccessibleObject are not overridden. */
|
|
public Constructor newConstructor(Class<?> declaringClass,
|
|
Class<?>[] parameterTypes,
|
|
Class<?>[] checkedExceptions,
|
|
int modifiers,
|
|
int slot,
|
|
String signature,
|
|
byte[] annotations,
|
|
byte[] parameterAnnotations)
|
|
{
|
|
return langReflectAccess().newConstructor(declaringClass,
|
|
parameterTypes,
|
|
checkedExceptions,
|
|
modifiers,
|
|
slot,
|
|
signature,
|
|
annotations,
|
|
parameterAnnotations);
|
|
}
|
|
|
|
/** Gets the MethodAccessor object for a java.lang.reflect.Method */
|
|
public MethodAccessor getMethodAccessor(Method m) {
|
|
return langReflectAccess().getMethodAccessor(m);
|
|
}
|
|
|
|
/** Sets the MethodAccessor object for a java.lang.reflect.Method */
|
|
public void setMethodAccessor(Method m, MethodAccessor accessor) {
|
|
langReflectAccess().setMethodAccessor(m, accessor);
|
|
}
|
|
|
|
/** Gets the ConstructorAccessor object for a
|
|
java.lang.reflect.Constructor */
|
|
public ConstructorAccessor getConstructorAccessor(Constructor c) {
|
|
return langReflectAccess().getConstructorAccessor(c);
|
|
}
|
|
|
|
/** Sets the ConstructorAccessor object for a
|
|
java.lang.reflect.Constructor */
|
|
public void setConstructorAccessor(Constructor c,
|
|
ConstructorAccessor accessor)
|
|
{
|
|
langReflectAccess().setConstructorAccessor(c, accessor);
|
|
}
|
|
|
|
/** Makes a copy of the passed method. The returned method is a
|
|
"child" of the passed one; see the comments in Method.java for
|
|
details. */
|
|
public Method copyMethod(Method arg) {
|
|
return langReflectAccess().copyMethod(arg);
|
|
}
|
|
|
|
/** Makes a copy of the passed field. The returned field is a
|
|
"child" of the passed one; see the comments in Field.java for
|
|
details. */
|
|
public Field copyField(Field arg) {
|
|
return langReflectAccess().copyField(arg);
|
|
}
|
|
|
|
/** Makes a copy of the passed constructor. The returned
|
|
constructor is a "child" of the passed one; see the comments
|
|
in Constructor.java for details. */
|
|
public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
|
|
return langReflectAccess().copyConstructor(arg);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Routines used by serialization
|
|
//
|
|
//
|
|
|
|
private static native ConstructorAccessor newConstructorAccessorForSerialization(Class classToInstantiate, Constructor constructorToCall);
|
|
|
|
public Constructor newConstructorForSerialization
|
|
(Class<?> classToInstantiate, Constructor constructorToCall)
|
|
{
|
|
// Fast path
|
|
if (constructorToCall.getDeclaringClass() == classToInstantiate) {
|
|
return constructorToCall;
|
|
}
|
|
|
|
ConstructorAccessor acc = newConstructorAccessorForSerialization(classToInstantiate, constructorToCall);
|
|
Constructor c = newConstructor(constructorToCall.getDeclaringClass(),
|
|
constructorToCall.getParameterTypes(),
|
|
constructorToCall.getExceptionTypes(),
|
|
constructorToCall.getModifiers(),
|
|
langReflectAccess().
|
|
getConstructorSlot(constructorToCall),
|
|
langReflectAccess().
|
|
getConstructorSignature(constructorToCall),
|
|
langReflectAccess().
|
|
getConstructorAnnotations(constructorToCall),
|
|
langReflectAccess().
|
|
getConstructorParameterAnnotations(constructorToCall));
|
|
setConstructorAccessor(c, acc);
|
|
return c;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Internals only below this point
|
|
//
|
|
|
|
private static LangReflectAccess langReflectAccess() {
|
|
if (langReflectAccess == null) {
|
|
// Call a static method to get class java.lang.reflect.Modifier
|
|
// initialized. Its static initializer will cause
|
|
// setLangReflectAccess() to be called from the context of the
|
|
// java.lang.reflect package.
|
|
Modifier.isPublic(Modifier.PUBLIC);
|
|
}
|
|
return langReflectAccess;
|
|
}
|
|
}
|