001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.graph.action;
023:
024: import java.util.HashMap;
025: import java.util.HashSet;
026: import java.util.Iterator;
027: import java.util.Map;
028: import java.util.Set;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.dom4j.Element;
033: import org.jbpm.context.def.VariableAccess;
034: import org.jbpm.context.exe.ContextInstance;
035: import org.jbpm.graph.def.Action;
036: import org.jbpm.graph.def.DelegationException;
037: import org.jbpm.graph.exe.ExecutionContext;
038: import org.jbpm.graph.exe.Token;
039: import org.jbpm.jpdl.xml.JpdlXmlReader;
040: import org.jbpm.jpdl.xml.Parsable;
041:
042: import bsh.Interpreter;
043: import bsh.TargetError;
044:
045: public class Script extends Action implements Parsable {
046:
047: private static final long serialVersionUID = 1L;
048:
049: protected String expression = null;
050: protected Set variableAccesses = null;
051:
052: public void read(Element scriptElement, JpdlXmlReader jpdlReader) {
053: if (scriptElement.isTextOnly()) {
054: expression = scriptElement.getText();
055: } else {
056: this .variableAccesses = new HashSet(jpdlReader
057: .readVariableAccesses(scriptElement));
058: expression = scriptElement.element("expression").getText();
059: }
060: }
061:
062: public void execute(ExecutionContext executionContext)
063: throws Exception {
064: Map outputMap = eval(executionContext);
065: setVariables(outputMap, executionContext);
066: }
067:
068: public Map eval(Token token) throws Exception {
069: return eval(new ExecutionContext(token));
070: }
071:
072: public Map eval(ExecutionContext executionContext) throws Exception {
073: Map inputMap = createInputMap(executionContext);
074: Set outputNames = getOutputNames();
075: return eval(inputMap, outputNames);
076: }
077:
078: public Map createInputMap(ExecutionContext executionContext) {
079: Token token = executionContext.getToken();
080:
081: Map inputMap = new HashMap();
082: inputMap.put("executionContext", executionContext);
083: inputMap.put("token", token);
084: inputMap.put("node", executionContext.getNode());
085: inputMap.put("task", executionContext.getTask());
086: inputMap
087: .put("taskInstance", executionContext.getTaskInstance());
088:
089: // if no readable variableInstances are specified,
090: ContextInstance contextInstance = executionContext
091: .getContextInstance();
092: if (!hasReadableVariable()) {
093: // we copy all the variableInstances of the context into the interpreter
094: Map variables = contextInstance.getVariables(token);
095: if (variables != null) {
096: Iterator iter = variables.entrySet().iterator();
097: while (iter.hasNext()) {
098: Map.Entry entry = (Map.Entry) iter.next();
099: String variableName = (String) entry.getKey();
100: Object variableValue = entry.getValue();
101: inputMap.put(variableName, variableValue);
102: }
103: }
104:
105: } else {
106: // we only copy the specified variableInstances into the interpreterz
107: Iterator iter = variableAccesses.iterator();
108: while (iter.hasNext()) {
109: VariableAccess variableAccess = (VariableAccess) iter
110: .next();
111: if (variableAccess.isReadable()) {
112: String variableName = variableAccess
113: .getVariableName();
114: String mappedName = variableAccess.getMappedName();
115: Object variableValue = contextInstance.getVariable(
116: variableName, token);
117: inputMap.put(mappedName, variableValue);
118: }
119: }
120: }
121:
122: return inputMap;
123: }
124:
125: public Map eval(Map inputMap, Set outputNames) throws Exception {
126: Map outputMap = new HashMap();
127:
128: try {
129: log.debug("script input: " + inputMap);
130: Interpreter interpreter = new Interpreter();
131: Iterator iter = inputMap.keySet().iterator();
132: while (iter.hasNext()) {
133: String inputName = (String) iter.next();
134: Object inputValue = inputMap.get(inputName);
135: interpreter.set(inputName, inputValue);
136: }
137: interpreter.eval(expression);
138: iter = outputNames.iterator();
139: while (iter.hasNext()) {
140: String outputName = (String) iter.next();
141: Object outputValue = interpreter.get(outputName);
142: outputMap.put(outputName, outputValue);
143: }
144: log.debug("script output: " + outputMap);
145: } catch (TargetError e) {
146: throw new DelegationException(
147: "script evaluation exception", e.getTarget());
148: } catch (Exception e) {
149: log.warn(
150: "exception during evaluation of script expression",
151: e);
152: // try to throw the cause of the EvalError
153: if (e.getCause() instanceof Exception) {
154: throw (Exception) e.getCause();
155: } else if (e.getCause() instanceof Error) {
156: throw (Error) e.getCause();
157: } else {
158: throw e;
159: }
160: }
161:
162: return outputMap;
163: }
164:
165: public void addVariableAccess(VariableAccess variableAccess) {
166: if (variableAccesses == null)
167: variableAccesses = new HashSet();
168: variableAccesses.add(variableAccess);
169: }
170:
171: Set getOutputNames() {
172: Set outputNames = new HashSet();
173: if (variableAccesses != null) {
174: Iterator iter = variableAccesses.iterator();
175: while (iter.hasNext()) {
176: VariableAccess variableAccess = (VariableAccess) iter
177: .next();
178: if (variableAccess.isWritable()) {
179: outputNames.add(variableAccess.getMappedName());
180: }
181: }
182: }
183: return outputNames;
184: }
185:
186: boolean hasReadableVariable() {
187: if (variableAccesses == null)
188: return false;
189: Iterator iter = variableAccesses.iterator();
190: while (iter.hasNext()) {
191: VariableAccess variableAccess = (VariableAccess) iter
192: .next();
193: if (variableAccess.isReadable()) {
194: return true;
195: }
196: }
197: return false;
198: }
199:
200: void setVariables(Map outputMap, ExecutionContext executionContext) {
201: if ((outputMap != null) && (!outputMap.isEmpty())
202: && (executionContext != null)) {
203: Map variableNames = getVariableNames();
204: ContextInstance contextInstance = executionContext
205: .getContextInstance();
206: Token token = executionContext.getToken();
207:
208: Iterator iter = outputMap.keySet().iterator();
209: while (iter.hasNext()) {
210: String mappedName = (String) iter.next();
211: String variableName = (String) variableNames
212: .get(mappedName);
213: contextInstance.setVariable(variableName, outputMap
214: .get(mappedName), token);
215: }
216: }
217: }
218:
219: Map getVariableNames() {
220: Map variableNames = new HashMap();
221: Iterator iter = variableAccesses.iterator();
222: while (iter.hasNext()) {
223: VariableAccess variableAccess = (VariableAccess) iter
224: .next();
225: if (variableAccess.isWritable()) {
226: variableNames.put(variableAccess.getMappedName(),
227: variableAccess.getVariableName());
228: }
229: }
230: return variableNames;
231: }
232:
233: public String getExpression() {
234: return expression;
235: }
236:
237: public void setExpression(String expression) {
238: this .expression = expression;
239: }
240:
241: public Set getVariableAccesses() {
242: return variableAccesses;
243: }
244:
245: public void setVariableAccesses(Set variableAccesses) {
246: this .variableAccesses = variableAccesses;
247: }
248:
249: private static final Log log = LogFactory.getLog(Script.class);
250: }
|