/*
* 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.classloader.*;
import org.jikesrvm.runtime.VM_Reflection;
import org.jikesrvm.runtime.VM_Runtime;
/**
* Implementation of java.lang.reflect.Constructor for JikesRVM.
*
* By convention, order methods in the same order
* as they appear in the method summary list of Sun's 1.4 Javadoc API.
*/
public final class Constructor<T> extends AccessibleObject
implements GenericDeclaration, Member {
final VM_Method constructor;
// Prevent this class from being instantiated.
@SuppressWarnings("unused")
private Constructor() {
constructor = null;
}
// For use by JikesRVMSupport
Constructor(VM_Method m) {
constructor = m;
}
public boolean equals(Object other) {
if (other instanceof Constructor) {
return constructor == ((Constructor<?>)other).constructor;
} else {
return false;
}
}
@SuppressWarnings("unchecked") // Type system needs to be bent a bit here
public Class<T> getDeclaringClass() {
return (Class<T>)constructor.getDeclaringClass().getClassForType();
}
public Class<?>[] getExceptionTypes() {
VM_TypeReference[] exceptionTypes = constructor.getExceptionTypes();
if (exceptionTypes == null) {
return new Class[0];
} else {
return JikesRVMSupport.typesToClasses(exceptionTypes);
}
}
public int getModifiers() {
return constructor.getModifiers();
}
public String getName() {
return getDeclaringClass().getName();
}
public Class<?>[] getParameterTypes() {
return JikesRVMSupport.typesToClasses(constructor.getParameterTypes());
}
public int hashCode() {
return getName().hashCode();
}
public boolean isSynthetic() {
return constructor.isSynthetic();
}
public Object newInstance(Object[] args) throws InstantiationException,
IllegalAccessException,
IllegalArgumentException,
InvocationTargetException {
// Check accessibility
if (!constructor.isPublic() && !isAccessible()) {
VM_Class accessingClass = VM_Class.getClassFromStackFrame(1);
JikesRVMSupport.checkAccess(constructor, accessingClass);
}
// validate number and types of arguments to constructor
VM_TypeReference[] parameterTypes = constructor.getParameterTypes();
if (args == null) {
if (parameterTypes.length != 0) {
throw new IllegalArgumentException("argument count mismatch");
}
} else {
if (args.length != parameterTypes.length) {
throw new IllegalArgumentException("argument count mismatch");
}
for (int i = 0; i < parameterTypes.length; i++) {
args[i] = JikesRVMSupport.makeArgumentCompatible(parameterTypes[i].resolve(false), args[i]);
}
}
VM_Class cls = constructor.getDeclaringClass();
if (cls.isAbstract()) {
throw new InstantiationException("Abstract class");
}
// Ensure that the class is initialized
if (!cls.isInitialized(false)) {
try {
VM_Runtime.initializeClassForDynamicLink(cls);
} catch (Throwable e) {
ExceptionInInitializerError ex = new ExceptionInInitializerError();
ex.initCause(e);
throw ex;
}
}
// Allocate an uninitialized instance;
Object obj = VM_Runtime.resolvedNewScalar(cls);
// Run the constructor on the instance.
try {
VM_Reflection.invoke(constructor, obj, args);
} catch (Throwable e) {
throw new InvocationTargetException(e);
}
return obj;
}
public String toString() {
StringBuilder sb = new StringBuilder(128);
Modifier.toString(getModifiers(), sb).append(' ');
sb.append(getDeclaringClass().getName()).append('(');
Class<?>[] c = getParameterTypes();
if (c.length > 0) {
sb.append(JikesRVMHelpers.getUserName(c[0]));
for (int i = 1; i < c.length; i++) {
sb.append(',').append(JikesRVMHelpers.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();
}
// Generics support
public TypeVariable<?>[] getTypeParameters() {
VM_Atom sig = constructor.getSignature();
if (sig == null) {
return new TypeVariable[0];
} else {
return JikesRVMHelpers.getTypeParameters(this, sig);
}
}
public Type[] getGenericExceptionTypes() {
VM_Atom sig = constructor.getSignature();
if (sig == null) {
return getExceptionTypes();
} else {
return JikesRVMHelpers.getGenericExceptionTypes(this, sig);
}
}
public Type[] getGenericParameterTypes() {
VM_Atom sig = constructor.getSignature();
if (sig == null) {
return getParameterTypes();
} else {
return JikesRVMHelpers.getGenericParameterTypes(this, sig);
}
}
public String toGenericString() {
StringBuilder sb = new StringBuilder(128);
Modifier.toString(getModifiers(), sb).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();
}
static void addTypeParameters(StringBuilder sb, TypeVariable<?>[] 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("> ");
}
}