use of org.codehaus.groovy.ast.expr.MethodCallExpression in project grails-core by grails.
the class ASTValidationErrorsHelper method addHasErrorsMethod.
protected void addHasErrorsMethod(final ClassNode paramTypeClassNode) {
final ASTNode getErrorsMethod = paramTypeClassNode.getMethod(HAS_ERRORS_METHOD_NAME, GrailsArtefactClassInjector.ZERO_PARAMETERS);
if (getErrorsMethod == null) {
final BlockStatement hasErrorsMethodCode = new BlockStatement();
final Expression initErrorsMethodCallExpression = new MethodCallExpression(new VariableExpression("this"), INIT_ERRORS_METHOD_NAME, EMPTY_TUPLE);
hasErrorsMethodCode.addStatement(new ExpressionStatement(initErrorsMethodCallExpression));
final Statement returnStatement = new ReturnStatement(new BooleanExpression(new MethodCallExpression(ERRORS_EXPRESSION, HAS_ERRORS_METHOD_NAME, EMPTY_TUPLE)));
hasErrorsMethodCode.addStatement(returnStatement);
paramTypeClassNode.addMethod(new MethodNode(HAS_ERRORS_METHOD_NAME, Modifier.PUBLIC, new ClassNode(Boolean.class), GrailsArtefactClassInjector.ZERO_PARAMETERS, GrailsArtefactClassInjector.EMPTY_CLASS_ARRAY, hasErrorsMethodCode));
}
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project gradle by gradle.
the class ModelBlockTransformer method call.
/*
TODO change this so that we extract all the information at compile time.
At the moment we use the transform to:
1. validate/restrict the syntax
2. transform rules into something more robust (e.g. foo.bar.baz {} into configure("foo.bar.baz", {})) - no dynamic propertyMissing() nonsense
3. hoist out input references (i.e. $()) into an annotation on rule closure classes to make available
This means we actually have to execute the code block in order to find the rule information within.
This is also problematic because it means we have to serialize this information into some form that fits into annotations.
Later, we will extract all the “up-front” information we need to know during compile time.
This will mean that we only need to execute the rules themselves, and not any code to actually register the rules.
*/
@Override
public void call(SourceUnit source) throws CompilationFailedException {
List<Statement> statements = source.getAST().getStatementBlock().getStatements();
for (Statement statement : statements) {
ScriptBlock scriptBlock = AstUtils.detectScriptBlock(statement, SCRIPT_BLOCK_NAMES);
if (scriptBlock == null) {
// Look for model(«») (i.e. call to model with anything other than non literal closure)
MethodCallExpression methodCall = AstUtils.extractBareMethodCall(statement);
if (methodCall == null) {
continue;
}
String methodName = AstUtils.extractConstantMethodName(methodCall);
if (methodName == null) {
continue;
}
if (methodName.equals(MODEL)) {
source.getErrorCollector().addError(new SyntaxException(NON_LITERAL_CLOSURE_TO_TOP_LEVEL_MODEL_MESSAGE, statement.getLineNumber(), statement.getColumnNumber()), source);
}
} else {
RuleVisitor ruleVisitor = new RuleVisitor(source, scriptSourceDescription, location);
RulesVisitor rulesVisitor = new RulesVisitor(source, ruleVisitor);
scriptBlock.getClosureExpression().getCode().visit(rulesVisitor);
}
}
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project grails-core by grails.
the class ControllerActionTransformer method getCodeToHandleAllowedMethods.
protected BlockStatement getCodeToHandleAllowedMethods(ClassNode controllerClass, String methodName) {
GrailsASTUtils.addEnhancedAnnotation(controllerClass, DefaultGrailsControllerClass.ALLOWED_HTTP_METHODS_PROPERTY);
final BlockStatement checkAllowedMethodsBlock = new BlockStatement();
final PropertyExpression requestPropertyExpression = new PropertyExpression(new VariableExpression("this"), "request");
final FieldNode allowedMethodsField = controllerClass.getField(DefaultGrailsControllerClass.ALLOWED_HTTP_METHODS_PROPERTY);
if (allowedMethodsField != null) {
final Expression initialAllowedMethodsExpression = allowedMethodsField.getInitialExpression();
if (initialAllowedMethodsExpression instanceof MapExpression) {
boolean actionIsRestricted = false;
final MapExpression allowedMethodsMapExpression = (MapExpression) initialAllowedMethodsExpression;
final List<MapEntryExpression> allowedMethodsMapEntryExpressions = allowedMethodsMapExpression.getMapEntryExpressions();
for (MapEntryExpression allowedMethodsMapEntryExpression : allowedMethodsMapEntryExpressions) {
final Expression allowedMethodsMapEntryKeyExpression = allowedMethodsMapEntryExpression.getKeyExpression();
if (allowedMethodsMapEntryKeyExpression instanceof ConstantExpression) {
final ConstantExpression allowedMethodsMapKeyConstantExpression = (ConstantExpression) allowedMethodsMapEntryKeyExpression;
final Object allowedMethodsMapKeyValue = allowedMethodsMapKeyConstantExpression.getValue();
if (methodName.equals(allowedMethodsMapKeyValue)) {
actionIsRestricted = true;
break;
}
}
}
if (actionIsRestricted) {
final PropertyExpression responsePropertyExpression = new PropertyExpression(new VariableExpression("this"), "response");
final ArgumentListExpression isAllowedArgumentList = new ArgumentListExpression();
isAllowedArgumentList.addExpression(new ConstantExpression(methodName));
isAllowedArgumentList.addExpression(new PropertyExpression(new VariableExpression("this"), "request"));
isAllowedArgumentList.addExpression(new PropertyExpression(new VariableExpression("this"), DefaultGrailsControllerClass.ALLOWED_HTTP_METHODS_PROPERTY));
final Expression isAllowedMethodCall = new StaticMethodCallExpression(ClassHelper.make(AllowedMethodsHelper.class), "isAllowed", isAllowedArgumentList);
final BooleanExpression isValidRequestMethod = new BooleanExpression(isAllowedMethodCall);
final MethodCallExpression sendErrorMethodCall = new MethodCallExpression(responsePropertyExpression, "sendError", new ConstantExpression(HttpServletResponse.SC_METHOD_NOT_ALLOWED));
final ReturnStatement returnStatement = new ReturnStatement(new ConstantExpression(null));
final BlockStatement blockToSendError = new BlockStatement();
blockToSendError.addStatement(new ExpressionStatement(sendErrorMethodCall));
blockToSendError.addStatement(returnStatement);
final IfStatement ifIsValidRequestMethodStatement = new IfStatement(isValidRequestMethod, new ExpressionStatement(new EmptyExpression()), blockToSendError);
checkAllowedMethodsBlock.addStatement(ifIsValidRequestMethodStatement);
}
}
}
final ArgumentListExpression argumentListExpression = new ArgumentListExpression();
argumentListExpression.addExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME));
argumentListExpression.addExpression(new ConstantExpression(methodName));
final Expression setAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "setAttribute", argumentListExpression);
final BlockStatement codeToExecuteIfAttributeIsNotSet = new BlockStatement();
codeToExecuteIfAttributeIsNotSet.addStatement(new ExpressionStatement(setAttributeMethodCall));
codeToExecuteIfAttributeIsNotSet.addStatement(checkAllowedMethodsBlock);
final BooleanExpression attributeIsSetBooleanExpression = new BooleanExpression(new MethodCallExpression(requestPropertyExpression, "getAttribute", new ArgumentListExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME))));
final Statement ifAttributeIsAlreadySetStatement = new IfStatement(attributeIsSetBooleanExpression, new EmptyStatement(), codeToExecuteIfAttributeIsNotSet);
final BlockStatement code = new BlockStatement();
code.addStatement(ifAttributeIsAlreadySetStatement);
return code;
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project grails-core by grails.
the class ControllerActionTransformer method wrapMethodBodyWithExceptionHandling.
/**
* This will wrap the method body in a try catch block which does something
* like this:
* <pre>
* try {
* // original method body here
* } catch (Exception $caughtException) {
* Method $method = getExceptionHandlerMethod($caughtException.getClass())
* if($method) {
* return $method.invoke(this, $caughtException)
* } else {
* throw $caughtException
* }
* }
* </pre>
* @param methodNode the method to add the try catch block to
*/
protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerClassNode, final MethodNode methodNode) {
final BlockStatement catchBlockCode = new BlockStatement();
final String caughtExceptionArgumentName = "$caughtException";
final Expression caughtExceptionVariableExpression = new VariableExpression(caughtExceptionArgumentName);
final Expression caughtExceptionTypeExpression = new PropertyExpression(caughtExceptionVariableExpression, "class");
final Expression thisExpression = new VariableExpression("this");
final MethodCallExpression getExceptionHandlerMethodCall = new MethodCallExpression(thisExpression, "getExceptionHandlerMethodFor", caughtExceptionTypeExpression);
applyDefaultMethodTarget(getExceptionHandlerMethodCall, controllerClassNode);
final ClassNode reflectMethodClassNode = new ClassNode(Method.class);
final String exceptionHandlerMethodVariableName = "$method";
final Expression exceptionHandlerMethodExpression = new VariableExpression(exceptionHandlerMethodVariableName, new ClassNode(Method.class));
final Expression declareExceptionHandlerMethod = new DeclarationExpression(new VariableExpression(exceptionHandlerMethodVariableName, reflectMethodClassNode), Token.newSymbol(Types.EQUALS, 0, 0), getExceptionHandlerMethodCall);
final ArgumentListExpression invokeArguments = new ArgumentListExpression();
invokeArguments.addExpression(thisExpression);
invokeArguments.addExpression(caughtExceptionVariableExpression);
final MethodCallExpression invokeExceptionHandlerMethodExpression = new MethodCallExpression(new VariableExpression(exceptionHandlerMethodVariableName), "invoke", invokeArguments);
applyDefaultMethodTarget(invokeExceptionHandlerMethodExpression, reflectMethodClassNode);
final Statement returnStatement = new ReturnStatement(invokeExceptionHandlerMethodExpression);
final Statement throwCaughtExceptionStatement = new ThrowStatement(caughtExceptionVariableExpression);
final Statement ifExceptionHandlerMethodExistsStatement = new IfStatement(new BooleanExpression(exceptionHandlerMethodExpression), returnStatement, throwCaughtExceptionStatement);
catchBlockCode.addStatement(new ExpressionStatement(declareExceptionHandlerMethod));
catchBlockCode.addStatement(ifExceptionHandlerMethodExistsStatement);
final CatchStatement catchStatement = new CatchStatement(new Parameter(new ClassNode(Exception.class), caughtExceptionArgumentName), catchBlockCode);
final Statement methodBody = methodNode.getCode();
BlockStatement tryBlock = new BlockStatement();
BlockStatement codeToHandleAllowedMethods = getCodeToHandleAllowedMethods(controllerClassNode, methodNode.getName());
tryBlock.addStatement(codeToHandleAllowedMethods);
tryBlock.addStatement(methodBody);
final TryCatchStatement tryCatchStatement = new TryCatchStatement(tryBlock, new EmptyStatement());
tryCatchStatement.addCatch(catchStatement);
final ArgumentListExpression argumentListExpression = new ArgumentListExpression();
argumentListExpression.addExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME));
final PropertyExpression requestPropertyExpression = new PropertyExpression(new VariableExpression("this"), "request");
final Expression removeAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "removeAttribute", argumentListExpression);
final Expression getAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "getAttribute", new ArgumentListExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME)));
final VariableExpression attributeValueExpression = new VariableExpression("$allowed_methods_attribute_value", ClassHelper.make(Object.class));
final Expression initializeAttributeValue = new DeclarationExpression(attributeValueExpression, Token.newSymbol(Types.EQUALS, 0, 0), getAttributeMethodCall);
final Expression attributeValueMatchesMethodNameExpression = new BinaryExpression(new ConstantExpression(methodNode.getName()), Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), attributeValueExpression);
final Statement ifAttributeValueMatchesMethodName = new IfStatement(new BooleanExpression(attributeValueMatchesMethodNameExpression), new ExpressionStatement(removeAttributeMethodCall), new EmptyStatement());
final BlockStatement blockToRemoveAttribute = new BlockStatement();
blockToRemoveAttribute.addStatement(new ExpressionStatement(initializeAttributeValue));
blockToRemoveAttribute.addStatement(ifAttributeValueMatchesMethodName);
final TryCatchStatement tryCatchToRemoveAttribute = new TryCatchStatement(blockToRemoveAttribute, new EmptyStatement());
tryCatchToRemoveAttribute.addCatch(new CatchStatement(new Parameter(ClassHelper.make(Exception.class), "$exceptionRemovingAttribute"), new EmptyStatement()));
tryCatchStatement.setFinallyStatement(tryCatchToRemoveAttribute);
methodNode.setCode(tryCatchStatement);
}
use of org.codehaus.groovy.ast.expr.MethodCallExpression in project grails-core by grails.
the class ControllerActionTransformer method initializeAndValidateCommandObjectParameter.
protected void initializeAndValidateCommandObjectParameter(final BlockStatement wrapper, final ClassNode controllerNode, final ClassNode commandObjectNode, final ASTNode actionNode, final String actionName, final String paramName, final SourceUnit source, final GeneratorContext context) {
final DeclarationExpression declareCoExpression = new DeclarationExpression(new VariableExpression(paramName, commandObjectNode), Token.newSymbol(Types.EQUALS, 0, 0), new EmptyExpression());
wrapper.addStatement(new ExpressionStatement(declareCoExpression));
if (commandObjectNode.isInterface() || Modifier.isAbstract(commandObjectNode.getModifiers())) {
final String warningMessage = "The [" + actionName + "] action in [" + controllerNode.getName() + "] accepts a parameter of type [" + commandObjectNode.getName() + "]. Interface types and abstract class types are not supported as command objects. This parameter will be ignored.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
} else {
initializeCommandObjectParameter(wrapper, commandObjectNode, paramName, source);
@SuppressWarnings("unchecked") boolean argumentIsValidateable = GrailsASTUtils.hasAnyAnnotations(commandObjectNode, grails.persistence.Entity.class, javax.persistence.Entity.class) || commandObjectNode.implementsInterface(ClassHelper.make(Validateable.class));
if (!argumentIsValidateable && commandObjectNode.isPrimaryClassNode()) {
final ModuleNode commandObjectModule = commandObjectNode.getModule();
if (commandObjectModule != null && this.compilationUnit != null) {
if (commandObjectModule == controllerNode.getModule() || doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "controllers" + File.separator)) {
TraitInjectionUtils.injectTrait(compilationUnit, source, commandObjectNode, Validateable.class);
List<ConstructorNode> declaredConstructors = commandObjectNode.getDeclaredConstructors();
List<Statement> objectInitializerStatements = commandObjectNode.getObjectInitializerStatements();
if (declaredConstructors.isEmpty() && !objectInitializerStatements.isEmpty()) {
BlockStatement constructorLogic = new BlockStatement();
ConstructorNode constructorNode = new ConstructorNode(Modifier.PUBLIC, constructorLogic);
commandObjectNode.addConstructor(constructorNode);
constructorLogic.addStatements(objectInitializerStatements);
}
argumentIsValidateable = true;
} else if (doesModulePathIncludeSubstring(commandObjectModule, "grails-app" + File.separator + "domain" + File.separator)) {
argumentIsValidateable = true;
}
}
}
if (argumentIsValidateable) {
final MethodCallExpression validateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "validate", EMPTY_TUPLE);
final MethodNode validateMethod = commandObjectNode.getMethod("validate", new Parameter[0]);
if (validateMethod != null) {
validateMethodCallExpression.setMethodTarget(validateMethod);
}
final Statement ifCommandObjectIsNotNullThenValidate = new IfStatement(new BooleanExpression(new VariableExpression(paramName)), new ExpressionStatement(validateMethodCallExpression), new ExpressionStatement(new EmptyExpression()));
wrapper.addStatement(ifCommandObjectIsNotNullThenValidate);
} else {
// try to dynamically invoke the .validate() method if it is available at runtime...
final Expression respondsToValidateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "respondsTo", new ArgumentListExpression(new ConstantExpression("validate")));
final Expression validateMethodCallExpression = new MethodCallExpression(new VariableExpression(paramName), "validate", new ArgumentListExpression());
final Statement ifRespondsToValidateThenValidateStatement = new IfStatement(new BooleanExpression(respondsToValidateMethodCallExpression), new ExpressionStatement(validateMethodCallExpression), new ExpressionStatement(new EmptyExpression()));
final Statement ifCommandObjectIsNotNullThenValidate = new IfStatement(new BooleanExpression(new VariableExpression(paramName)), ifRespondsToValidateThenValidateStatement, new ExpressionStatement(new EmptyExpression()));
wrapper.addStatement(ifCommandObjectIsNotNullThenValidate);
final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which does not implement grails.validation.Validateable. Data binding will still be applied " + "to this command object but the instance will not be validateable.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
}
if (GrailsASTUtils.isInnerClassNode(commandObjectNode)) {
final String warningMessage = "The [" + actionName + "] action accepts a parameter of type [" + commandObjectNode.getName() + "] which is an inner class. Command object classes should not be inner classes.";
GrailsASTUtils.warning(source, actionNode, warningMessage);
} else {
new DefaultASTDatabindingHelper().injectDatabindingCode(source, context, commandObjectNode);
}
}
}
Aggregations