001: // $Id: BSH.java,v 1.12 2005/08/08 12:45:41 belaban Exp $
002:
003: package org.jgroups.protocols;
004:
005: import bsh.EvalError;
006: import bsh.Interpreter;
007: import org.jgroups.Address;
008: import org.jgroups.Event;
009: import org.jgroups.Header;
010: import org.jgroups.Message;
011: import org.jgroups.stack.Protocol;
012: import org.jgroups.util.Util;
013:
014: import java.io.IOException;
015: import java.io.ObjectInput;
016: import java.io.ObjectOutput;
017: import java.io.Serializable;
018:
019: /**
020: * Beanshell (<a href=http://www.beanshell.org>www.beanshell.org</a>) interpreter class.
021: * The <tt>eval()</tt> method receives Java code, executes it and returns the
022: * result of the evaluation (or an exception).
023: * User: Bela
024: * Date: Mar 8, 2003
025: * Time: 1:57:07 PM
026: * @author Bela Ban
027: */
028: public class BSH extends Protocol {
029: static final String name = "BSH";
030: Interpreter interpreter = null;
031:
032: public BSH() {
033: }
034:
035: public String getName() {
036: return name;
037: }
038:
039: public void init() throws Exception {
040: }
041:
042: public void start() throws Exception {
043: }
044:
045: public void stop() {
046: if (interpreter != null)
047: destroyInterpreter();
048: }
049:
050: public void destroy() {
051: }
052:
053: /** We have no up handler thread */
054: public void startUpHandler() {
055: }
056:
057: /** We have no down handler thread */
058: public void startDownHandler() {
059: }
060:
061: public void up(Event evt) {
062: Header h;
063: Message msg;
064: int type;
065:
066: if (evt.getType() == Event.MSG) {
067: msg = (Message) evt.getArg();
068: h = msg.removeHeader(name);
069: if (h != null && h instanceof BshHeader) {
070: type = ((BshHeader) h).type;
071: switch (type) {
072: case BshHeader.REQ:
073: handleRequest(msg.getSrc(), msg.getBuffer());
074: return;
075: case BshHeader.RSP:
076: msg.putHeader(name, h);
077: passUp(evt);
078: return;
079: case BshHeader.DESTROY_INTERPRETER:
080: destroyInterpreter();
081: return;
082: default:
083: if (log.isErrorEnabled())
084: log.error("header type was not REQ as expected"
085: + " (was " + type + ')');
086: return;
087: }
088: }
089: }
090: passUp(evt);
091: }
092:
093: void handleRequest(Address sender, byte[] buf) {
094: Object retval;
095: String code;
096:
097: if (buf == null) {
098: if (log.isErrorEnabled())
099: log.error("buffer was null");
100: return;
101: }
102:
103: code = new String(buf);
104:
105: // create interpreter just-in-time
106: if (interpreter == null) {
107: interpreter = new Interpreter();
108:
109: if (log.isInfoEnabled())
110: log.info("beanshell interpreter was created");
111: try {
112: interpreter.set("bsh_prot", this );
113:
114: if (log.isInfoEnabled())
115: log.info("set \"bsh_prot\" to " + this );
116: } catch (EvalError err) {
117: if (log.isErrorEnabled())
118: log.error("failed setting \"bsh_prot\": " + err);
119: }
120:
121: }
122:
123: try {
124: retval = interpreter.eval(code);
125:
126: if (log.isInfoEnabled())
127: log.info("eval: \"" + code + "\", retval=" + retval);
128: } catch (EvalError ex) {
129: if (log.isErrorEnabled())
130: log.error("error is " + Util.getStackTrace(ex));
131: retval = ex;
132: }
133:
134: if (sender != null) {
135: Message rsp = new Message(sender, null, null);
136:
137: // serialize the object if serializable, otherwise just send string
138: // representation
139: if (retval != null) {
140: if (retval instanceof Serializable)
141: rsp.setObject((Serializable) retval);
142: else
143: rsp.setObject(retval.toString());
144: }
145:
146: if (log.isInfoEnabled())
147: log.info("sending back response " + retval + " to "
148: + rsp.getDest());
149: rsp.putHeader(name, new BshHeader(BshHeader.RSP));
150: passDown(new Event(Event.MSG, rsp));
151: }
152: }
153:
154: /* --------------------------- Callbacks ---------------------------- */
155: // public Object eval(String code) throws Exception {
156: // Object retval=null;
157: // try {
158: // retval=interpreter.eval(code);
159: //
160: // if(log.isInfoEnabled()) log.info("BSH.eval()", "eval: \"" + code +
161: // "\", retval=" + retval);
162: // if(retval != null && !(retval instanceof Serializable)) {
163: // if(log.isErrorEnabled()) log.error("BSH.eval", "return value " + retval +
164: // " is not serializable, cannot be sent back " +
165: // "(returning null)");
166: // return null;
167: // }
168: // return retval;
169: // }
170: // catch(EvalError ex) {
171: // if(log.isErrorEnabled()) log.error("BSH.eval()", "error is " + Util.getStackTrace(ex));
172: // return ex;
173: // }
174: // }
175: //
176: public void destroyInterpreter() {
177: interpreter = null; // allow it to be garbage collected
178:
179: if (log.isInfoEnabled())
180: log.info("beanshell interpreter was destroyed");
181: }
182:
183: /* ------------------------ End of Callbacks ------------------------ */
184:
185: public static class BshHeader extends Header {
186: public static final int REQ = 1;
187: public static final int RSP = 2;
188: public static final int DESTROY_INTERPRETER = 3;
189: int type = REQ;
190:
191: public BshHeader() {
192: }
193:
194: public BshHeader(int type) {
195: this .type = type;
196: }
197:
198: public long size() {
199: return 10;
200: }
201:
202: public String toString() {
203: StringBuffer sb = new StringBuffer();
204: if (type == REQ)
205: sb.append("REQ");
206: else if (type == RSP)
207: sb.append("RSP");
208: else if (type == DESTROY_INTERPRETER)
209: sb.append("DESTROY_INTERPRETER");
210: else
211: sb.append("<unknown type>");
212: return sb.toString();
213: }
214:
215: public void writeExternal(ObjectOutput out) throws IOException {
216: out.writeInt(type);
217: }
218:
219: public void readExternal(ObjectInput in) throws IOException,
220: ClassNotFoundException {
221: type = in.readInt();
222: }
223:
224: }
225:
226: }
|