use of org.springframework.expression.spel.support.ReflectiveConstructorExecutor in project spring-framework by spring-projects.
the class ConstructorReference method createNewInstance.
/**
* Create a new ordinary object and return it.
* @param state the expression state within which this expression is being evaluated
* @return the new object
* @throws EvaluationException if there is a problem creating the object
*/
private TypedValue createNewInstance(ExpressionState state) throws EvaluationException {
Object[] arguments = new Object[getChildCount() - 1];
List<TypeDescriptor> argumentTypes = new ArrayList<>(getChildCount() - 1);
for (int i = 0; i < arguments.length; i++) {
TypedValue childValue = this.children[i + 1].getValueInternal(state);
Object value = childValue.getValue();
arguments[i] = value;
argumentTypes.add(TypeDescriptor.forObject(value));
}
ConstructorExecutor executorToUse = this.cachedExecutor;
if (executorToUse != null) {
try {
return executorToUse.execute(state.getEvaluationContext(), arguments);
} catch (AccessException ex) {
// Otherwise the constructor could not be invoked.
if (ex.getCause() instanceof InvocationTargetException) {
// User exception was the root cause - exit now
Throwable rootCause = ex.getCause().getCause();
if (rootCause instanceof RuntimeException) {
throw (RuntimeException) rootCause;
} else {
String typeName = (String) this.children[0].getValueInternal(state).getValue();
throw new SpelEvaluationException(getStartPosition(), rootCause, SpelMessage.CONSTRUCTOR_INVOCATION_PROBLEM, typeName, FormatHelper.formatMethodForMessage("", argumentTypes));
}
}
// At this point we know it wasn't a user problem so worth a retry if a better candidate can be found
this.cachedExecutor = null;
}
}
// Either there was no accessor or it no longer exists
String typeName = (String) this.children[0].getValueInternal(state).getValue();
executorToUse = findExecutorForConstructor(typeName, argumentTypes, state);
try {
this.cachedExecutor = executorToUse;
if (this.cachedExecutor instanceof ReflectiveConstructorExecutor) {
this.exitTypeDescriptor = CodeFlow.toDescriptor(((ReflectiveConstructorExecutor) this.cachedExecutor).getConstructor().getDeclaringClass());
}
return executorToUse.execute(state.getEvaluationContext(), arguments);
} catch (AccessException ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.CONSTRUCTOR_INVOCATION_PROBLEM, typeName, FormatHelper.formatMethodForMessage("", argumentTypes));
}
}
use of org.springframework.expression.spel.support.ReflectiveConstructorExecutor in project spring-framework by spring-projects.
the class ConstructorReference method generateCode.
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
ReflectiveConstructorExecutor executor = ((ReflectiveConstructorExecutor) this.cachedExecutor);
Constructor<?> constructor = executor.getConstructor();
String classDesc = constructor.getDeclaringClass().getName().replace('.', '/');
mv.visitTypeInsn(NEW, classDesc);
mv.visitInsn(DUP);
// children[0] is the type of the constructor, don't want to include that in argument processing
SpelNodeImpl[] arguments = new SpelNodeImpl[children.length - 1];
System.arraycopy(children, 1, arguments, 0, children.length - 1);
generateCodeForArguments(mv, cf, constructor, arguments);
mv.visitMethodInsn(INVOKESPECIAL, classDesc, "<init>", CodeFlow.createSignatureDescriptor(constructor), false);
cf.pushDescriptor(this.exitTypeDescriptor);
}
use of org.springframework.expression.spel.support.ReflectiveConstructorExecutor in project spring-framework by spring-projects.
the class ConstructorReference method isCompilable.
@Override
public boolean isCompilable() {
if (!(this.cachedExecutor instanceof ReflectiveConstructorExecutor) || this.exitTypeDescriptor == null) {
return false;
}
if (getChildCount() > 1) {
for (int c = 1, max = getChildCount(); c < max; c++) {
if (!this.children[c].isCompilable()) {
return false;
}
}
}
ReflectiveConstructorExecutor executor = (ReflectiveConstructorExecutor) this.cachedExecutor;
Constructor<?> constructor = executor.getConstructor();
return (Modifier.isPublic(constructor.getModifiers()) && Modifier.isPublic(constructor.getDeclaringClass().getModifiers()));
}
Aggregations