KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > scripting > groovy > GroovyScriptFactory


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.scripting.groovy;
18
19 import java.io.IOException JavaDoc;
20
21 import groovy.lang.GroovyClassLoader;
22 import groovy.lang.GroovyObject;
23 import groovy.lang.Script;
24 import org.codehaus.groovy.control.CompilationFailedException;
25
26 import org.springframework.beans.factory.BeanClassLoaderAware;
27 import org.springframework.scripting.ScriptCompilationException;
28 import org.springframework.scripting.ScriptFactory;
29 import org.springframework.scripting.ScriptSource;
30 import org.springframework.util.Assert;
31 import org.springframework.util.ClassUtils;
32
33 /**
34  * {@link org.springframework.scripting.ScriptFactory} implementation
35  * for a Groovy script.
36  *
37  * <p>Typically used in combination with a
38  * {@link org.springframework.scripting.support.ScriptFactoryPostProcessor};
39  * see the latter's javadoc} for a configuration example.
40  *
41  * @author Juergen Hoeller
42  * @author Rob Harrop
43  * @author Rod Johnson
44  * @since 2.0
45  * @see groovy.lang.GroovyClassLoader
46  * @see org.springframework.scripting.support.ScriptFactoryPostProcessor
47  */

48 public class GroovyScriptFactory implements ScriptFactory, BeanClassLoaderAware {
49
50     private final String JavaDoc scriptSourceLocator;
51     
52     private final GroovyObjectCustomizer groovyObjectCustomizer;
53
54     private GroovyClassLoader groovyClassLoader = new GroovyClassLoader(ClassUtils.getDefaultClassLoader());
55
56     private Class JavaDoc scriptClass;
57
58     private Class JavaDoc scriptResultClass;
59
60     private final Object JavaDoc scriptClassMonitor = new Object JavaDoc();
61
62
63     /**
64      * Create a new GroovyScriptFactory for the given script source.
65      * <p>We don't need to specify script interfaces here, since
66      * a Groovy script defines its Java interfaces itself.
67      * @param scriptSourceLocator a locator that points to the source of the script.
68      * Interpreted by the post-processor that actually creates the script.
69      */

70     public GroovyScriptFactory(String JavaDoc scriptSourceLocator) {
71         this(scriptSourceLocator, null);
72     }
73
74     /**
75      * Create a new GroovyScriptFactory for the given script source,
76      * specifying a strategy interface that can create a custom MetaClass
77      * to supply missing methods and otherwise change the behavior of the object.
78      * <p>We don't need to specify script interfaces here, since
79      * a Groovy script defines its Java interfaces itself.
80      * @param scriptSourceLocator a locator that points to the source of the script.
81      * Interpreted by the post-processor that actually creates the script.
82      * @param groovyObjectCustomizer a customizer that can set a custom metaclass
83      * or make other changes to the GroovyObject created by this factory
84      * (may be <code>null</code>)
85      */

86     public GroovyScriptFactory(String JavaDoc scriptSourceLocator, GroovyObjectCustomizer groovyObjectCustomizer) {
87         Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty");
88         this.scriptSourceLocator = scriptSourceLocator;
89         this.groovyObjectCustomizer = groovyObjectCustomizer;
90     }
91
92
93     public void setBeanClassLoader(ClassLoader JavaDoc classLoader) {
94         this.groovyClassLoader = new GroovyClassLoader(classLoader);
95     }
96
97     public String JavaDoc getScriptSourceLocator() {
98         return this.scriptSourceLocator;
99     }
100
101     /**
102      * Groovy scripts determine their interfaces themselves,
103      * hence we don't need to explicitly expose interfaces here.
104      * @return <code>null</code> always
105      */

106     public Class JavaDoc[] getScriptInterfaces() {
107         return null;
108     }
109
110     /**
111      * Groovy scripts do not need a config interface,
112      * since they expose their setters as public methods.
113      */

114     public boolean requiresConfigInterface() {
115         return false;
116     }
117
118
119     /**
120      * Loads and parses the Groovy script via the GroovyClassLoader.
121      * @see groovy.lang.GroovyClassLoader
122      */

123     public Object JavaDoc getScriptedObject(ScriptSource scriptSource, Class JavaDoc[] actualInterfaces)
124             throws IOException JavaDoc, ScriptCompilationException {
125
126         try {
127             Class JavaDoc scriptClassToExecute = null;
128
129             synchronized (this.scriptClassMonitor) {
130                 if (this.scriptClass == null || scriptSource.isModified()) {
131                     this.scriptClass = this.groovyClassLoader.parseClass(scriptSource.getScriptAsString());
132
133                     if (Script.class.isAssignableFrom(this.scriptClass)) {
134                         // A Groovy script, probably creating an instance: let's execute it.
135
Object JavaDoc result = executeScript(this.scriptClass);
136                         this.scriptResultClass = (result != null ? result.getClass() : null);
137                         return result;
138                     }
139                     else {
140                         this.scriptResultClass = this.scriptClass;
141                     }
142                 }
143                 scriptClassToExecute = this.scriptClass;
144             }
145
146             // Process re-execution outside of the synchronized block.
147
return executeScript(scriptClassToExecute);
148         }
149         catch (CompilationFailedException ex) {
150             throw new ScriptCompilationException(
151                     "Could not compile Groovy script: " + scriptSource, ex);
152         }
153     }
154
155     public Class JavaDoc getScriptedObjectType(ScriptSource scriptSource)
156             throws IOException JavaDoc, ScriptCompilationException {
157
158         synchronized (this.scriptClassMonitor) {
159             if (this.scriptClass == null || scriptSource.isModified()) {
160                 this.scriptClass = this.groovyClassLoader.parseClass(scriptSource.getScriptAsString());
161
162                 if (Script.class.isAssignableFrom(this.scriptClass)) {
163                     // A Groovy script, probably creating an instance: let's execute it.
164
Object JavaDoc result = executeScript(this.scriptClass);
165                     this.scriptResultClass = (result != null ? result.getClass() : null);
166                 }
167                 else {
168                     this.scriptResultClass = this.scriptClass;
169                 }
170             }
171             return this.scriptResultClass;
172         }
173     }
174
175     /**
176      * Instantiate the given Groovy script class and run it if necessary.
177      * @param scriptClass the Groovy script class
178      * @return the result object (either an instance of the script class
179      * or the result of running the script instance)
180      * @throws ScriptCompilationException in case of instantiation failure
181      */

182     protected Object JavaDoc executeScript(Class JavaDoc scriptClass) throws ScriptCompilationException {
183         try {
184             GroovyObject goo = (GroovyObject) scriptClass.newInstance();
185
186             if (this.groovyObjectCustomizer != null) {
187                 // Allow metaclass and other customization.
188
this.groovyObjectCustomizer.customize(goo);
189             }
190
191             if (goo instanceof Script) {
192                 // A Groovy script, probably creating an instance: let's execute it.
193
return ((Script) goo).run();
194             }
195             else {
196                 // An instance of the scripted class: let's return it as-is.
197
return goo;
198             }
199         }
200         catch (InstantiationException JavaDoc ex) {
201             throw new ScriptCompilationException(
202                     "Could not instantiate Groovy script class: " + scriptClass.getName(), ex);
203         }
204         catch (IllegalAccessException JavaDoc ex) {
205             throw new ScriptCompilationException(
206                     "Could not access Groovy script constructor: " + scriptClass.getName(), ex);
207         }
208     }
209
210
211     public String JavaDoc toString() {
212         return "GroovyScriptFactory: script source locator [" + this.scriptSourceLocator + "]";
213     }
214
215 }
216
Popular Tags