/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang.reflect;
import java.lang.annotation.Annotation;
import org.jikesrvm.classloader.RVMClass;
import org.jikesrvm.classloader.RVMMember;
import org.jikesrvm.classloader.RVMMethod;
import org.jikesrvm.classloader.TypeReference;
import org.jikesrvm.runtime.ReflectionBase;
import org.jikesrvm.runtime.RuntimeEntrypoints;
import org.jikesrvm.runtime.Reflection;
/**
* This class must be implemented by the VM vendor. This class models a
* constructor. Information about the constructor can be accessed, and the
* constructor can be invoked dynamically.
*
*/
public final class Constructor<T> extends AccessibleObject implements GenericDeclaration, Member {
/**
* Data being wrapped by the Constructor API
*/
private final RVMMethod vmConstructor;
/**
* Possible reflective method invoker
*/
private final ReflectionBase invoker;
/**
* Constructor
*/
Constructor(RVMMethod vmConstructor){
this.vmConstructor = vmConstructor;
if (Reflection.cacheInvokerInJavaLangReflect) {
invoker = vmConstructor.getInvoker();
} else {
invoker = null;
}
}
/**
* Prevent this class from being instantiated
*/
private Constructor(){
//do nothing
this.vmConstructor = null;
invoker = null;
}
public TypeVariable<Constructor<T>>[] getTypeParameters() {
throw new Error("TODO");
}
/**
* <p>
* Returns the String representation of the constructor's declaration,
* including the type parameters.
* </p>
*
* @return An instance of String.
* @since 1.5
*/
public String toGenericString() {
throw new Error("TODO");
}
/**
* <p>
* Gets the parameter types as an array of {@link Type} instances, in
* declaration order. If the constructor has no parameters, then an empty
* array is returned.
* </p>
*
* @return An array of {@link Type} instances.
* @throws GenericSignatureFormatError if the generic method signature is
* invalid.
* @throws TypeNotPresentException if the component type points to a missing
* type.
* @throws MalformedParameterizedTypeException if the component type points
* to a type that can't be instantiated for some reason.
* @since 1.5
*/
public Type[] getGenericParameterTypes() {
throw new Error("TODO");
}
/**
* <p>
* Gets the exception types as an array of {@link Type} instances. If the
* constructor has no declared exceptions, then an empty array is returned.
* </p>
*
* @return An array of {@link Type} instances.
* @throws GenericSignatureFormatError if the generic method signature is
* invalid.
* @throws TypeNotPresentException if the component type points to a missing
* type.
* @throws MalformedParameterizedTypeException if the component type points
* to a type that can't be instantiated for some reason.
* @since 1.5
*/
public Type[] getGenericExceptionTypes() {
throw new Error("TODO");
}
/**
* <p>
* Gets an array of arrays that represent the annotations of the formal
* parameters of this constructor. If there are no parameters on this
* constructor, then an empty array is returned. If there are no annotations
* set, then and array of empty arrays is returned.
* </p>
*
* @return An array of arrays of {@link Annotation} instances.
* @since 1.5
*/
public Annotation[][] getParameterAnnotations() {
return super.getParameterAnnotations();
}
/**
* <p>
* Indicates whether or not this constructor takes a variable number
* argument.
* </p>
*
* @return A value of <code>true</code> if a vararg is declare, otherwise
* <code>false</code>.
* @since 1.5
*/
public boolean isVarArgs() {
return super.isVarArgs();
}
public boolean isSynthetic() {
return super.isSynthetic();
}
/**
* Compares the specified object to this Constructor and answer if they are
* equal. The object must be an instance of Constructor with the same
* defining class and parameter types.
*
* @param object the object to compare
* @return true if the specified object is equal to this Constructor, false
* otherwise
* @see #hashCode
*/
@Override
public boolean equals(Object object) {
if (object instanceof Constructor) {
Constructor that = (Constructor)object;
return this.vmConstructor == that.vmConstructor;
} else {
return false;
}
}
/**
* Return the {@link Class} associated with the class that defined this
* constructor.
*
* @return the declaring class
*/
public Class<T> getDeclaringClass() {
return (Class<T>)vmConstructor.getDeclaringClass().getClassForType();
}
/**
* Return an array of the {@link Class} objects associated with the
* exceptions declared to be thrown by this constructor. If the constructor
* was not declared to throw any exceptions, the array returned will be
* empty.
*
* @return the declared exception classes
*/
public Class<?>[] getExceptionTypes() {
return super.getExceptionTypes();
}
/**
* Return the modifiers for the modeled constructor. The Modifier class
* should be used to decode the result.
*
* @return the modifiers
* @see java.lang.reflect.Modifier
*/
public int getModifiers() {
return super.getModifiers();
}
/**
* Return the name of the modeled constructor. This is the name of the
* declaring class.
*
* @return the name
*/
public String getName() {
return getDeclaringClass().getName();
}
/**
* Return an array of the {@link Class} objects associated with the
* parameter types of this constructor. If the constructor was declared with
* no parameters, the array returned will be empty.
*
* @return the parameter types
*/
public Class<?>[] getParameterTypes() {
return VMCommonLibrarySupport.typesToClasses(vmConstructor.getParameterTypes());
}
/**
* Answers an integer hash code for the receiver. Objects which are equal
* answer the same value for this method. The hash code for a Constructor is
* the hash code of the declaring class' name.
*
* @return the receiver's hash
* @see #equals
*/
@Override
public int hashCode() {
return getName().hashCode();
}
/**
* Return a new instance of the declaring class, initialized by dynamically
* invoking the modeled constructor. This reproduces the effect of
* <code>new declaringClass(arg1, arg2, ... , argN)</code> This method
* performs the following:
* <ul>
* <li>A new instance of the declaring class is created. If the declaring
* class cannot be instantiated (i.e. abstract class, an interface, an array
* type, or a base type) then an InstantiationException is thrown.</li>
* <li>If this Constructor object is enforcing access control (see
* AccessibleObject) and the modeled constructor is not accessible from the
* current context, an IllegalAccessException is thrown.</li>
* <li>If the number of arguments passed and the number of parameters do
* not match, an IllegalArgumentException is thrown.</li>
* <li>For each argument passed:
* <ul>
* <li>If the corresponding parameter type is a base type, the argument is
* unwrapped. If the unwrapping fails, an IllegalArgumentException is
* thrown.</li>
* <li>If the resulting argument cannot be converted to the parameter type
* via a widening conversion, an IllegalArgumentException is thrown.</li>
* </ul>
* <li>The modeled constructor is then invoked. If an exception is thrown
* during the invocation, it is caught and wrapped in an
* InvocationTargetException. This exception is then thrown. If the
* invocation completes normally, the newly initialized object is returned.
* </ul>
*
* @param args the arguments to the constructor
* @return the new, initialized, object
* @exception java.lang.InstantiationException if the class cannot be
* instantiated
* @exception java.lang.IllegalAccessException if the modeled constructor
* is not accessible
* @exception java.lang.IllegalArgumentException if an incorrect number of
* arguments are passed, or an argument could not be converted by
* a widening conversion
* @exception java.lang.reflect.InvocationTargetException if an exception
* was thrown by the invoked constructor
* @see java.lang.reflect.AccessibleObject
*/
public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
return (T)VMCommonLibrarySupport.construct(vmConstructor, this, args, RVMClass.getClassFromStackFrame(1), invoker);
}
/**
* Answers a string containing a concise, human-readable description of the
* receiver. The format of the string is modifiers (if any) declaring class
* name '(' parameter types, separated by ',' ')' If the constructor throws
* exceptions, ' throws ' exception types, separated by ',' For example:
* <code>public String(byte[],String) throws UnsupportedEncodingException</code>
*
* @return a printable representation for the receiver
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder(80);
// append modifiers if any
int modifier = getModifiers();
if (modifier != 0) {
// VARARGS incorrectly recognized
final int MASK = ~Modifier.VARARGS;
sb.append(Modifier.toString(modifier & MASK)).append(' ');
}
// append constructor name
appendArrayType(sb, getDeclaringClass());
// append parameters
sb.append('(');
appendArrayType(sb, getParameterTypes());
sb.append(')');
// append exeptions if any
Class[] exn = getExceptionTypes();
if (exn.length > 0) {
sb.append(" throws ");
appendSimpleType(sb, exn);
}
return sb.toString();
}
/* ---- Non-API methods ---- */
/**
* Set the accessibilty to the value of flag performing a check on the constructor.
*/
@Override
void setAccessible0(boolean flag) {
if (flag && getDeclaringClass() == Class.class) {
throw new SecurityException("Can not make the java.lang.Class class constructor accessible");
}
super.setAccessible0(flag);
}
/**
* Get the VM member implementation. Package protected to stop outside use.
*/
@Override
RVMMember getVMMember() {
return vmConstructor;
}
/**
* Get the VM method implementation, invalid for fields. Package protected to
* stop outside use.
*/
@Override
RVMMethod getVMMethod() {
return vmConstructor;
}
}