001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.scripting.groovy; 018 019import java.io.IOException; 020import java.util.Map; 021 022import groovy.lang.Binding; 023import groovy.lang.GroovyRuntimeException; 024import groovy.lang.GroovyShell; 025import org.codehaus.groovy.control.CompilerConfiguration; 026import org.codehaus.groovy.control.customizers.CompilationCustomizer; 027 028import org.springframework.beans.factory.BeanClassLoaderAware; 029import org.springframework.lang.Nullable; 030import org.springframework.scripting.ScriptCompilationException; 031import org.springframework.scripting.ScriptEvaluator; 032import org.springframework.scripting.ScriptSource; 033import org.springframework.scripting.support.ResourceScriptSource; 034 035/** 036 * Groovy-based implementation of Spring's {@link ScriptEvaluator} strategy interface. 037 * 038 * @author Juergen Hoeller 039 * @since 4.0 040 * @see GroovyShell#evaluate(String, String) 041 */ 042public class GroovyScriptEvaluator implements ScriptEvaluator, BeanClassLoaderAware { 043 044 @Nullable 045 private ClassLoader classLoader; 046 047 private CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); 048 049 050 /** 051 * Construct a new GroovyScriptEvaluator. 052 */ 053 public GroovyScriptEvaluator() { 054 } 055 056 /** 057 * Construct a new GroovyScriptEvaluator. 058 * @param classLoader the ClassLoader to use as a parent for the {@link GroovyShell} 059 */ 060 public GroovyScriptEvaluator(@Nullable ClassLoader classLoader) { 061 this.classLoader = classLoader; 062 } 063 064 065 /** 066 * Set a custom compiler configuration for this evaluator. 067 * @since 4.3.3 068 * @see #setCompilationCustomizers 069 */ 070 public void setCompilerConfiguration(@Nullable CompilerConfiguration compilerConfiguration) { 071 this.compilerConfiguration = 072 (compilerConfiguration != null ? compilerConfiguration : new CompilerConfiguration()); 073 } 074 075 /** 076 * Return this evaluator's compiler configuration (never {@code null}). 077 * @since 4.3.3 078 * @see #setCompilerConfiguration 079 */ 080 public CompilerConfiguration getCompilerConfiguration() { 081 return this.compilerConfiguration; 082 } 083 084 /** 085 * Set one or more customizers to be applied to this evaluator's compiler configuration. 086 * <p>Note that this modifies the shared compiler configuration held by this evaluator. 087 * @since 4.3.3 088 * @see #setCompilerConfiguration 089 */ 090 public void setCompilationCustomizers(CompilationCustomizer... compilationCustomizers) { 091 this.compilerConfiguration.addCompilationCustomizers(compilationCustomizers); 092 } 093 094 @Override 095 public void setBeanClassLoader(ClassLoader classLoader) { 096 this.classLoader = classLoader; 097 } 098 099 100 @Override 101 @Nullable 102 public Object evaluate(ScriptSource script) { 103 return evaluate(script, null); 104 } 105 106 @Override 107 @Nullable 108 public Object evaluate(ScriptSource script, @Nullable Map<String, Object> arguments) { 109 GroovyShell groovyShell = new GroovyShell( 110 this.classLoader, new Binding(arguments), this.compilerConfiguration); 111 try { 112 String filename = (script instanceof ResourceScriptSource ? 113 ((ResourceScriptSource) script).getResource().getFilename() : null); 114 if (filename != null) { 115 return groovyShell.evaluate(script.getScriptAsString(), filename); 116 } 117 else { 118 return groovyShell.evaluate(script.getScriptAsString()); 119 } 120 } 121 catch (IOException ex) { 122 throw new ScriptCompilationException(script, "Cannot access Groovy script", ex); 123 } 124 catch (GroovyRuntimeException ex) { 125 throw new ScriptCompilationException(script, ex); 126 } 127 } 128 129}