org.powermock.reflect.internal.ConstructorFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of powermock-reflect Show documentation
Show all versions of powermock-reflect Show documentation
Various utilities for accessing internals of a class.
package org.powermock.reflect.internal;
import org.powermock.reflect.exceptions.ConstructorNotFoundException;
import org.powermock.reflect.exceptions.TooManyConstructorsFoundException;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
class ConstructorFinder {
private Class> type;
private Object[] arguments;
private Class> unmockedType;
private Constructor potentialConstructor;
ConstructorFinder(Class> type, Object... arguments) {
if (type == null) {
throw new IllegalArgumentException("Class type cannot be null.");
}
this.type = type;
this.arguments = arguments;
this.unmockedType = WhiteboxImpl.getOriginalUnmockedType(type);
if (isNestedClass() && arguments != null) {
addArgumentForNestedClass();
}
}
public java.lang.reflect.Constructor findConstructor() {
lookupPotentialConstructor();
throwExceptionIfConstructorWasNotFound();
return potentialConstructor.getJavaConstructor();
}
private void lookupPotentialConstructor() {Set constructors = getDeclaredConstructorsWithoutPowerMockConstructor();
for (Constructor constructor : constructors) {
if (constructor.canBeInvokeWith(arguments)) {
setPotentialConstructor(constructor);
}
// if a constructor is found and it has varargs parameters then the constructor will be used even if
// other constructor is matcher the given arguments. It is done, because when Argument Matchers are used
// arguments passed to the method are null value and it's imposable to determinate whether parameters
// match to arguments or not.
if (isVarArgConstructorFound()){
return;
}
}
}
private boolean isVarArgConstructorFound() {return potentialConstructor!=null && potentialConstructor.isVarArg();}
private void setPotentialConstructor(Constructor constructor) {
if (potentialConstructor == null) {
potentialConstructor = constructor;
}else{
/*
* We've already found a constructor match before, this
* means that PowerMock cannot determine which method to
* expect since there are two methods with the same name
* and the same number of arguments but one is using
* wrapper types.
*/
throwExceptionWhenMultipleConstructorMatchesFound(new java.lang.reflect.Constructor[]{potentialConstructor.getJavaConstructor(),
constructor.getJavaConstructor()});
}
}
public void throwExceptionWhenMultipleConstructorMatchesFound(java.lang.reflect.Constructor[] constructors) {
if (constructors == null || constructors.length < 2) {
throw new IllegalArgumentException("Internal error: throwExceptionWhenMultipleConstructorMatchesFound needs at least two constructors.");
}
StringBuilder sb = new StringBuilder();
sb.append("Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to.\n");
sb.append("Matching constructors in class ").append(constructors[0].getDeclaringClass().getName())
.append(" were:\n");
for (java.lang.reflect.Constructor constructor : constructors) {
sb.append(constructor.getName()).append("( ");
final Class>[] parameterTypes = constructor.getParameterTypes();
for (Class> paramType : parameterTypes) {
sb.append(paramType.getName()).append(".class ");
}
sb.append(")\n");
}
throw new TooManyConstructorsFoundException(sb.toString());
}
private void addArgumentForNestedClass() {
Object[] argumentsForLocalClass = new Object[arguments.length + 1];
argumentsForLocalClass[0] = unmockedType.getEnclosingClass();
System.arraycopy(arguments, 0, argumentsForLocalClass, 1, arguments.length);
arguments = argumentsForLocalClass;
}
private boolean isNestedClass() {
return (unmockedType.isLocalClass() || unmockedType.isAnonymousClass() || unmockedType.isMemberClass())
&& !Modifier.isStatic(unmockedType.getModifiers());
}
private Set getDeclaredConstructorsWithoutPowerMockConstructor() {
Set constructors = new HashSet();
for (java.lang.reflect.Constructor> constructor : unmockedType.getDeclaredConstructors()) {
if (!isPowerMockConstructor(constructor.getParameterTypes())) {
constructors.add(new Constructor(constructor));
}
}
return constructors;
}
private boolean isPowerMockConstructor(Class>[] parameterTypes) {
return parameterTypes.length >= 1
&& parameterTypes[parameterTypes.length - 1].getName().equals(
"org.powermock.core.IndicateReloadClass");
}
private void throwExceptionIfConstructorWasNotFound() {
if (potentialConstructor == null) {
String message = "No constructor found in class '" + WhiteboxImpl.getOriginalUnmockedType(type).getName() + "' " +
"with "
+ "parameter types: [ " + WhiteboxImpl.getArgumentTypesAsString(arguments) + " ].";
throw new ConstructorNotFoundException(message);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy