KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pentaho > plugin > javascript > JavascriptRule


1 /*
2  * Copyright 2006 Pentaho Corporation. All rights reserved.
3  * This software was developed by Pentaho Corporation and is provided under the terms
4  * of the Mozilla Public License, Version 1.1, or any later version. You may not use
5  * this file except in compliance with the license. If you need a copy of the license,
6  * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
7  * BI Platform. The Initial Developer is Pentaho Corporation.
8  *
9  * Software distributed under the Mozilla Public License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
11  * the license for the specific language governing your rights and limitations.
12  *
13  * @created Jun 28, 2005
14  * @author James Dixon
15  */

16
17 package org.pentaho.plugin.javascript;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Set JavaDoc;
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 /**
37  * @author James Dixon
38  *
39  * TODO To change the template for this generated type comment go to Window -
40  * Preferences - Java - Code Style - Code Templates
41  */

42 public class JavascriptRule extends ComponentBase {
43
44     /**
45      *
46      */

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         // This component does not have any system settings to validate
57
return true;
58     }
59
60     protected boolean validateAction() {
61         if (!isDefinedInput("script")) { //$NON-NLS-1$
62
error(Messages.getErrorString("JSRULE.ERROR_0001_SCRIPT_NOT_DEFINED", getActionName())); //$NON-NLS-1$
63
return false;
64         }
65
66     /*
67         Set libs = getResourceNames();
68         Iterator iter = libs.iterator();
69         while (iter.hasNext()) {
70             String name = iter.next().toString();
71             IActionResource libraryResource = getResource(name);
72             if ( "text/javascript".equalsIgnoreCase( libraryResource.getMimeType() ) ) { //$NON-NLS-1$
73                 if (!PentahoSystem.getSolutionRepository(getSession()).resourceExists(libraryResource.getAddress())) {
74                     error(Messages.getErrorString("JSRULE.ERROR_0004_LIBRARY_NOT_FOUND", name)); //$NON-NLS-1$
75                     return false;
76                 }
77                 if (PentahoSystem.getSolutionRepository(getSession()).resourceSize(libraryResource.getAddress()) > Integer.MAX_VALUE) {
78                     error(Messages.getErrorString("JSRULE.ERROR_0005_LIBRARY_TOO_LARGE", name, Integer.toBinaryString(Integer.MAX_VALUE))); //$NON-NLS-1$
79                     return false;
80                 }
81                 libraryResources.add(libraryResource);
82             }
83         }
84     */

85         Set JavaDoc outputs = getOutputNames();
86         if ((outputs == null) || (outputs.size() == 0)) {
87             error(Messages.getString("Template.ERROR_0002_OUTPUT_COUNT_WRONG")); //$NON-NLS-1$
88
return false;
89         }
90         if ((outputs.size() > 1) && isDefinedInput("output" + 1)) { //$NON-NLS-1$
91
oldStyleOutputs = true;
92             int size = outputs.size();
93             for (int i = 1; i <= size; ++i) {
94                 if (!isDefinedInput("output" + i)) { //$NON-NLS-1$
95
error(Messages.getErrorString("JavascriptRule.ERROR_0006_NO_MAPPED_OUTPUTS", String.valueOf(outputs.size()), String.valueOf(i))); //$NON-NLS-1$
96
return (false);
97                 }
98                 outputs.remove(getInputStringValue("output" + i)); //$NON-NLS-1$
99
}
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))); //$NON-NLS-1$//$NON-NLS-2$
103
}
104                 return (false);
105             }
106         }
107         return true;
108     }
109
110     public void done() {
111     }
112
113     /*
114      * (non-Javadoc)
115      *
116      * @see org.pentaho.component.ComponentBase#execute()
117      */

