KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > util > JavaScriptHelper


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.forms.util;
17
18 import java.io.IOException JavaDoc;
19 import java.io.StringReader JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import org.apache.avalon.framework.CascadingRuntimeException;
24 import org.apache.cocoon.components.flow.FlowHelper;
25 import org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptFlowHelper;
26 import org.mozilla.javascript.Context;
27 import org.mozilla.javascript.Function;
28 import org.mozilla.javascript.JavaScriptException;
29 import org.mozilla.javascript.Script;
30 import org.mozilla.javascript.Scriptable;
31 import org.w3c.dom.Element JavaDoc;
32
33 /**
34  * Helper methods to use JavaScript in various locations of the Cocoon Forms configuration files
35  * such as event listeners and bindings.
36  *
37  * @author <a HREF="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
38  * @version $Id: JavaScriptHelper.java 289538 2005-09-16 13:46:22Z sylvain $
39  */

40 public class JavaScriptHelper {
41
42     /**
43      * A shared root scope, avoiding to recreate a new one each time.
44      */

45     private static Scriptable _rootScope = null;
46
47     /**
48      * Build a script with the content of a DOM element.
49      *
50      * @param element the element containing the script
51      * @return the compiled script
52      * @throws IOException
53      */

54     public static Script buildScript(Element JavaDoc element) throws IOException JavaDoc {
55         String JavaDoc jsText = DomHelper.getElementText(element);
56         String JavaDoc sourceName = DomHelper.getSystemIdLocation(element);
57
58         Context ctx = Context.enter();
59         Script script;
60         try {
61             script = ctx.compileReader(
62                 getRootScope(), //scope
63
new StringReader JavaDoc(jsText), // in
64
sourceName == null ? "<unknown>" : sourceName, // sourceName
65
DomHelper.getLineLocation(element), // lineNo
66
null // securityDomain
67
);
68         } finally {
69             Context.exit();
70         }
71         return script;
72     }
73
74     /**
75      * Build a function with the content of a DOM element.
76      *
77      * @param element the element containing the function body
78      * @param name the name of the function
79      * @param argumentNames names of the function arguments
80      * @return the compiled function
81      * @throws IOException
82      */

83     public static Function buildFunction(Element JavaDoc element, String JavaDoc name, String JavaDoc[] argumentNames) throws IOException JavaDoc {
84         // Enclose the script text with a function declaration
85
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("function ").append(name).append("(");
86         for (int i = 0; i < argumentNames.length; i++) {
87             if (i > 0) {
88                 buffer.append(',');
89             }
90             buffer.append(argumentNames[i]);
91         }
92         buffer.append(") {\n").append(DomHelper.getElementText(element)).append("\n}");
93         
94         String JavaDoc jsText = buffer.toString();
95         String JavaDoc sourceName = DomHelper.getSystemIdLocation(element);
96
97         Context ctx = Context.enter();
98         Function func;
99         try {
100             func = ctx.compileFunction(
101                 getRootScope(), //scope
102
jsText, // in
103
sourceName == null ? "<unknown>" : sourceName, // sourceName
104
DomHelper.getLineLocation(element) - 1, // lineNo, "-1" because we added "function..."
105
null // securityDomain
106
);
107         } finally {
108             Context.exit();
109         }
110         return func;
111     }
112
113     /**
114      * Get a root scope for building child scopes.
115      *
116      * @return an appropriate root scope
117      */

118     public static Scriptable getRootScope() {
119         // FIXME: TemplateOMH should be used in 2.2
120
//return TemplateObjectModelHelper.getScope();
121

122         
123         if (_rootScope == null) {
124             // Create it if never used up to now
125
Context ctx = Context.enter();
126             try {
127                 _rootScope = ctx.initStandardObjects(null);
128             } finally {
129                 Context.exit();
130             }
131         }
132         return _rootScope;
133     }
134
135     /**
136      * Get a parent scope for building a child scope. The request is searched for an existing scope
137      * that can be provided by a flowscript higher in the call stack, giving visibility to flowscript
138      * functions and global (session) variables.
139      *
140      * @param objectModel the object model where the flowscript scope will be searched (can be <code>null</code>).
141      * @return an appropriate parent scope.
142      */

143     public static Scriptable getParentScope(Map JavaDoc objectModel) {
144         // Try to get the flowscript scope
145
Scriptable parentScope = null;
146         if (objectModel != null) {
147             parentScope = FOM_JavaScriptFlowHelper.getFOM_FlowScope(objectModel);
148         }
149
150         if (parentScope != null) {
151             return parentScope;
152         } else {
153             return getRootScope();
154         }
155     }
156
157     public static Object JavaDoc execScript(Script script, Map JavaDoc values, Map JavaDoc objectModel) throws JavaScriptException {
158         Context ctx = Context.enter();
159         try {
160             Scriptable parentScope = getParentScope(objectModel);
161
162             // Create a new local scope
163
Scriptable scope;
164             try {
165                 scope = ctx.newObject(parentScope);
166             } catch (Exception JavaDoc e) {
167                 // Should normally not happen
168
throw new CascadingRuntimeException("Cannont create script scope", e);
169             }
170             scope.setParentScope(parentScope);
171
172             // Populate the scope
173
Iterator JavaDoc iter = values.entrySet().iterator();
174             while(iter.hasNext()) {
175                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iter.next();
176                 String JavaDoc key = (String JavaDoc)entry.getKey();
177                 Object JavaDoc value = entry.getValue();
178                 scope.put(key, scope, Context.toObject(value, scope));
179             }
180             
181             if (objectModel != null) {
182                 Object JavaDoc viewData = FlowHelper.getContextObject(objectModel);
183                 if (viewData != null) {
184                     scope.put("viewData", scope, Context.toObject(viewData, scope));
185                 }
186             }
187
188             Object JavaDoc result = script.exec(ctx, scope);
189             return FlowHelper.unwrap(result);
190         } finally {
191             Context.exit();
192         }
193     }
194     
195     public static Object JavaDoc callFunction(Function func, Object JavaDoc thisObject, Object JavaDoc[] arguments, Map JavaDoc objectModel) throws JavaScriptException {
196         Context ctx = Context.enter();
197         try {
198             Scriptable scope = getParentScope(objectModel);
199
200             if (objectModel != null) {
201                 Object JavaDoc viewData = FlowHelper.getContextObject(objectModel);
202                 if (viewData != null) {
203                     // Create a new local scope to hold the view data
204
Scriptable newScope;
205                     try {
206                         newScope = ctx.newObject(scope);
207                     } catch (Exception JavaDoc e) {
208                         // Should normally not happen
209
throw new CascadingRuntimeException("Cannont create function scope", e);
210                     }
211                     newScope.setParentScope(scope);
212                     scope = newScope;
213             
214                     scope.put("viewData", scope, Context.toObject(viewData, scope));
215                 }
216             }
217             Object JavaDoc result = func.call(ctx, scope, thisObject == null? null: Context.toObject(thisObject, scope), arguments);
218             return FlowHelper.unwrap(result);
219         } finally {
220             Context.exit();
221         }
222     }
223 }
224
Popular Tags