1 16 17 package org.pentaho.plugin.javascript; 18 19 import java.util.ArrayList ; 20 import java.util.Iterator ; 21 import java.util.Set ; 22 23 import org.apache.commons.logging.Log; 24 import org.apache.commons.logging.LogFactory; 25 import org.mozilla.javascript.Context; 26 import org.mozilla.javascript.NativeArray; 27 import org.mozilla.javascript.Scriptable; 28 import org.mozilla.javascript.ScriptableObject; 29 import org.pentaho.core.connection.IPentahoResultSet; 30 import org.pentaho.core.connection.javascript.JavaScriptResultSet; 31 import org.pentaho.core.connection.javascript.RhinoScriptable; 32 import org.pentaho.core.solution.IActionResource; 33 import org.pentaho.messages.Messages; 34 import org.pentaho.plugin.ComponentBase; 35 36 42 public class JavascriptRule extends ComponentBase { 43 44 47 private static final long serialVersionUID = -8305132222755452461L; 48 49 private boolean oldStyleOutputs; 50 51 public Log getLogger() { 52 return LogFactory.getLog(JavascriptRule.class); 53 } 54 55 protected boolean validateSystemSettings() { 56 return true; 58 } 59 60 protected boolean validateAction() { 61 if (!isDefinedInput("script")) { error(Messages.getErrorString("JSRULE.ERROR_0001_SCRIPT_NOT_DEFINED", getActionName())); return false; 64 } 65 66 85 Set outputs = getOutputNames(); 86 if ((outputs == null) || (outputs.size() == 0)) { 87 error(Messages.getString("Template.ERROR_0002_OUTPUT_COUNT_WRONG")); return false; 89 } 90 if ((outputs.size() > 1) && isDefinedInput("output" + 1)) { oldStyleOutputs = true; 92 int size = outputs.size(); 93 for (int i = 1; i <= size; ++i) { 94 if (!isDefinedInput("output" + i)) { error(Messages.getErrorString("JavascriptRule.ERROR_0006_NO_MAPPED_OUTPUTS", String.valueOf(outputs.size()), String.valueOf(i))); return (false); 97 } 98 outputs.remove(getInputStringValue("output" + i)); } 100 if (outputs.size() > 0) { 101 for (int i = 1; i <= outputs.size(); ++i) { 102 error(Messages.getErrorString("JavascriptRule.ERROR_0007_MISSING_OUTPUT_OUTPUT_X_MAP", getInputStringValue("output" + i))); } 104 return (false); 105 } 106 } 107 return true; 108 } 109 110 public void done() { 111 } 112 113 118 protected boolean executeAction() { 119 Context cx = Context.enter(); 120 StringBuffer buffer = new StringBuffer (); 121 Iterator iter = getResourceNames().iterator(); 122 while (iter.hasNext()) { 123 IActionResource resource = getResource(iter.next().toString()); 124 if ( "text/javascript".equalsIgnoreCase( resource.getMimeType() ) ) { buffer.append(getResourceAsString(resource)); 127 } 128 } 129 130 ArrayList outputNames = new ArrayList (); 131 Set outputs = getOutputNames(); 132 if (outputs.size() == 1) { 133 String outputName = (String ) outputs.iterator().next(); 134 outputNames.add(outputName); 135 } else { 136 if (oldStyleOutputs) { 137 int i = 1; 138 while (true) { 139 if (isDefinedInput("output" + i)) { String outputName = getInputStringValue("output" + i); outputNames.add(outputName); 142 } else { 143 break; 144 } 145 i++; 146 } 147 } else { 148 Iterator it = outputs.iterator(); 149 while (it.hasNext()) { 150 outputNames.add(it.next()); 151 } 152 } 153 } 154 155 boolean success = false; 156 try { 157 String script = getInputStringValue("script"); if (script == null) { 159 error(Messages.getErrorString("JSRULE.ERROR_0001_SCRIPT_NOT_DEFINED", getActionName())); } else { 161 buffer.append(script); 162 script = buffer.toString(); 163 if (debug) 164 debug("script=" + script); try { 166 ScriptableObject scriptable = new RhinoScriptable(); 167 Scriptable scope = cx.initStandardObjects(scriptable); 169 170 Object resultObject = executeScript(scriptable, scope, script, cx); 171 if (oldStyleOutputs) { 172 if (resultObject instanceof org.mozilla.javascript.NativeArray) { 173 NativeArray jsArray = (NativeArray) resultObject; 175 int length = (int) jsArray.getLength(); 176 for (int i = 0; i < length; i++) { 177 Object value = jsArray.get(i, scriptable); 178 if (i < outputNames.size()) { 179 String name = (String ) outputNames.get(i); 180 setOutputValue(name, convertWrappedJavaObject(value)); 181 } else { 182 break; 183 } 184 } 185 } else { 186 setOutputValue((String ) outputNames.get(0), convertWrappedJavaObject(resultObject)); 188 } 189 } else { 190 if ( (outputNames.size() == 1) && (resultObject != null)) { 191 setOutputValue((String ) outputNames.get(0), convertWrappedJavaObject(resultObject)); 192 } else { 193 ArrayList setOutputs = new ArrayList (outputNames.size()); 194 Object [] ids = ScriptableObject.getPropertyIds(scope); 195 for (int i = 0; i < ids.length; i++) { 196 int idx = outputNames.indexOf(ids[i].toString()); 197 if (idx >= 0) { 198 setOutputValue((String ) outputNames.get(idx), 199 convertWrappedJavaObject(ScriptableObject.getProperty(scope, (String ) ids[i]))); 200 setOutputs.add(outputNames.get(idx)); 201 } 202 } 203 if (setOutputs.size() != outputNames.size()) { 207 for (int i = 0; i < outputNames.size(); i++) { 208 if (setOutputs.indexOf(outputNames.get(i)) < 0) { 209 setOutputValue((String ) outputNames.get(i), null); 212 } 213 } 214 } 215 } 216 217 } 218 219 success = true; 220 } catch (Exception e) { 221 error(Messages.getErrorString("JSRULE.ERROR_0003_EXECUTION_FAILED"), e); } 223 } 224 } finally { 225 Context.exit(); 226 } 227 return success; 228 } 229 230 protected Object executeScript(ScriptableObject scriptable, Scriptable scope, String script, Context cx) throws Exception { 231 ScriptableObject.defineClass(scope, JavaScriptResultSet.class); 232 Set inputNames = getInputNames(); 233 Iterator inputNamesIterator = inputNames.iterator(); 234 String inputName; 235 Object inputValue; 236 while (inputNamesIterator.hasNext()) { 237 inputName = (String ) inputNamesIterator.next(); 238 if (inputName.indexOf('-')>=0) { 239 throw new IllegalArgumentException (Messages.getErrorString("JSRULE.ERROR_0006_INVALID_JS_VARIABLE", inputName)); } 241 inputValue = getInputValue(inputName); 242 Object wrapper; 243 if (inputValue instanceof IPentahoResultSet) { 244 JavaScriptResultSet results = new JavaScriptResultSet(); 245 results.setResultSet((IPentahoResultSet) inputValue); 246 wrapper = Context.javaToJS(inputValue, results); 247 } else { 248 wrapper = Context.javaToJS(inputValue, scope); 249 } 250 ScriptableObject.putProperty(scope, inputName, wrapper); 251 } 252 253 Object wrappedOut = Context.javaToJS(System.out, scope); 255 Object wrappedThis = Context.javaToJS(this, scope); 256 ScriptableObject.putProperty(scope, "out", wrappedOut); ScriptableObject.putProperty(scope, "rule", wrappedThis); return cx.evaluateString(scope, script, "<cmd>", 1, null); 261 } 262 263 protected Object convertWrappedJavaObject(Object obj) { 264 if (obj instanceof org.mozilla.javascript.NativeJavaObject) { 272 return ((org.mozilla.javascript.NativeJavaObject) obj).unwrap(); 273 } else { 274 return obj; 275 } 276 } 277 278 public boolean init() { 279 return true; 280 } 281 282 } 283 | Popular Tags |