118     protected boolean executeAction() {
119         Context cx = Context.enter();
120         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
121         Iterator JavaDoc iter = getResourceNames().iterator();
122         while (iter.hasNext()) {
123             IActionResource resource = getResource(iter.next().toString());
124             // If this is a javascript resource then append it to the script string
125
if ( "text/javascript".equalsIgnoreCase( resource.getMimeType() ) ) { //$NON-NLS-1$
126
buffer.append(getResourceAsString(resource));
127             }
128         }
129
130         ArrayList JavaDoc outputNames = new ArrayList JavaDoc();
131         Set JavaDoc outputs = getOutputNames();
132         if (outputs.size() == 1) {
133             String JavaDoc outputName = (String JavaDoc) outputs.iterator().next();
134             outputNames.add(outputName);
135         } else {
136             if (oldStyleOutputs) {
137                 int i = 1;
138                 while (true) {
139                     if (isDefinedInput("output" + i)) { //$NON-NLS-1$
140
String JavaDoc outputName = getInputStringValue("output" + i); //$NON-NLS-1$
141
outputNames.add(outputName);
142                     } else {
143                         break;
144                     }
145                     i++;
146                 }
147             } else {
148                 Iterator JavaDoc it = outputs.iterator();
149                 while (it.hasNext()) {
150                     outputNames.add(it.next());
151                 }
152             }
153         }
154
155         boolean success = false;
156         try {
157             String JavaDoc script = getInputStringValue("script"); //$NON-NLS-1$
158
if (script == null) {
159                 error(Messages.getErrorString("JSRULE.ERROR_0001_SCRIPT_NOT_DEFINED", getActionName())); //$NON-NLS-1$
160
} else {
161                 buffer.append(script);
162                 script = buffer.toString();
163                 if (debug)
164                     debug("script=" + script); //$NON-NLS-1$
165
try {
166                     ScriptableObject scriptable = new RhinoScriptable();
167                     // initialize the standard javascript objects
168
Scriptable scope = cx.initStandardObjects(scriptable);
169
170                     Object JavaDoc resultObject = executeScript(scriptable, scope, script, cx);
171                     if (oldStyleOutputs) {
172                         if (resultObject instanceof org.mozilla.javascript.NativeArray) {
173                             // we need to convert this to an ArrayList
174
NativeArray jsArray = (NativeArray) resultObject;
175                             int length = (int) jsArray.getLength();
176                             for (int i = 0; i < length; i++) {
177                                 Object JavaDoc value = jsArray.get(i, scriptable);
178                                 if (i < outputNames.size()) {
179                                     String JavaDoc name = (String JavaDoc) outputNames.get(i);
180                                     setOutputValue(name, convertWrappedJavaObject(value));
181                                 } else {
182                                     break;
183                                 }
184                             }
185                         } else {
186                             // TODO: type handling
187
setOutputValue((String JavaDoc) outputNames.get(0), convertWrappedJavaObject(resultObject));
188                         }
189                     } else {
190                         if ( (outputNames.size() == 1) && (resultObject != null)) {
191                             setOutputValue((String JavaDoc) outputNames.get(0), convertWrappedJavaObject(resultObject));
192                         } else {
193                             ArrayList JavaDoc setOutputs = new ArrayList JavaDoc(outputNames.size());
194                             Object JavaDoc[] 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 JavaDoc) outputNames.get(idx),
199                                                     convertWrappedJavaObject(ScriptableObject.getProperty(scope, (String JavaDoc) ids[i])));
200                                     setOutputs.add(outputNames.get(idx));
201                                 }
202                             }
203                             // Javascript Component defined an output, but
204
// didn't set it to anything.
205
// So, set it to null.
206
if (setOutputs.size() != outputNames.size()) {
207                                 for (int i = 0; i < outputNames.size(); i++) {
208                                     if (setOutputs.indexOf(outputNames.get(i)) < 0) {
209                                         // An output that wasn't set in the
210
// javascript component
211
setOutputValue((String JavaDoc) outputNames.get(i), null);
212                                     }
213                                 }
214                             }
215                         }
216
217                     }
218
219                     success = true;
220                 } catch (Exception JavaDoc e) {
221                     error(Messages.getErrorString("JSRULE.ERROR_0003_EXECUTION_FAILED"), e); //$NON-NLS-1$
222
}
223             }
224         } finally {
225             Context.exit();
226         }
227         return success;
228     }
229
230     protected Object JavaDoc executeScript(ScriptableObject scriptable, Scriptable scope, String JavaDoc script, Context cx) throws Exception JavaDoc {
231         ScriptableObject.defineClass(scope, JavaScriptResultSet.class);
232         Set JavaDoc inputNames = getInputNames();
233         Iterator JavaDoc inputNamesIterator = inputNames.iterator();
234         String JavaDoc inputName;
235         Object JavaDoc inputValue;
236         while (inputNamesIterator.hasNext()) {
237             inputName = (String JavaDoc) inputNamesIterator.next();
238             if (inputName.indexOf('-')>=0) {
239               throw new IllegalArgumentException JavaDoc(Messages.getErrorString("JSRULE.ERROR_0006_INVALID_JS_VARIABLE", inputName)); //$NON-NLS-1$
240
}
241             inputValue = getInputValue(inputName);
242             Object JavaDoc 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         // Add system out and this object to the scope
254
Object JavaDoc wrappedOut = Context.javaToJS(System.out, scope);
255         Object JavaDoc wrappedThis = Context.javaToJS(this, scope);
256         ScriptableObject.putProperty(scope, "out", wrappedOut); //$NON-NLS-1$
257
ScriptableObject.putProperty(scope, "rule", wrappedThis); //$NON-NLS-1$
258
// evaluate the script
259
return cx.evaluateString(scope, script, "<cmd>", 1, null); //$NON-NLS-1$
260

261     }
262
263     protected Object JavaDoc convertWrappedJavaObject(Object JavaDoc obj) {
264         // If we wrap an object going in, and simply return the object,
265
// without unwrapping it, we're left with an object we can't
266
// use. Case in point was a Java array going in, and being
267
// wrapped as a org.mozilla.javascript.NativeJavaArray. On
268
// the way back into the context though, it stayed a mozilla
269
// object. This unwraps objects properly so that they can be
270
// recognized throughout the system.
271
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