All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.chromattic.groovy.ChromatticDelegate Maven / Gradle / Ivy

/*
* Copyright (C) 2003-2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.chromattic.groovy;

import groovy.lang.GroovyInterceptable;
import org.chromattic.groovy.exceptions.NoSuchSetterException;
import org.chromattic.spi.instrument.MethodHandler;
import org.codehaus.groovy.ast.*;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.*;

import java.lang.reflect.Modifier;
import java.util.Iterator;

/**
 * @author Alain Defrance
 * @version $Revision$
 */
public class ChromatticDelegate {

  public void setGroovyInterceptable(ClassNode classNode) {
    for (ClassNode interfaceNode : classNode.getInterfaces())
      if (interfaceNode.getTypeClass().equals(GroovyInterceptable.class)) return;

    //
    classNode.addInterface(new ClassNode(GroovyInterceptable.class));
  }

  public void addInvokerField(ClassNode classNode) {
    GroovyUtils.createGetter(
      classNode
      , classNode.addField(
          "chromatticInvoker"
          , Modifier.PRIVATE
          , new ClassNode(MethodHandler.class)
          , new ConstantExpression(null)
        )
    );
  }

  public void plugGetProperty(ClassNode classNode) throws NoSuchMethodException {
    MethodNode methodNode = classNode.getMethod("getProperty", new Parameter[]{new Parameter(ClassHelper.STRING_TYPE, "p")});
    if (
            methodNode == null
            || !classNode.equals(methodNode.getDeclaringClass())
            ) throw new NoSuchMethodException();

    //
    methodNode.setCode(
      new BlockStatement(
        new Statement[] {
                //new ThrowStatement(new ConstructorCallExpression(new ClassNode(RuntimeException.class), new EmptyExpression())),
          new ReturnStatement(
            new StaticMethodCallExpression(
              new ClassNode(ChromatticGroovyInvocation.class)
              , "getProperty"
              , new ArgumentListExpression(
                  new Expression[] {
                    new VariableExpression("this")
                    , new VariableExpression("p")
                    , new FieldExpression(classNode.getField("chromatticInvoker"))
                  }
              )
            )
          )
        }
        ,new VariableScope()
      )
    );
  }

  public void plugSetProperty(ClassNode classNode) throws NoSuchMethodException {
    MethodNode methodNode = classNode.getMethod(
      "setProperty"
      , new Parameter[] {
          new Parameter(ClassHelper.STRING_TYPE, "p")
          , new Parameter(ClassHelper.OBJECT_TYPE, "v")
      }
    );
    if (
            methodNode == null
            || !classNode.equals(methodNode.getDeclaringClass())
            ) throw new NoSuchMethodException();
    
    //
    methodNode.setCode(
      new BlockStatement(
        new Statement[] {
                //new ThrowStatement(new ConstructorCallExpression(new ClassNode(RuntimeException.class), new EmptyExpression())),
          new ExpressionStatement(
            new StaticMethodCallExpression(
              new ClassNode(ChromatticGroovyInvocation.class)
              , "setProperty"
              , new ArgumentListExpression(
                  new Expression[] {
                    new VariableExpression("this")
                    , new VariableExpression("p")
                    , new VariableExpression("v")
                    , new FieldExpression(classNode.getField("chromatticInvoker"))
                  }
              )
            )
          )
        }
        ,new VariableScope()
      )
    );
  }

  public void plugInvokeMethod(ClassNode classNode) throws NoSuchMethodException {
    MethodNode methodNode = classNode.getMethod(
      "invokeMethod"
      , new Parameter[] {
          new Parameter(ClassHelper.STRING_TYPE, "m")
          , new Parameter(ClassHelper.OBJECT_TYPE, "p")
      }
    );
    if (
            methodNode == null
            || !classNode.equals(methodNode.getDeclaringClass())
            ) throw new NoSuchMethodException();
    
    //
    methodNode.setCode(
      new BlockStatement(
        new Statement[] {
          new ExpressionStatement(
            new StaticMethodCallExpression(
              new ClassNode(ChromatticGroovyInvocation.class)
              , "invokeMethod"
              , new ArgumentListExpression(
                  new Expression[] {
                    new VariableExpression("this")
                    , new VariableExpression("m")
                    , new VariableExpression("p")
                    , new FieldExpression(classNode.getField("chromatticInvoker"))
                  }
              )
            )
          )
        }
        ,new VariableScope()
      )
    );
  }

  public void generateGetProperty(ClassNode classNode) {
    classNode.addMethod(
      "getProperty"
      , Modifier.PUBLIC
      , ClassHelper.OBJECT_TYPE
      , new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "p") }
      , new ClassNode[] {}
      , new EmptyStatement()
    );
    try {
      plugGetProperty(classNode);
    } catch (NoSuchMethodException ignore) { }
  }

  public void generateSetProperty(ClassNode classNode) {
    classNode.addMethod(
      "setProperty"
      , Modifier.PUBLIC
      , ClassHelper.VOID_TYPE
      , new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "p"), new Parameter(ClassHelper.OBJECT_TYPE, "v") }
      , new ClassNode[] {}
      , new EmptyStatement()
    );
    try {
      plugSetProperty(classNode);
    } catch (NoSuchMethodException ignore) { }
  }

  public void generateInvokeMethod(ClassNode classNode) {
    classNode.addMethod(
      "invokeMethod"
      , Modifier.PUBLIC
      , ClassHelper.OBJECT_TYPE
      , new Parameter[] { new Parameter(ClassHelper.STRING_TYPE, "m"), new Parameter(ClassHelper.OBJECT_TYPE, "p") }
      , new ClassNode[] {}
      , new EmptyStatement()
    );
    try {
      plugInvokeMethod(classNode);
    } catch (NoSuchMethodException ignore) { }
  }

  public void plugInjector(FieldNode fieldNode, ClassNode injectorClass) throws NoSuchSetterException
  {
    ClassNode classNode = fieldNode.getDeclaringClass();
    MethodNode methodNode = GroovyUtils.getSetter(classNode, fieldNode);
    if (methodNode == null) {
      throw new NoSuchSetterException(
              "setter should exists to plug injector : " + classNode.getName() + "." + fieldNode.getName());
    }
    Statement oldCode = methodNode.getCode();

    //
    methodNode.setCode(
      new BlockStatement(
        new Statement[] {
          new ExpressionStatement(
            new StaticMethodCallExpression(
              injectorClass
              , "contextualize"
              , new ArgumentListExpression(
                  new Expression[] {
                    new VariableExpression(methodNode.getParameters()[0].getName())
                    , new VariableExpression("this")
                  }
              )
            )
          )
          , oldCode
        }
        ,new VariableScope()
      )
    );
  }


  public void removeChromatticField(ClassNode classNode) {
    Iterator it = classNode.getFields().iterator();
    while(it.hasNext()) {
      FieldNode fieldNode = it.next();
      if (GroovyUtils.isChromatticAnnoted(GroovyUtils.getGetter(classNode, fieldNode))) {
        it.remove();
        fieldNode.getOwner().redirect().renameField(fieldNode.getName(), fieldNode.getName() + "_");
      }
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy