KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > woody > 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.woody.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 Woody configuration files
35  * such as event listeners and bindings.
36  *
37  * @author <a HREF="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
38  * @version CVS $Id: JavaScriptHelper.java 30932 2004-07-29 17:35:38Z vgritsenko $
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 argumentNames names of the function arguments
79      * @return the compiled function
80      * @throws IOException
81      */

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

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

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