From: <ls...@us...> - 2008-12-14 22:22:13
|
Revision: 4788 http://jnode.svn.sourceforge.net/jnode/?rev=4788&view=rev Author: lsantha Date: 2008-12-14 21:49:21 +0000 (Sun, 14 Dec 2008) Log Message: ----------- Intgerated java.lang.reflect.Constructor from OpenJDK. Modified Paths: -------------- trunk/core/src/classpath/vm/java/lang/Thread.java trunk/core/src/classpath/vm/java/lang/reflect/Method.java trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java trunk/core/src/openjdk/java/java/lang/ThreadGroup.java trunk/core/src/openjdk/vm/sun/reflect/NativeNativeConstructorAccessorImpl.java Added Paths: ----------- trunk/core/src/openjdk/java/java/lang/reflect/Constructor.java Removed Paths: ------------- trunk/core/src/classpath/vm/java/lang/reflect/Constructor.java Modified: trunk/core/src/classpath/vm/java/lang/Thread.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/Thread.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/classpath/vm/java/lang/Thread.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -41,6 +41,7 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.HashMap; +import java.lang.reflect.Constructor; import org.jnode.security.JNodePermission; @@ -1365,7 +1366,13 @@ static { ThreadGroup g = null; try { - g = ThreadGroup.class.getDeclaredConstructor().newInstance(); + /* + Constructor<ThreadGroup> constr = ThreadGroup.class.getDeclaredConstructor(); + constr.setAccessible(true); + g = constr.newInstance(); + constr.setAccessible(false); + */ + g = new ThreadGroup(); }catch (Exception e){ e.printStackTrace(); org.jnode.vm.Unsafe.die("Root ThreadGroup creation failure."); Deleted: trunk/core/src/classpath/vm/java/lang/reflect/Constructor.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/reflect/Constructor.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/classpath/vm/java/lang/reflect/Constructor.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -1,566 +0,0 @@ -/* java.lang.reflect.Constructor - reflection of Java constructors - Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath 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 for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.lang.reflect; - -import gnu.java.lang.ClassHelper; -import java.lang.annotation.Annotation; -import java.lang.annotation.AnnotationFormatError; -import java.util.ArrayList; - -import org.jnode.vm.VmReflection; -import org.jnode.vm.classmgr.VmExceptions; -import org.jnode.vm.classmgr.VmMethod; -import org.jnode.vm.classmgr.Signature; -import gnu.java.lang.reflect.MethodSignatureParser; - -import java.util.Arrays; -import sun.reflect.annotation.AnnotationParser; -import sun.reflect.ConstructorAccessor; - -/** - * The Constructor class represents a constructor of a class. It also allows - * dynamic creation of an object, via reflection. Invocation on Constructor - * objects knows how to do widening conversions, but throws - * {@link IllegalArgumentException} if a narrowing conversion would be - * necessary. You can query for information on this Constructor regardless - * of location, but construction access may be limited by Java language - * access controls. If you can't do it in the compiler, you can't normally - * do it here either.<p> - * - * <B>Note:</B> This class returns and accepts types as Classes, even - * primitive types; there are Class types defined that represent each - * different primitive type. They are <code>java.lang.Boolean.TYPE, - * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, - * byte.class</code>, etc. These are not to be confused with the - * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are - * real classes.<p> - * - * Also note that this is not a serializable class. It is entirely feasible - * to make it serializable using the Externalizable interface, but this is - * on Sun, not me. - * - * @author John Keiser - * @author Eric Blake <eb...@em...> - * @see Member - * @see Class - * @see java.lang.Class#getConstructor(Class[]) - * @see java.lang.Class#getDeclaredConstructor(Class[]) - * @see java.lang.Class#getConstructors() - * @see java.lang.Class#getDeclaredConstructors() - * @since 1.1 - * @status updated to 1.4 - */ -public final class Constructor<T> - extends AccessibleObject - implements GenericDeclaration, Member -{ - private Class<T> clazz; - private int slot; - - private final VmMethod vmMethod; - private ArrayList<Class> parameterTypes; - private ArrayList<Class> exceptionTypes; - - private static final int CONSTRUCTOR_MODIFIERS - = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC; - - /** - * This class is uninstantiable except from native code. - */ - public Constructor(VmMethod vmMethod) { - this.vmMethod = vmMethod; - } - - /** - * Gets the class that declared this constructor. - * @return the class that declared this member - */ - public Class<T> getDeclaringClass() - { - return (Class<T>) vmMethod.getDeclaringClass().asClass(); - } - - /** - * Gets the name of this constructor (the non-qualified name of the class - * it was declared in). - * @return the name of this constructor - */ - public String getName() - { - return getDeclaringClass().getName(); - } - - /** - * Return the raw modifiers for this constructor. In particular - * this will include the synthetic and varargs bits. - * @return the constructor's modifiers - */ - private int getModifiersInternal() - { - return vmMethod.getModifiers(); - } - - /** - * Gets the modifiers this constructor uses. Use the <code>Modifier</code> - * class to interpret the values. A constructor can only have a subset of the - * following modifiers: public, private, protected. - * - * @return an integer representing the modifiers to this Member - * @see Modifier - */ - public int getModifiers() - { - return getModifiersInternal() & CONSTRUCTOR_MODIFIERS; - } - - /** - * Return true if this constructor is synthetic, false otherwise. - * A synthetic member is one which is created by the compiler, - * and which does not appear in the user's source code. - * @since 1.5 - */ - public boolean isSynthetic() - { - return (getModifiersInternal() & Modifier.SYNTHETIC) != 0; - } - - /** - * Return true if this is a varargs constructor, that is if - * the constructor takes a variable number of arguments. - * @since 1.5 - */ - public boolean isVarArgs() - { - return (getModifiersInternal() & Modifier.VARARGS) != 0; - } - - /** - * Get the parameter list for this constructor, in declaration order. If the - * constructor takes no parameters, returns a 0-length array (not null). - * - * @return a list of the types of the constructor's parameters - */ - public Class<?>[] getParameterTypes() - { - if (parameterTypes == null) { - int cnt = vmMethod.getNoArguments(); - ArrayList<Class> list = new ArrayList<Class>(cnt); - for (int i = 0; i < cnt; i++) { - list.add(vmMethod.getArgumentType(i).asClass()); - } - parameterTypes = list; - } - return (Class[])parameterTypes.toArray(new Class[parameterTypes.size()]); - } - - /** - * Get the exception types this constructor says it throws, in no particular - * order. If the constructor has no throws clause, returns a 0-length array - * (not null). - * - * @return a list of the types in the constructor's throws clause - */ - public Class<?>[] getExceptionTypes() { - if (exceptionTypes == null) { - final VmExceptions exceptions = vmMethod.getExceptions(); - final int cnt = exceptions.getLength(); - final ArrayList<Class> list = new ArrayList<Class>(cnt); - for (int i = 0; i < cnt; i++) { - list.add(exceptions.getException(i).getResolvedVmClass().asClass()); - } - exceptionTypes = list; - } - return (Class[])exceptionTypes.toArray(new Class[exceptionTypes.size()]); - } - - /** - * Compare two objects to see if they are semantically equivalent. - * Two Constructors are semantically equivalent if they have the same - * declaring class and the same parameter list. This ignores different - * exception clauses, but since you can't create a Method except through the - * VM, this is just the == relation. - * - * @param o the object to compare to - * @return <code>true</code> if they are equal; <code>false</code> if not. - */ - public boolean equals(Object o) - { - if (!(o instanceof Constructor)) - return false; - Constructor that = (Constructor)o; - if (this.getDeclaringClass() != that.getDeclaringClass()) - return false; - if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes())) - return false; - return true; - } - - /** - * Get the hash code for the Constructor. The Constructor hash code is the - * hash code of the declaring class's name. - * - * @return the hash code for the object - */ - public int hashCode() - { - return getDeclaringClass().getName().hashCode(); - } - - /** - * Get a String representation of the Constructor. A Constructor's String - * representation is "<modifier> <classname>(<paramtypes>) - * throws <exceptions>", where everything after ')' is omitted if - * there are no exceptions.<br> Example: - * <code>public java.io.FileInputStream(java.lang.Runnable) - * throws java.io.FileNotFoundException</code> - * - * @return the String representation of the Constructor - */ - public String toString() { - // 128 is a reasonable buffer initial size for constructor - StringBuilder sb = new StringBuilder(128); - sb.append(Modifier.toString(getModifiers())).append(' '); - sb.append(getDeclaringClass().getName()).append('('); - Class[] c = getParameterTypes(); - if (c.length > 0) - { - sb.append(ClassHelper.getUserName(c[0])); - for (int i = 1; i < c.length; i++) - sb.append(',').append(ClassHelper.getUserName(c[i])); - } - sb.append(')'); - c = getExceptionTypes(); - if (c.length > 0) { - sb.append(" throws ").append(c[0].getName()); - for (int i = 1; i < c.length; i++) - sb.append(',').append(c[i].getName()); - } - return sb.toString(); - } - - static <X extends GenericDeclaration> - void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs) - { - if (typeArgs.length == 0) - return; - sb.append('<'); - for (int i = 0; i < typeArgs.length; ++i) - { - if (i > 0) - sb.append(','); - sb.append(typeArgs[i]); - } - sb.append("> "); - } - - public String toGenericString() - { - StringBuilder sb = new StringBuilder(128); - sb.append(Modifier.toString(getModifiers())).append(' '); - addTypeParameters(sb, getTypeParameters()); - sb.append(getDeclaringClass().getName()).append('('); - Type[] types = getGenericParameterTypes(); - if (types.length > 0) - { - sb.append(types[0]); - for (int i = 1; i < types.length; ++i) - sb.append(',').append(types[i]); - } - sb.append(')'); - types = getGenericExceptionTypes(); - if (types.length > 0) - { - sb.append(" throws ").append(types[0]); - for (int i = 1; i < types.length; i++) - sb.append(',').append(types[i]); - } - return sb.toString(); - } - - /** - * Create a new instance by invoking the constructor. Arguments are - * automatically unwrapped and widened, if needed.<p> - * - * If this class is abstract, you will get an - * <code>InstantiationException</code>. If the constructor takes 0 - * arguments, you may use null or a 0-length array for <code>args</code>.<p> - * - * If this Constructor enforces access control, your runtime context is - * evaluated, and you may have an <code>IllegalAccessException</code> if - * you could not create this object in similar compiled code. If the class - * is uninitialized, you trigger class initialization, which may end in a - * <code>ExceptionInInitializerError</code>.<p> - * - * Then, the constructor is invoked. If it completes normally, the return - * value will be the new object. If it completes abruptly, the exception is - * wrapped in an <code>InvocationTargetException</code>. - * - * @param args the arguments to the constructor - * @return the newly created object - * @throws IllegalAccessException if the constructor could not normally be - * called by the Java code (i.e. it is not public) - * @throws IllegalArgumentException if the number of arguments is incorrect; - * or if the arguments types are wrong even with a widening - * conversion - * @throws InstantiationException if the class is abstract - * @throws InvocationTargetException if the constructor throws an exception - * @throws ExceptionInInitializerError if construction triggered class - * initialization, which then failed - */ - public T newInstance(Object... args) throws InstantiationException, IllegalAccessException, InvocationTargetException { - if(constructorAccessor == null) - return (T) VmReflection.newInstance(vmMethod, args); - else - return (T) constructorAccessor.newInstance(args); - } - - - /** - * Returns an array of <code>TypeVariable</code> objects that represents - * the type variables declared by this constructor, in declaration order. - * An array of size zero is returned if this constructor has no type - * variables. - * - * @return the type variables associated with this constructor. - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public TypeVariable<Constructor<T>>[] getTypeParameters() - { - String sig = getSignature(); - if (sig == null) - return new TypeVariable[0]; - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getTypeParameters(); - } - - /** - * Return the String in the Signature attribute for this constructor. If there - * is no Signature attribute, return null. - */ - String getSignature() - { - return vmMethod.getSignature(); - } - - /** - * Returns an array of <code>Type</code> objects that represents - * the exception types declared by this constructor, in declaration order. - * An array of size zero is returned if this constructor declares no - * exceptions. - * - * @return the exception types declared by this constructor. - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public Type[] getGenericExceptionTypes() - { - String sig = getSignature(); - if (sig == null) - return getExceptionTypes(); - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getGenericExceptionTypes(); - } - - /** - * Returns an array of <code>Type</code> objects that represents - * the parameter list for this constructor, in declaration order. - * An array of size zero is returned if this constructor takes no - * parameters. - * - * @return a list of the types of the constructor's parameters - * @throws GenericSignatureFormatError if the generic signature does - * not conform to the format specified in the Virtual Machine - * specification, version 3. - * @since 1.5 - */ - public Type[] getGenericParameterTypes() - { - String sig = getSignature(); - if (sig == null) - return getParameterTypes(); - MethodSignatureParser p = new MethodSignatureParser(this, sig); - return p.getGenericParameterTypes(); - } - - - /** - * @see java.lang.reflect.AnnotatedElement#getAnnotation(java.lang.Class) - */ - public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { - return vmMethod.getAnnotation(annotationClass); - } - - /** - * @see java.lang.reflect.AnnotatedElement#getAnnotations() - */ - public Annotation[] getAnnotations() { - return vmMethod.getAnnotations(); - } - - /** - * @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotations() - */ - public Annotation[] getDeclaredAnnotations() { - return vmMethod.getDeclaredAnnotations(); - } - - - /** - * @see java.lang.reflect.AnnotatedElement#isAnnotationPresent(java.lang.Class) - */ - public boolean isAnnotationPresent(Class< ? extends Annotation> annotationClass) { - return vmMethod.isAnnotationPresent(annotationClass); - } - - //jnode openjdk - - private byte[] parameterAnnotations; - /** - * Returns an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by - * this <tt>Constructor</tt> object. (Returns an array of length zero if the - * underlying method is parameterless. If the method has one or more - * parameters, a nested array of length zero is returned for each parameter - * with no annotations.) The annotation objects contained in the returned - * arrays are serializable. The caller of this method is free to modify - * the returned arrays; it will have no effect on the arrays returned to - * other callers. - * - * @return an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the method represented by this - * Constructor object - * @since 1.5 - */ - public Annotation[][] getParameterAnnotations() { - int numParameters = parameterTypes.size(); - if (parameterAnnotations == null) - return new Annotation[numParameters][0]; - - Annotation[][] result = AnnotationParser.parseParameterAnnotations( - parameterAnnotations, - sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - getDeclaringClass()); - if (result.length != numParameters) { - Class<?> declaringClass = getDeclaringClass(); - if (declaringClass.isEnum() || - declaringClass.isAnonymousClass() || - declaringClass.isLocalClass() ) - ; // Can't do reliable parameter counting - else { - if (!declaringClass.isMemberClass() || // top-level - // Check for the enclosing instance parameter for - // non-static member classes - (declaringClass.isMemberClass() && - ((declaringClass.getModifiers() & Modifier.STATIC) == 0) && - result.length + 1 != numParameters) ) { - throw new AnnotationFormatError( - "Parameter annotations don't match number of parameters"); - } - } - } - return result; - } - - - public Constructor(Class<T> declaringClass, Class[] parameterTypes, Class[] checkedExceptions, int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations) { - //todo implement it - String my_signature = Signature.toSignature(null, parameterTypes); - this.vmMethod = declaringClass.getVmClass().link().getDeclaredMethod("<init>", my_signature); - if(this.vmMethod == null) throw new RuntimeException("Constructor creation failure"); - - this.modifiers = modifiers; - this.slot = slot; - this.signature = signature; - this.annotations = annotations; - this.parameterAnnotations = parameterAnnotations; - } - - - private int modifiers; - // Generics and annotations support - private transient String signature; - // generic info repository; lazily initialized - private byte[] annotations; - - private volatile ConstructorAccessor constructorAccessor; - - /** - * Returns <tt>true</tt> if and only if the underlying class - * is a member class. - * - * @return <tt>true</tt> if and only if this class is a member class. - * @since 1.5 - */ - public ConstructorAccessor getConstructorAccessor() { - return constructorAccessor; - } - - public void setConstructorAccessor(ConstructorAccessor accessor) { - constructorAccessor = accessor; - // Propagate up - /* - if (root != null) { - root.setConstructorAccessor(accessor); - } - */ - } - - public int getSlot() { - return slot; - } - - public byte[] getRawAnnotations() { - return annotations; - } - - public byte[] getRawParameterAnnotations() { - return parameterAnnotations; - } - - public Constructor<T> copy() { - //todo implement it - throw new UnsupportedOperationException(); - } -} Modified: trunk/core/src/classpath/vm/java/lang/reflect/Method.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/classpath/vm/java/lang/reflect/Method.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -319,7 +319,7 @@ // 128 is a reasonable buffer initial size for constructor StringBuilder sb = new StringBuilder(128); sb.append(Modifier.toString(getModifiers())).append(' '); - Constructor.addTypeParameters(sb, getTypeParameters()); + addTypeParameters(sb, getTypeParameters()); sb.append(getGenericReturnType()).append(' '); sb.append(getDeclaringClass().getName()).append('.'); sb.append(getName()).append('('); @@ -596,4 +596,18 @@ return result; } + static <X extends GenericDeclaration> + void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs) + { + if (typeArgs.length == 0) + return; + sb.append('<'); + for (int i = 0; i < typeArgs.length; ++i) + { + if (i > 0) + sb.append(','); + sb.append(typeArgs[i]); + } + sb.append("> "); + } } Modified: trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java =================================================================== --- trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/core/org/jnode/vm/classmgr/VmMethod.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -194,7 +194,41 @@ Member javaMember = javaMemberHolder.get(); if (javaMember == null) { if (isConstructor()) { - javaMember = new Constructor(this); + //parameter types + int arg_count = getNoArguments(); + Class[] args = new Class[arg_count]; + for (int i = 0; i < arg_count; i++) { + args[i] = getArgumentType(i).asClass(); + } + + //checked exceptions + final VmExceptions exceptions = getExceptions(); + int ce_count = exceptions.getLength(); + final Class[] ces = new Class[ce_count]; + for (int i = 0; i < ce_count; i++) { + VmConstClass vmConstClass = exceptions.getException(i); + if (!vmConstClass.isResolved()) { + vmConstClass.doResolve(getDeclaringClass().getLoader()); + } + ces[i] = vmConstClass.getResolvedVmClass().asClass(); + } + + //slot + VmType decl_type = getDeclaringClass(); + int slot = -1; + for (int i = 0; i < decl_type.getNoDeclaredMethods(); i++) { + if (this == decl_type.getDeclaredMethod(i)) { + slot = i; + break; + } + } + + if (slot == -1) { + throw new ClassFormatError("Invalid constructor"); + } + + javaMember = new Constructor(getDeclaringClass().asClass(), args, ces, getModifiers(), slot, + getSignature(), getRawAnnotations(), getRawParameterAnnotations()); } else { javaMember = new Method(this); } Modified: trunk/core/src/openjdk/java/java/lang/ThreadGroup.java =================================================================== --- trunk/core/src/openjdk/java/java/lang/ThreadGroup.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/openjdk/java/java/lang/ThreadGroup.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -68,12 +68,12 @@ int ngroups; ThreadGroup groups[]; - + //jnode /** * Creates an empty Thread group that is not in any Thread group. * This method is used to create the system Thread group. */ - private ThreadGroup() { // called from C code + public ThreadGroup() { // called from C code this.name = "system"; this.maxPriority = Thread.MAX_PRIORITY; } Added: trunk/core/src/openjdk/java/java/lang/reflect/Constructor.java =================================================================== --- trunk/core/src/openjdk/java/java/lang/reflect/Constructor.java (rev 0) +++ trunk/core/src/openjdk/java/java/lang/reflect/Constructor.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -0,0 +1,691 @@ +/* + * Copyright 1996-2006 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.lang.reflect; + +import sun.reflect.ConstructorAccessor; +import sun.reflect.Reflection; +import sun.reflect.generics.repository.ConstructorRepository; +import sun.reflect.generics.factory.CoreReflectionFactory; +import sun.reflect.generics.factory.GenericsFactory; +import sun.reflect.generics.scope.ConstructorScope; +import java.lang.annotation.Annotation; +import java.util.Map; +import sun.reflect.annotation.AnnotationParser; +import java.lang.annotation.AnnotationFormatError; +import java.lang.reflect.Modifier; + +/** + * {@code Constructor} provides information about, and access to, a single + * constructor for a class. + * + * <p>{@code Constructor} permits widening conversions to occur when matching the + * actual parameters to newInstance() with the underlying + * constructor's formal parameters, but throws an + * {@code IllegalArgumentException} if a narrowing conversion would occur. + * + * @param <T> the class in which the constructor is declared + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getConstructors() + * @see java.lang.Class#getConstructor(Class[]) + * @see java.lang.Class#getDeclaredConstructors() + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final + class Constructor<T> extends AccessibleObject implements + GenericDeclaration, + Member { + + private Class<T> clazz; + private int slot; + private Class[] parameterTypes; + private Class[] exceptionTypes; + private int modifiers; + // Generics and annotations support + private transient String signature; + // generic info repository; lazily initialized + private transient ConstructorRepository genericInfo; + private byte[] annotations; + private byte[] parameterAnnotations; + + // For non-public members or members in package-private classes, + // it is necessary to perform somewhat expensive security checks. + // If the security check succeeds for a given class, it will + // always succeed (it is not affected by the granting or revoking + // of permissions); we speed up the check in the common case by + // remembering the last Class for which the check succeeded. + private volatile Class securityCheckCache; + + // Modifiers that can be applied to a constructor in source code + private static final int LANGUAGE_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; + + // Generics infrastructure + // Accessor for factory + private GenericsFactory getFactory() { + // create scope and factory + return CoreReflectionFactory.make(this, ConstructorScope.make(this)); + } + + // Accessor for generic info repository + private ConstructorRepository getGenericInfo() { + // lazily initialize repository if necessary + if (genericInfo == null) { + // create and cache generic info repository + genericInfo = + ConstructorRepository.make(getSignature(), + getFactory()); + } + return genericInfo; //return cached repository + } + + private volatile ConstructorAccessor constructorAccessor; + // For sharing of ConstructorAccessors. This branching structure + // is currently only two levels deep (i.e., one root Constructor + // and potentially many Constructor objects pointing to it.) + private Constructor<T> root; + + //jnode + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + public Constructor(Class<T> declaringClass, + Class[] parameterTypes, + Class[] checkedExceptions, + int modifiers, + int slot, + String signature, + byte[] annotations, + byte[] parameterAnnotations) + { + this.clazz = declaringClass; + this.parameterTypes = parameterTypes; + this.exceptionTypes = checkedExceptions; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + this.annotations = annotations; + this.parameterAnnotations = parameterAnnotations; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Constructor. The copy's + * "root" field points to this Constructor. + */ + Constructor<T> copy() { + // This routine enables sharing of ConstructorAccessor objects + // among Constructor objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + Constructor<T> res = new Constructor<T>(clazz, + parameterTypes, + exceptionTypes, modifiers, slot, + signature, + annotations, + parameterAnnotations); + res.root = this; + // Might as well eagerly propagate this if already present + res.constructorAccessor = constructorAccessor; + return res; + } + + /** + * Returns the {@code Class} object representing the class that declares + * the constructor represented by this {@code Constructor} object. + */ + public Class<T> getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of this constructor, as a string. This is + * always the same as the simple name of the constructor's declaring + * class. + */ + public String getName() { + return getDeclaringClass().getName(); + } + + /** + * Returns the Java language modifiers for the constructor + * represented by this {@code Constructor} object, as an integer. The + * {@code Modifier} class should be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in the Java Virtual Machine Specification, + * 3rd edition + * @since 1.5 + */ + public TypeVariable<Constructor<T>>[] getTypeParameters() { + if (getSignature() != null) { + return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters(); + } else + return (TypeVariable<Constructor<T>>[])new TypeVariable[0]; + } + + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the constructor + * represented by this {@code Constructor} object. Returns an array of + * length 0 if the underlying constructor takes no parameters. + * + * @return the parameter types for the constructor this object + * represents + */ + public Class<?>[] getParameterTypes() { + return (Class<?>[]) parameterTypes.clone(); + } + + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the method represented by + * this {@code Constructor} object. Returns an array of length 0 if the + * underlying method takes no parameters. + * + * <p>If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + * <p>If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of {@code Type}s that represent the formal + * parameter types of the underlying method, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in the Java Virtual Machine Specification, 3rd edition + * @throws TypeNotPresentException if any of the parameter + * types of the underlying method refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying method's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericParameterTypes() { + if (getSignature() != null) + return getGenericInfo().getParameterTypes(); + else + return getParameterTypes(); + } + + + /** + * Returns an array of {@code Class} objects that represent the types + * of exceptions declared to be thrown by the underlying constructor + * represented by this {@code Constructor} object. Returns an array of + * length 0 if the constructor declares no exceptions in its {@code throws} clause. + * + * @return the exception types declared as being thrown by the + * constructor this object represents + */ + public Class<?>[] getExceptionTypes() { + return (Class<?>[])exceptionTypes.clone(); + } + + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this {@code Constructor} object. + * Returns an array of length 0 if the underlying method declares + * no exceptions in its {@code throws} clause. + * + * <p>If an exception type is a parameterized type, the {@code Type} + * object returned for it must accurately reflect the actual type + * parameters used in the source code. + * + * <p>If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in the Java Virtual Machine Specification, 3rd edition + * @throws TypeNotPresentException if the underlying method's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying method's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericExceptionTypes() { + Type[] result; + if (getSignature() != null && + ( (result = getGenericInfo().getExceptionTypes()).length > 0 )) + return result; + else + return getExceptionTypes(); + } + + /** + * Compares this {@code Constructor} against the specified object. + * Returns true if the objects are the same. Two {@code Constructor} objects are + * the same if they were declared by the same class and have the + * same formal parameter types. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Constructor) { + Constructor other = (Constructor)obj; + if (getDeclaringClass() == other.getDeclaringClass()) { + /* Avoid unnecessary cloning */ + Class[] params1 = parameterTypes; + Class[] params2 = other.parameterTypes; + if (params1.length == params2.length) { + for (int i = 0; i < params1.length; i++) { + if (params1[i] != params2[i]) + return false; + } + return true; + } + } + } + return false; + } + + /** + * Returns a hashcode for this {@code Constructor}. The hashcode is + * the same as the hashcode for the underlying constructor's + * declaring class name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode(); + } + + /** + * Returns a string describing this {@code Constructor}. The string is + * formatted as the constructor access modifiers, if any, + * followed by the fully-qualified name of the declaring class, + * followed by a parenthesized, comma-separated list of the + * constructor's formal parameter types. For example: + * <pre> + * public java.util.Hashtable(int,float) + * </pre> + * + * <p>The only possible modifiers for constructors are the access + * modifiers {@code public}, {@code protected} or + * {@code private}. Only one of these may appear, or none if the + * constructor has default (package) access. + */ + public String toString() { + try { + StringBuffer sb = new StringBuffer(); + int mod = getModifiers() & LANGUAGE_MODIFIERS; + if (mod != 0) { + sb.append(Modifier.toString(mod) + " "); + } + sb.append(Field.getTypeName(getDeclaringClass())); + sb.append("("); + Class[] params = parameterTypes; // avoid clone + for (int j = 0; j < params.length; j++) { + sb.append(Field.getTypeName(params[j])); + if (j < (params.length - 1)) + sb.append(","); + } + sb.append(")"); + Class[] exceptions = exceptionTypes; // avoid clone + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append(exceptions[k].getName()); + if (k < (exceptions.length - 1)) + sb.append(","); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Returns a string describing this {@code Constructor}, + * including type parameters. The string is formatted as the + * constructor access modifiers, if any, followed by an + * angle-bracketed comma separated list of the constructor's type + * parameters, if any, followed by the fully-qualified name of the + * declaring class, followed by a parenthesized, comma-separated + * list of the constructor's generic formal parameter types. + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the constructor is declared to throw + * exceptions, the parameter list is followed by a space, followed + * by the word "{@code throws}" followed by a + * comma-separated list of the thrown exception types. + * + * <p>The only possible modifiers for constructors are the access + * modifiers {@code public}, {@code protected} or + * {@code private}. Only one of these may appear, or none if the + * constructor has default (package) access. + * + * @return a string describing this {@code Constructor}, + * include type parameters + * + * @since 1.5 + */ + public String toGenericString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & LANGUAGE_MODIFIERS; + if (mod != 0) { + sb.append(Modifier.toString(mod) + " "); + } + TypeVariable<?>[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append("<"); + for(TypeVariable<?> typeparm: typeparms) { + if (!first) + sb.append(","); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + sb.append(Field.getTypeName(getDeclaringClass())); + sb.append("("); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = (params[j] instanceof Class<?>)? + Field.getTypeName((Class<?>)params[j]): + (params[j].toString()); + sb.append(param); + if (j < (params.length - 1)) + sb.append(","); + } + sb.append(")"); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(","); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Uses the constructor represented by this {@code Constructor} object to + * create and initialize a new instance of the constructor's + * declaring class, with the specified initialization parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as necessary. + * + * <p>If the number of formal parameters required by the underlying constructor + * is 0, the supplied {@code initargs} array may be of length 0 or null. + * + * <p>If the constructor's declaring class is an inner class in a + * non-static context, the first argument to the constructor needs + * to be the enclosing instance; see <i>The Java Language + * Specification</i>, section 15.9.3. + * + * <p>If the required access and argument checks succeed and the + * instantiation will proceed, the constructor's declaring class + * is initialized if it has not already been initialized. + * + * <p>If the constructor completes normally, returns the newly + * created and initialized instance. + * + * @param initargs array of objects to be passed as arguments to + * the constructor call; values of primitive types are wrapped in + * a wrapper object of the appropriate type (e.g. a {@code float} + * in a {@link java.lang.Float Float}) + * + * @return a new object created by calling the constructor + * this object represents + * + * @exception IllegalAccessException if this {@code Constructor} object + * enforces Java language access control and the underlying + * constructor is inaccessible. + * @exception IllegalArgumentException if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion; if + * this constructor pertains to an enum type. + * @exception InstantiationException if the class that declares the + * underlying constructor represents an abstract class. + * @exception InvocationTargetException if the underlying constructor + * throws an exception. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + public T newInstance(Object ... initargs) + throws InstantiationException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException + { + if (!override) { + if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { + Class caller = Reflection.getCallerClass(2); + if (securityCheckCache != caller) { + Reflection.ensureMemberAccess(caller, clazz, null, modifiers); + securityCheckCache = caller; + } + } + } + if ((clazz.getModifiers() & Modifier.ENUM) != 0) + throw new IllegalArgumentException("Cannot reflectively create enum objects"); + if (constructorAccessor == null) acquireConstructorAccessor(); + return (T) constructorAccessor.newInstance(initargs); + } + + /** + * Returns {@code true} if this constructor was declared to take + * a variable number of arguments; returns {@code false} + * otherwise. + * + * @return {@code true} if an only if this constructor was declared to + * take a variable number of arguments. + * @since 1.5 + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this constructor is a synthetic + * constructor; returns {@code false} otherwise. + * + * @return true if and only if this constructor is a synthetic + * constructor as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + // NOTE that there is no synchronization used here. It is correct + // (though not efficient) to generate more than one + // ConstructorAccessor for a given Constructor. However, avoiding + // synchronization will probably make the implementation more + // scalable. + private void acquireConstructorAccessor() { + // First check to see if one has been created yet, and take it + // if so. + ConstructorAccessor tmp = null; + if (root != null) tmp = root.getConstructorAccessor(); + if (tmp != null) { + constructorAccessor = tmp; + return; + } + // Otherwise fabricate one and propagate it up to the root + tmp = reflectionFactory.newConstructorAccessor(this); + setConstructorAccessor(tmp); + } + + // Returns ConstructorAccessor for this Constructor object, not + // looking up the chain to the root + ConstructorAccessor getConstructorAccessor() { + return constructorAccessor; + } + + // Sets the ConstructorAccessor for this Constructor object and + // (recursively) its root + void setConstructorAccessor(ConstructorAccessor accessor) { + constructorAccessor = accessor; + // Propagate up + if (root != null) { + root.setConstructorAccessor(accessor); + } + } + + //jnode + public int getSlot() { + return slot; + } + + String getSignature() { + return signature; + } + + byte[] getRawAnnotations() { + return annotations; + } + + byte[] getRawParameterAnnotations() { + return parameterAnnotations; + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { + if (annotationClass == null) + throw new NullPointerException(); + + return (T) declaredAnnotations().get(annotationClass); + } + + private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0]; + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY); + } + + private transient Map<Class, Annotation> declaredAnnotations; + + private synchronized Map<Class, Annotation> declaredAnnotations() { + if (declaredAnnotations == null) { + declaredAnnotations = AnnotationParser.parseAnnotations( + annotations, sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + getDeclaringClass()); + } + return declaredAnnotations; + } + + /** + * Returns an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by + * this {@code Constructor} object. (Returns an array of length zero if the + * underlying method is parameterless. If the method has one or more + * parameters, a nested array of length zero is returned for each parameter + * with no annotations.) The annotation objects contained in the returned + * arrays are serializable. The caller of this method is free to modify + * the returned arrays; it will have no effect on the arrays returned to + * other callers. + * + * @return an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by this + * Constructor object + * @since 1.5 + */ + public Annotation[][] getParameterAnnotations() { + int numParameters = parameterTypes.length; + if (parameterAnnotations == null) + return new Annotation[numParameters][0]; + + Annotation[][] result = AnnotationParser.parseParameterAnnotations( + parameterAnnotations, + sun.misc.SharedSecrets.getJavaLangAccess(). + getConstantPool(getDeclaringClass()), + getDeclaringClass()); + if (result.length != numParameters) { + Class<?> declaringClass = getDeclaringClass(); + if (declaringClass.isEnum() || + declaringClass.isAnonymousClass() || + declaringClass.isLocalClass() ) + ; // Can't do reliable parameter counting + else { + if (!declaringClass.isMemberClass() || // top-level + // Check for the enclosing instance parameter for + // non-static member classes + (declaringClass.isMemberClass() && + ((declaringClass.getModifiers() & Modifier.STATIC) == 0) && + result.length + 1 != numParameters) ) { + throw new AnnotationFormatError( + "Parameter annotations don't match number of parameters"); + } + } + } + return result; + } +} Modified: trunk/core/src/openjdk/vm/sun/reflect/NativeNativeConstructorAccessorImpl.java =================================================================== --- trunk/core/src/openjdk/vm/sun/reflect/NativeNativeConstructorAccessorImpl.java 2008-12-13 21:11:59 UTC (rev 4787) +++ trunk/core/src/openjdk/vm/sun/reflect/NativeNativeConstructorAccessorImpl.java 2008-12-14 21:49:21 UTC (rev 4788) @@ -1,6 +1,10 @@ package sun.reflect; import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import org.jnode.vm.classmgr.VmType; +import org.jnode.vm.classmgr.VmMethod; +import org.jnode.vm.VmReflection; /** * @see sun.reflect.NativeConstructorAccessorImpl @@ -9,8 +13,16 @@ /** * @see sun.reflect.NativeConstructorAccessorImpl#newInstance0(java.lang.reflect.Constructor, java.lang.Object[]) */ - private static Object newInstance0(Constructor arg1, Object[] arg2) { - //todo implement it - throw new UnsupportedOperationException(); + private static Object newInstance0(Constructor arg1, Object[] arg2) throws InstantiationException, + IllegalArgumentException, + InvocationTargetException{ + VmType vmt = arg1.getDeclaringClass().getVmClass(); + VmMethod vmm = vmt.getDeclaredMethod(arg1.getSlot()); + try { + return VmReflection.newInstance(vmm, arg2); + } catch (IllegalAccessException iae) { //todo| this should not happen, fix VmReflection.newInstance() to not + //todo| throw this exception + throw new InstantiationException("Unexpected IllegalAccessException"); + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |