KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > javasupport > bsf > JRubyEngine


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
15  * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
16  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
17  * Copyright (C) 2004-2006 Thomas E Enebo <enebo@acm.org>
18  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
19  * Copyright (C) 2005 Charles O Nutter <headius@headius.com>
20  *
21  * Alternatively, the contents of this file may be used under the terms of
22  * either of the GNU General Public License Version 2 or later (the "GPL"),
23  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
24  * in which case the provisions of the GPL or the LGPL are applicable instead
25  * of those above. If you wish to allow use of your version of this file only
26  * under the terms of either the GPL or the LGPL, and not to allow others to
27  * use your version of this file under the terms of the CPL, indicate your
28  * decision by deleting the provisions above and replace them with the notice
29  * and other provisions required by the GPL or the LGPL. If you do not delete
30  * the provisions above, a recipient may use your version of this file under
31  * the terms of any one of the CPL, the GPL or the LGPL.
32  ***** END LICENSE BLOCK *****/

33 package org.jruby.javasupport.bsf;
34
35 import java.util.Arrays JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Vector JavaDoc;
38
39 import org.apache.bsf.BSFDeclaredBean;
40 import org.apache.bsf.BSFException;
41 import org.apache.bsf.BSFManager;
42 import org.apache.bsf.util.BSFEngineImpl;
43 import org.apache.bsf.util.BSFFunctions;
44 import org.jruby.Ruby;
45 import org.jruby.ast.Node;
46 import org.jruby.exceptions.JumpException;
47 import org.jruby.exceptions.RaiseException;
48 import org.jruby.javasupport.Java;
49 import org.jruby.javasupport.JavaEmbedUtils;
50 import org.jruby.javasupport.JavaObject;
51 import org.jruby.javasupport.JavaUtil;
52 import org.jruby.runtime.Block;
53 import org.jruby.runtime.DynamicScope;
54 import org.jruby.runtime.GlobalVariable;
55 import org.jruby.runtime.IAccessor;
56 import org.jruby.runtime.ThreadContext;
57 import org.jruby.runtime.builtin.IRubyObject;
58
59 /** An implementation of a JRuby BSF implementation.
60  *
61  * @author jpetersen
62  */

63 public class JRubyEngine extends BSFEngineImpl {
64     private Ruby runtime;
65
66     public Object JavaDoc apply(String JavaDoc file, int line, int col, Object JavaDoc funcBody, Vector JavaDoc paramNames, Vector JavaDoc args) {
67         ThreadContext threadContext = runtime.getCurrentContext();
68         try {
69             // add a new method conext
70
String JavaDoc[] names = new String JavaDoc[paramNames.size()];
71             paramNames.toArray(names);
72
73             threadContext.preBsfApply(names);
74             
75             // FIXME: This is broken. We are assigning BSF globals as local vars in the top-level
76
// scope. This may be ok, but we are overwriting $~ and $_. Leaving for now.
77
DynamicScope scope = threadContext.getCurrentScope();
78
79             // set global variables
80
for (int i = 0, size = args.size(); i < size; i++) {
81                 scope.setValue(i, JavaEmbedUtils.javaToRuby(runtime, args.get(i)), 0);
82             }
83
84             // See eval todo about why this is commented out
85
//runtime.setPosition(file, line);
86

87             Node node = runtime.parse(file, funcBody.toString(), null);
88             return JavaEmbedUtils.rubyToJava(runtime, runtime.getTopSelf().eval(node), Object JavaDoc.class);
89         } finally {
90             threadContext.postBsfApply();
91         }
92     }
93
94     public Object JavaDoc eval(String JavaDoc file, int line, int col, Object JavaDoc expr) throws BSFException {
95         try {
96             // TODO: [JRUBY-24] This next line never would have worked correctly as a LexerSource
97
// would have thrown a parsing error with a name of "<script>" and a line
98
// value of whatever line in the string it is in. Find real way of returning
99
// what is expected.
100
//runtime.setPosition(file, line);
101
IRubyObject result = runtime.evalScript(expr.toString());
102             return JavaEmbedUtils.rubyToJava(runtime, result, Object JavaDoc.class);
103         } catch (Exception JavaDoc excptn) {
104             throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "Exception", excptn);
105         }
106     }
107
108     public void exec(String JavaDoc file, int line, int col, Object JavaDoc expr) throws BSFException {
109         try {
110             // See eval todo about why this is commented out
111
//runtime.setPosition(file, line);
112
runtime.evalScript(expr.toString());
113         } catch (Exception JavaDoc excptn) {
114             throw new BSFException(BSFException.REASON_EXECUTION_ERROR, "Exception", excptn);
115         }
116     }
117
118     public Object JavaDoc call(Object JavaDoc recv, String JavaDoc method, Object JavaDoc[] args) throws BSFException {
119         try {
120             return JavaEmbedUtils.invokeMethod(runtime, recv, method, args, Object JavaDoc.class);
121         } catch (Exception JavaDoc excptn) {
122             printException(runtime, excptn);
123             throw new BSFException(BSFException.REASON_EXECUTION_ERROR, excptn.getMessage(), excptn);
124         }
125     }
126
127     public void initialize(BSFManager manager, String JavaDoc language, Vector JavaDoc someDeclaredBeans) throws BSFException {
128         super.initialize(manager, language, someDeclaredBeans);
129
130         runtime = JavaEmbedUtils.initialize(getClassPath(manager));
131
132         for (int i = 0, size = someDeclaredBeans.size(); i < size; i++) {
133             BSFDeclaredBean bean = (BSFDeclaredBean) someDeclaredBeans.elementAt(i);
134             runtime.getGlobalVariables().define(
135                 GlobalVariable.variableName(bean.name),
136                 new BeanGlobalVariable(runtime, bean));
137         }
138
139         runtime.getGlobalVariables().defineReadonly("$bsf", new FunctionsGlobalVariable(runtime, new BSFFunctions(manager, this)));
140     }
141     
142     private List JavaDoc getClassPath(BSFManager manager) {
143         return Arrays.asList(manager.getClassPath().split(System.getProperty("path.separator")));
144     }
145
146     public void declareBean(BSFDeclaredBean bean) throws BSFException {
147         runtime.getGlobalVariables().define(
148             GlobalVariable.variableName(bean.name),
149             new BeanGlobalVariable(runtime, bean));
150     }
151
152     public void undeclareBean(BSFDeclaredBean bean) throws BSFException {
153         runtime.getGlobalVariables().set(GlobalVariable.variableName(bean.name), runtime.getNil());
154     }
155
156     public void handleException(BSFException bsfExcptn) {
157         printException(runtime, (Exception JavaDoc) bsfExcptn.getTargetException());
158     }
159
160     /**
161      *
162      * Prints out an error message.
163      *
164      * @param exception An Exception thrown by JRuby
165      */

166     private static void printException(Ruby runtime, Exception JavaDoc exception) {
167         if (exception instanceof JumpException) {
168             JumpException je = (JumpException)exception;
169             if (je.getJumpType() == JumpException.JumpType.RaiseJump) {
170                 runtime.printError(((RaiseException)je).getException());
171             } else if (je.getJumpType() == JumpException.JumpType.ThrowJump) {
172                 runtime.getErrorStream().println("internal error: throw jump caught");
173             } else if (je.getJumpType() == JumpException.JumpType.BreakJump) {
174                 runtime.getErrorStream().println("break without block.");
175             } else if (je.getJumpType() == JumpException.JumpType.ReturnJump) {
176                 runtime.getErrorStream().println("return without block.");
177             }
178         }
179     }
180
181     private static class BeanGlobalVariable implements IAccessor {
182         private Ruby runtime;
183         private BSFDeclaredBean bean;
184
185         public BeanGlobalVariable(Ruby runtime, BSFDeclaredBean bean) {
186             this.runtime = runtime;
187             this.bean = bean;
188         }
189
190         public IRubyObject getValue() {
191             IRubyObject result = JavaUtil.convertJavaToRuby(runtime, bean.bean, bean.type);
192             if (result instanceof JavaObject) {
193                 return runtime.getModule("JavaUtilities").callMethod(runtime.getCurrentContext(), "wrap", result);
194             }
195             return result;
196         }
197
198         public IRubyObject setValue(IRubyObject value) {
199             bean.bean = JavaUtil.convertArgument(Java.ruby_to_java(runtime.getObject(), value, Block.NULL_BLOCK), bean.type);
200             return value;
201         }
202     }
203
204     private static class FunctionsGlobalVariable implements IAccessor {
205         private Ruby runtime;
206         private BSFFunctions functions;
207
208         public FunctionsGlobalVariable(Ruby runtime, BSFFunctions functions) {
209             this.runtime = runtime;
210             this.functions = functions;
211         }
212
213         public IRubyObject getValue() {
214             IRubyObject result = JavaUtil.convertJavaToRuby(runtime, functions, BSFFunctions.class);
215             if (result instanceof JavaObject) {
216                 return runtime.getModule("JavaUtilities").callMethod(runtime.getCurrentContext(), "wrap", result);
217             }
218             return result;
219         }
220
221         public IRubyObject setValue(IRubyObject value) {
222             return value;
223         }
224     }
225
226     /**
227      * @see org.apache.bsf.BSFEngine#terminate()
228      */

229     public void terminate() {
230         JavaEmbedUtils.terminate(runtime);
231         runtime = null;
232         super.terminate();
233     }
234 }
235
Popular Tags