KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > scripting > bsh > BshScriptFactory


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.bsh;
18
19 import java.io.IOException JavaDoc;
20
21 import bsh.EvalError;
22
23 import org.springframework.beans.factory.BeanClassLoaderAware;
24 import org.springframework.scripting.ScriptCompilationException;
25 import org.springframework.scripting.ScriptFactory;
26 import org.springframework.scripting.ScriptSource;
27 import org.springframework.util.Assert;
28 import org.springframework.util.ClassUtils;
29
30 /**
31  * {@link org.springframework.scripting.ScriptFactory} implementation
32  * for a BeanShell script.
33  *
34  * <p>Typically used in combination with a
35  * {@link org.springframework.scripting.support.ScriptFactoryPostProcessor};
36  * see the latter's javadoc for a configuration example.
37  *
38  * @author Juergen Hoeller
39  * @author Rob Harrop
40  * @since 2.0
41  * @see BshScriptUtils
42  * @see org.springframework.scripting.support.ScriptFactoryPostProcessor
43  */

44 public class BshScriptFactory implements ScriptFactory, BeanClassLoaderAware {
45
46     private final String JavaDoc scriptSourceLocator;
47
48     private final Class JavaDoc[] scriptInterfaces;
49
50     private ClassLoader JavaDoc beanClassLoader = ClassUtils.getDefaultClassLoader();
51
52     private Class JavaDoc scriptClass;
53
54     private final Object JavaDoc scriptClassMonitor = new Object JavaDoc();
55
56
57     /**
58      * Create a new BshScriptFactory for the given script source.
59      * <p>With this <code>BshScriptFactory</code> variant, the script needs to
60      * declare a full class or return an actual instance of the scripted object.
61      * @param scriptSourceLocator a locator that points to the source of the script.
62      * Interpreted by the post-processor that actually creates the script.
63      */

64     public BshScriptFactory(String JavaDoc scriptSourceLocator) {
65         this(scriptSourceLocator, null);
66     }
67
68     /**
69      * Create a new BshScriptFactory for the given script source.
70      * <p>The script may either be a simple script that needs a corresponding proxy
71      * generated (implementing the specified interfaces), or declare a full class
72      * or return an actual instance of the scripted object (in which case the
73      * specified interfaces, if any, need to be implemented by that class/instance).
74      * @param scriptSourceLocator a locator that points to the source of the script.
75      * Interpreted by the post-processor that actually creates the script.
76      * @param scriptInterfaces the Java interfaces that the scripted object
77      * is supposed to implement (may be <code>null</code>)
78      */

79     public BshScriptFactory(String JavaDoc scriptSourceLocator, Class JavaDoc[] scriptInterfaces) {
80         Assert.hasText(scriptSourceLocator, "'scriptSourceLocator' must not be empty");
81         this.scriptSourceLocator = scriptSourceLocator;
82         this.scriptInterfaces = scriptInterfaces;
83     }
84
85     public void setBeanClassLoader(ClassLoader JavaDoc classLoader) {
86         this.beanClassLoader = classLoader;
87     }
88
89
90     public String JavaDoc getScriptSourceLocator() {
91         return this.scriptSourceLocator;
92     }
93
94     public Class JavaDoc[] getScriptInterfaces() {
95         return this.scriptInterfaces;
96     }
97
98     /**
99      * BeanShell scripts do require a config interface.
100      */

101     public boolean requiresConfigInterface() {
102         return true;
103     }
104
105     /**
106      * Load and parse the BeanShell script via {@link BshScriptUtils}.
107      * @see BshScriptUtils#createBshObject(String, Class[], ClassLoader)
108      */

109     public Object JavaDoc getScriptedObject(ScriptSource actualScriptSource, Class JavaDoc[] actualInterfaces)
110             throws IOException JavaDoc, ScriptCompilationException {
111
112         try {
113             Class JavaDoc clazz = null;
114             synchronized (this.scriptClassMonitor) {
115                 if (actualScriptSource.isModified()) {
116                     // New script content: Let's check whether it evaluates to a Class.
117
Object JavaDoc result = BshScriptUtils.evaluateBshScript(
118                             actualScriptSource.getScriptAsString(), actualInterfaces, this.beanClassLoader);
119                     if (result instanceof Class JavaDoc) {
120                         // A Class: We'll cache the Class here and create an instance
121
// outside of the synchronized block.
122
this.scriptClass = (Class JavaDoc) result;
123                     }
124                     else {
125                         // Not a Class: OK, we'll simply create BeanShell objects
126
// through evaluating the script for every call later on.
127
// For this first-time check, let's simply return the
128
// already evaluated object.
129
return result;
130                     }
131                 }
132                 clazz = this.scriptClass;
133             }
134             if (clazz != null) {
135                 // A Class: We need to create an instance for every call.
136
try {
137                     return clazz.newInstance();
138                 }
139                 catch (Throwable JavaDoc ex) {
140                     throw new ScriptCompilationException("Could not instantiate script class: " + clazz, ex);
141                 }
142             }
143             else {
144                 // Not a Class: We need to evaluate the script for every call.
145
return BshScriptUtils.createBshObject(
146                         actualScriptSource.getScriptAsString(), actualInterfaces, this.beanClassLoader);
147             }
148         }
149         catch (EvalError ex) {
150             throw new ScriptCompilationException("Could not compile BeanShell script: " + actualScriptSource, ex);
151         }
152     }
153
154     public Class JavaDoc getScriptedObjectType(ScriptSource scriptSource)
155             throws IOException JavaDoc, ScriptCompilationException {
156
157         try {
158             synchronized (this.scriptClassMonitor) {
159                 if (scriptSource.isModified()) {
160                     // New script content: Let's check whether it evaluates to a Class.
161
this.scriptClass = BshScriptUtils.determineBshObjectType(scriptSource.getScriptAsString());
162                 }
163                 return this.scriptClass;
164             }
165         }
166         catch (EvalError ex) {
167             throw new ScriptCompilationException("Could not compile BeanShell script: " + scriptSource, ex);
168         }
169     }
170
171
172     public String JavaDoc toString() {
173         return "BshScriptFactory: script source locator [" + this.scriptSourceLocator + "]";
174     }
175
176 }
177
Popular Tags