Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.
*/
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed 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.
*/
/*
* Copyright (C) 2012 RoboVM AB
*
* Licensed 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 java.util.Arrays;
import libcore.util.EmptyArray;
import libcore.reflect.GenericSignatureParser;
import libcore.reflect.ListOfTypes;
import libcore.reflect.Types;
import com.bugvm.rt.VM;
/**
* This class represents a constructor. Information about the constructor can be
* accessed, and the constructor can be invoked dynamically.
*
* @param the class that declares this constructor
*/
public final class Constructor extends AccessibleObject implements GenericDeclaration,
Member {
/*
* The BugVM Method* object
*/
private final long method;
/*
* Cached fields
*/
private int modifiers = -1;
private Class declaringClass;
private Class>[] parameterTypes;
private Class>[] exceptionTypes;
private Annotation[] declaredAnnotations;
private Annotation[][] parameterAnnotations;
ListOfTypes genericExceptionTypes;
ListOfTypes genericParameterTypes;
TypeVariable>[] formalTypeParameters;
private volatile boolean genericTypesAreInitialized = false;
Constructor(long method){
this.method = method;
}
/**
* Construct a clone of the given instance.
*
* @param orig non-null; the original instance to clone
*/
/*package*/ Constructor(Constructor orig) {
this.method = orig.method;
this.modifiers = orig.modifiers;
this.declaringClass = orig.declaringClass;
this.parameterTypes = orig.parameterTypes;
this.exceptionTypes = orig.exceptionTypes;
this.genericExceptionTypes = orig.genericExceptionTypes;
this.genericParameterTypes = orig.genericParameterTypes;
this.formalTypeParameters = orig.formalTypeParameters;
this.genericTypesAreInitialized = orig.genericTypesAreInitialized;
this.declaredAnnotations = orig.declaredAnnotations;
this.parameterAnnotations = orig.parameterAnnotations;
// Copy the accessible flag.
if (orig.flag) {
this.flag = true;
}
}
@SuppressWarnings("unchecked")
private synchronized void initGenericTypes() {
if (!genericTypesAreInitialized) {
String signatureAttribute = getSignatureAttribute();
GenericSignatureParser parser = new GenericSignatureParser(
getDeclaringClass().getClassLoader());
parser.parseForConstructor(this, signatureAttribute, getExceptionTypes());
formalTypeParameters = parser.formalTypeParameters;
genericParameterTypes = parser.parameterTypes;
genericExceptionTypes = parser.exceptionTypes;
genericTypesAreInitialized = true;
}
}
@Override
protected String getSignatureAttribute() {
return Method.getSignatureAttribute(method);
}
public TypeVariable>[] getTypeParameters() {
initGenericTypes();
return formalTypeParameters.clone();
}
/**
* Returns the string representation of the constructor's declaration,
* including the type parameters.
*
* @return the string representation of the constructor's declaration
*/
public String toGenericString() {
StringBuilder sb = new StringBuilder(80);
initGenericTypes();
// append modifiers if any
int modifier = getModifiers();
if (modifier != 0) {
sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' ');
}
// append type parameters
if (formalTypeParameters != null && formalTypeParameters.length > 0) {
sb.append('<');
for (int i = 0; i < formalTypeParameters.length; i++) {
appendGenericType(sb, formalTypeParameters[i]);
if (i < formalTypeParameters.length - 1) {
sb.append(",");
}
}
sb.append("> ");
}
// append constructor name
appendTypeName(sb, getDeclaringClass());
// append parameters
sb.append('(');
appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
sb.append(')');
// append exceptions if any
Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
if (genericExceptionTypeArray.length > 0) {
sb.append(" throws ");
appendArrayGenericType(sb, genericExceptionTypeArray);
}
return sb.toString();
}
/**
* Returns the generic parameter types as an array of {@code Type}
* instances, in declaration order. If this constructor has no generic
* parameters, an empty array is returned.
*
* @return the parameter types
*
* @throws GenericSignatureFormatError
* if the generic constructor signature is invalid
* @throws TypeNotPresentException
* if any parameter type points to a missing type
* @throws MalformedParameterizedTypeException
* if any parameter type points to a type that cannot be
* instantiated for some reason
*/
public Type[] getGenericParameterTypes() {
initGenericTypes();
return Types.getTypeArray(genericParameterTypes, true);
}
/**
* Returns the exception types as an array of {@code Type} instances. If
* this constructor has no declared exceptions, an empty array will be
* returned.
*
* @return an array of generic exception types
*
* @throws GenericSignatureFormatError
* if the generic constructor signature is invalid
* @throws TypeNotPresentException
* if any exception type points to a missing type
* @throws MalformedParameterizedTypeException
* if any exception type points to a type that cannot be
* instantiated for some reason
*/
public Type[] getGenericExceptionTypes() {
initGenericTypes();
return Types.getTypeArray(genericExceptionTypes, true);
}
@Override
protected Annotation[] getDeclaredAnnotations(boolean copy) {
if (declaredAnnotations == null) {
declaredAnnotations = Method.getDeclaredAnnotations(method);
}
return copy ? declaredAnnotations.clone() : declaredAnnotations;
}
/**
* Returns 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 an array of empty arrays is returned.
*
* @return an array of arrays of {@code Annotation} instances
*/
public Annotation[][] getParameterAnnotations() {
if (parameterAnnotations == null) {
Annotation[][] pa = Method.getParameterAnnotations(method);
if (pa.length == 0) {
pa = Method.noAnnotations(getParameterTypes(false).length);
}
parameterAnnotations = pa;
}
return parameterAnnotations.clone();
}
/**
* Indicates whether or not this constructor takes a variable number of
* arguments.
*
* @return {@code true} if a vararg is declare, otherwise
* {@code false}
*/
public boolean isVarArgs() {
return (getModifiers() & Modifier.VARARGS) != 0;
}
/**
* Indicates whether or not this constructor is synthetic (artificially
* introduced by the compiler).
*
* @return {@code true} if this constructor is synthetic, {@code false}
* otherwise
*/
public boolean isSynthetic() {
return (getModifiers() & Modifier.SYNTHETIC) != 0;
}
/**
* Indicates whether or not the specified {@code object} is equal to this
* constructor. To be equal, the specified object must be an instance
* of {@code Constructor} with the same declaring class and parameter types
* as this constructor.
*
* @param object
* the object to compare
*
* @return {@code true} if the specified object is equal to this
* constructor, {@code false} otherwise
*
* @see #hashCode
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (!(object instanceof Constructor)) {
return false;
}
Constructor> rhs = (Constructor>) object;
return getDeclaringClass().equals(rhs.getDeclaringClass()) &&
Arrays.equals(getParameterTypes(false), rhs.getParameterTypes(false));
}
/**
* Returns the class that declares this constructor.
*
* @return the declaring class
*/
public Class getDeclaringClass() {
if (declaringClass == null) {
declaringClass = Method.getDeclaringClass(method);
}
return declaringClass;
}
/**
* Returns the exception types as an array of {@code Class} instances. If
* this constructor has no declared exceptions, an empty array will be
* returned.
*
* @return the declared exception classes
*/
public Class>[] getExceptionTypes() {
return getExceptionTypes(true);
}
Class>[] getExceptionTypes(boolean copy) {
if (exceptionTypes == null) {
exceptionTypes = Method.getExceptionTypes(method);
}
return copy ? exceptionTypes.clone() : exceptionTypes;
}
/**
* Returns the modifiers for this constructor. The {@link Modifier} class
* should be used to decode the result.
*
* @return the modifiers for this constructor
* @see Modifier
*/
public int getModifiers() {
if (modifiers == -1) {
modifiers = Method.getModifiers(method);
}
return modifiers;
}
/**
* Returns the name of this constructor.
*
* @return the name of this constructor
*/
public String getName() {
return getDeclaringClass().getName();
}
/**
* Returns an array of the {@code Class} objects associated with the
* parameter types of this constructor. If the constructor was declared with
* no parameters, an empty array will be returned.
*
* @return the parameter types
*/
public Class>[] getParameterTypes() {
return getParameterTypes(true);
}
Class>[] getParameterTypes(boolean copy) {
if (parameterTypes == null) {
parameterTypes = Method.getParameterTypes(method);
}
return copy ? parameterTypes.clone() : parameterTypes;
}
/**
* Returns the constructor's signature in non-printable form. This is called
* (only) from IO native code and needed for deriving the serialVersionUID
* of the class
*
* @return the constructor's signature
*/
@SuppressWarnings("unused")
private String getSignature() {
Class>[] parameterTypes = getParameterTypes(false);
StringBuilder result = new StringBuilder();
result.append('(');
for (int i = 0; i < parameterTypes.length; i++) {
result.append(getSignature(parameterTypes[i]));
}
result.append(")V");
return result.toString();
}
/**
* Returns an integer hash code for this constructor. Constructors which are
* equal return the same value for this method. The hash code for a
* Constructor is the hash code of the name of the declaring class.
*
* @return the hash code
*
* @see #equals
*/
@Override
public int hashCode() {
return getDeclaringClass().getName().hashCode();
}
/**
* Returns a new instance of the declaring class, initialized by dynamically
* invoking the constructor represented by this {@code Constructor} object.
* This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
* argN)} This method performs the following:
*
*
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 primitive type) then an InstantiationException is thrown.
*
If this Constructor object is enforcing access control (see
* {@link AccessibleObject}) and this constructor is not accessible from the
* current context, an IllegalAccessException is thrown.
*
If the number of arguments passed and the number of parameters do not
* match, an IllegalArgumentException is thrown.
*
For each argument passed:
*
*
If the corresponding parameter type is a primitive type, the argument
* is unboxed. If the unboxing fails, an IllegalArgumentException is
* thrown.
*
If the resulting argument cannot be converted to the parameter type
* via a widening conversion, an IllegalArgumentException is thrown.
*
*
The constructor represented by this {@code Constructor} object 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.
*
*
* @param args
* the arguments to the constructor
*
* @return the new, initialized, object
*
* @exception InstantiationException
* if the class cannot be instantiated
* @exception IllegalAccessException
* if this constructor is not accessible
* @exception IllegalArgumentException
* if an incorrect number of arguments are passed, or an
* argument could not be converted by a widening conversion
* @exception InvocationTargetException
* if an exception was thrown by the invoked constructor
*
* @see AccessibleObject
*/
@SuppressWarnings("unchecked")
public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Class clazz = getDeclaringClass();
int clazzModifiers = clazz.getModifiers();
if (clazz.isArray() || Modifier.isAbstract(clazzModifiers) || Modifier.isInterface(clazzModifiers) || clazz.isPrimitive()) {
throw new InstantiationException("class " + clazz.getName() + " cannot be instantiated");
}
if (args == null) {
args = EmptyArray.OBJECT;
}
Class>[] pTypes = getParameterTypes(false);
if (args.length != pTypes.length) {
throw new IllegalArgumentException("wrong number of arguments; "
+ "expected " + pTypes.length + ", got " + args.length);
}
if (!flag) {
// Check access
if (!checkAccessibleFast(this)) {
Class>[] callers = VM.getStackClasses(0, 2);
// If we've been called from Class.newInstance() we should use the caller's caller
Class> caller = callers[0] == Class.class ? callers[1] : callers[0];
if (!checkAccessible(caller, this)) {
throw new IllegalAccessException(String.format("Attempt to access constructor %s(%s) from class %s",
clazz.getName(), toString(parameterTypes), caller.getName()));
}
}
}
return (T) internalNewInstance(method, pTypes, args);
}
private native static Object internalNewInstance(long method, Class>[] pTypes, Object[] args) throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException;
/**
* Returns a string containing a concise, human-readable description of this
* constructor. The format of the string is:
*
*
*
modifiers (if any)
*
declaring class name
*
'('
*
parameter types, separated by ',' (if any)
*
')'
*
'throws' plus exception types, separated by ',' (if any)
*
*
* For example:
* {@code public String(byte[],String) throws UnsupportedEncodingException}
*
* @return a printable representation for this constructor
*/
@Override
public String toString() {
Class> declaringClass = getDeclaringClass();
Class>[] parameterTypes = getParameterTypes(false);
Class>[] exceptionTypes = getExceptionTypes(false);
StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
if (result.length() != 0)
result.append(' ');
result.append(declaringClass.getName());
result.append("(");
result.append(toString(parameterTypes));
result.append(")");
if (exceptionTypes != null && exceptionTypes.length != 0) {
result.append(" throws ");
result.append(toString(exceptionTypes));
}
return result.toString();
}
}