Package ratpack.groovy.script.internal

Source Code of ratpack.groovy.script.internal.ScriptEngine

/*
* Copyright 2013 the original author or authors.
*
* 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 ratpack.groovy.script.internal;

import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
import groovy.transform.CompileStatic;
import groovy.transform.InheritConstructors;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.classgen.Verifier;
import org.codehaus.groovy.control.*;
import org.codehaus.groovy.control.customizers.CompilationCustomizer;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;

import java.nio.file.Path;
import java.security.CodeSource;

public class ScriptEngine<T extends Script> {

  private static final ClassNode LINE_NUMBER_CLASS_NODE = new ClassNode(LineNumber.class);

  private final boolean staticCompile;
  private final Class<T> scriptBaseClass;
  private ClassLoader parentLoader;

  public ScriptEngine(ClassLoader parentLoader, boolean staticCompile, Class<T> scriptBaseClass) {
    this.parentLoader = parentLoader;
    this.staticCompile = staticCompile;
    this.scriptBaseClass = scriptBaseClass;
  }

  public T create(String scriptName, Path scriptPath, String scriptText, Object... scriptConstructionArgs) throws IllegalAccessException, InstantiationException {
    Class<T> scriptClass = compile(scriptName, scriptPath, scriptText);
    return DefaultGroovyMethods.newInstance(scriptClass, scriptConstructionArgs);
  }

  @SuppressWarnings("unchecked")
  public Class<T> compile(String scriptName, String scriptText) throws IllegalAccessException, InstantiationException {
    return createClassLoader(null).parseClass(scriptText, scriptName);
  }

  @SuppressWarnings("unchecked")
  public Class<T> compile(String scriptName, Path scriptPath, String scriptText) throws IllegalAccessException, InstantiationException {
    return createClassLoader(scriptPath).parseClass(scriptText, scriptName);
  }

  private GroovyClassLoader createClassLoader(final Path scriptPath) {
    final CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
    if (!scriptBaseClass.equals(Script.class)) {
      compilerConfiguration.setScriptBaseClass(scriptBaseClass.getName());
    }
    compilerConfiguration.addCompilationCustomizers(new CompilationCustomizer(CompilePhase.CONVERSION) {
      @Override
      public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
        if (staticCompile) {
          classNode.addAnnotation(new AnnotationNode(new ClassNode(CompileStatic.class)));
        }
        classNode.addAnnotation(new AnnotationNode(new ClassNode(InheritConstructors.class)));
        if (scriptPath != null) {
          AnnotationNode scriptPathAnnotation = new AnnotationNode(new ClassNode(ScriptPath.class));
          scriptPathAnnotation.addMember("value", new ConstantExpression(scriptPath.toUri().toString()));
          classNode.addAnnotation(scriptPathAnnotation);
        }
      }
    });

    return new GroovyClassLoader(parentLoader, compilerConfiguration) {
      @Override
      protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
        return new CompilationUnit(config, source, this) {
          {
            verifier = new Verifier() {
              @Override
              public void visitClass(ClassNode node) {
                if (node.implementsInterface(ClassHelper.GENERATED_CLOSURE_Type)) {
                  AnnotationNode lineNumberAnnotation = new AnnotationNode(LINE_NUMBER_CLASS_NODE);
                  lineNumberAnnotation.addMember("value", new ConstantExpression(node.getLineNumber(), true));
                  node.addAnnotation(lineNumberAnnotation);
                }

                super.visitClass(node);
              }
            };
          }
        };
      }
    };

  }

}
TOP

Related Classes of ratpack.groovy.script.internal.ScriptEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.