1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.codehaus.groovy.bsf;
47
48 import groovy.lang.Closure;
49 import groovy.lang.GroovyShell;
50 import org.apache.bsf.BSFDeclaredBean;
51 import org.apache.bsf.BSFException;
52 import org.apache.bsf.BSFManager;
53 import org.apache.bsf.util.BSFEngineImpl;
54 import org.apache.bsf.util.BSFFunctions;
55 import org.codehaus.groovy.runtime.InvokerHelper;
56
57 import java.util.Vector;
58
59 /***
60 * A BSF Engine for the <a href="http://groovy.codehaus.org/">Groovy</a>
61 * scripting language.
62 * <p/>
63 * It's derived from the Jython / JPython engine
64 *
65 * @author James Strachan
66 */
67 public class GroovyEngine extends BSFEngineImpl {
68 protected GroovyShell shell;
69
70
71
72
73
74
75
76
77
78 private String convertToValidJavaClassname(String inName) {
79 if (inName == null || inName.equals("")) {
80 return "_";
81 }
82 StringBuffer output = new StringBuffer(inName.length());
83 boolean firstChar = true;
84 for (int i = 0; i < inName.length(); ++i) {
85 char ch = inName.charAt(i);
86 if (firstChar && !Character.isJavaIdentifierStart(ch)) {
87 ch = '_';
88 } else if (!firstChar
89 && !(Character.isJavaIdentifierPart(ch) || ch == '.')) {
90 ch = '_';
91 }
92 firstChar = (ch == '.');
93 output.append(ch);
94 }
95 return output.toString();
96 }
97
98 /***
99 * Allow an anonymous function to be declared and invoked
100 */
101 public Object apply(String source, int lineNo, int columnNo, Object funcBody, Vector paramNames,
102 Vector arguments) throws BSFException {
103 Object object = eval(source, lineNo, columnNo, funcBody);
104 if (object instanceof Closure) {
105
106 Closure closure = (Closure) object;
107 return closure.call(arguments.toArray());
108 }
109 return object;
110 }
111
112 /***
113 * Call the named method of the given object.
114 */
115 public Object call(Object object, String method, Object[] args) throws BSFException {
116 return InvokerHelper.invokeMethod(object, method, args);
117 }
118
119 /***
120 * Evaluate an expression.
121 */
122 public Object eval(String source, int lineNo, int columnNo, Object script) throws BSFException {
123 try {
124 source = convertToValidJavaClassname(source);
125 return getEvalShell().evaluate(script.toString(), source);
126 } catch (Exception e) {
127 throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
128 }
129 }
130
131 /***
132 * Execute a script.
133 */
134 public void exec(String source, int lineNo, int columnNo, Object script) throws BSFException {
135 try {
136
137 source = convertToValidJavaClassname(source);
138 getEvalShell().evaluate(script.toString(), source);
139 } catch (Exception e) {
140 throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "exception from Groovy: " + e, e);
141 }
142 }
143
144 /***
145 * Initialize the engine.
146 */
147 public void initialize(BSFManager mgr, String lang, Vector declaredBeans) throws BSFException {
148 super.initialize(mgr, lang, declaredBeans);
149
150
151 shell = new GroovyShell(mgr.getClassLoader());
152
153
154 shell.setVariable("bsf", new BSFFunctions(mgr, this));
155
156 int size = declaredBeans.size();
157 for (int i = 0; i < size; i++) {
158 declareBean((BSFDeclaredBean) declaredBeans.elementAt(i));
159 }
160 }
161
162 /***
163 * Declare a bean
164 */
165 public void declareBean(BSFDeclaredBean bean) throws BSFException {
166 shell.setVariable(bean.name, bean.bean);
167 }
168
169 /***
170 * Undeclare a previously declared bean.
171 */
172 public void undeclareBean(BSFDeclaredBean bean) throws BSFException {
173 shell.setVariable(bean.name, null);
174 }
175
176 /***
177 * @return a newly created GroovyShell using the same variable scope but a new class loader
178 */
179 protected GroovyShell getEvalShell() {
180 return new GroovyShell(shell);
181 }
182 }