001: /*
002: Copyright (c) 2003 eInnovation Inc. All rights reserved
003:
004: This library is free software; you can redistribute it and/or modify it under the terms
005: of the GNU Lesser General Public License as published by the Free Software Foundation;
006: either version 2.1 of the License, or (at your option) any later version.
007:
008: This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
009: without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: See the GNU Lesser General Public License for more details.
011: */
012:
013: /*--
014:
015: Copyright (C) 2001-2002 Anthony Eden.
016: All rights reserved.
017:
018: */
019: package com.openedit.modules.scriptrunner;
020:
021: import java.io.FileNotFoundException;
022: import java.io.IOException;
023: import java.io.Reader;
024: import java.io.StringWriter;
025: import java.util.Iterator;
026: import java.util.Map;
027:
028: import javax.servlet.ServletContext;
029: import javax.servlet.http.HttpServletRequest;
030: import javax.servlet.http.HttpServletResponse;
031: import javax.servlet.http.HttpSession;
032:
033: import org.apache.bsf.BSFException;
034: import org.apache.bsf.BSFManager;
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.openedit.repository.ContentItem;
038: import org.openedit.repository.filesystem.StringItem;
039: import org.springframework.beans.factory.BeanFactory;
040:
041: import com.openedit.OpenEditException;
042: import com.openedit.WebPageRequest;
043: import com.openedit.modules.BaseModule;
044: import com.openedit.page.Page;
045: import com.openedit.page.PageAction;
046: import com.openedit.page.PageRequestKeys;
047: import com.openedit.page.PageStreamer;
048: import com.openedit.util.OutputFiller;
049: import com.openedit.util.PathUtilities;
050: import com.openedit.util.URLUtilities;
051:
052: /**
053: * An action which is implemented in a BSF supported scripting language. Script actions have
054: * access to several varibles:
055: *
056: * <p>
057: * These are always available:
058: * </p>
059: *
060: * <p>
061: * <b>site</b> - The SiteContext<br><b>syslog</b> - Standard logging stream (Log4J Category)<br>
062: * </p>
063: *
064: * <p>
065: * If there is a context defined when the action is executed (all actions excluding startup
066: * actions):
067: * </p>
068: *
069: * <p>
070: * <b>context</b> - The current context<br>
071: * <b>application</b> - The ServletContext<br>
072: * <b>request</b> - The HTTP request<br>
073: * <b>response</b> - The HTTP response<br>
074: * <b>session</b> - The HTTP session<br>
075: * <b>page</b> - The Page object<br>
076: * </p>
077: *
078: * @author Anthony Eden
079: * @author Matt Avery, mavery@einnovation.com (converted to Spring framework)
080: */
081: public class ScriptModule extends BaseModule implements PageRequestKeys {
082:
083: public static final String SCRIPT_TAG = "script";
084: private static Log log = LogFactory.getLog(ScriptModule.class);
085:
086: public ScriptModule() {
087: super ();
088: }
089:
090: /**
091: * Execute the action script represented by this ScriptAction.
092: *
093: * @param context The current context
094: *
095: * @throws OpenEditException
096: */
097: public synchronized void run(WebPageRequest context)
098: throws OpenEditException {
099: PageAction inAction = context.getCurrentAction();
100: String code = inAction.getConfig().getChildValue(SCRIPT_TAG);
101: //this could be passed in via the config
102:
103: ScriptLogger logger = new ScriptLogger();
104: context.putPageValue("log", logger);
105:
106: Map variableMap = context.getPageMap();
107: //TODO: Replace these with an OpenEdit object so they can call OpenEdit.getUserManager()
108:
109: String filepath = context.getPath();
110: code = PathUtilities.resolveRelativePath(code, filepath);
111:
112: execScript(variableMap, code);
113: }
114:
115: public void execScript(Map variableMap, String code)
116: throws OpenEditException {
117: variableMap.put("userManager", getUserManager());
118: variableMap.put("moduleManager", getModuleManager());
119: variableMap.put("pageManager", getPageManager());
120: variableMap.put("root", getRoot());
121:
122: Script script = loadScript(code);
123: log.info("Executing script: " + script.getDescription());
124:
125: try {
126: if (script.getDescription().endsWith(".js")) {
127: execWithRhino(script, variableMap);
128:
129: //execWithBsf(context, configuration);
130: } else {
131: execWithBsf(script, variableMap);
132: }
133: } catch (Exception e) {
134: if (e instanceof OpenEditException) {
135: throw (OpenEditException) e;
136: }
137: throw new OpenEditException(e);
138: }
139: }
140:
141: public Script loadScript(String code) throws OpenEditException {
142: try {
143:
144: Page scriptPage = getPageManager().getPage(code);
145:
146: Reader in = scriptPage.getReader();
147: StringWriter out = new StringWriter();
148: new OutputFiller().fill(in, out);
149: in.close();
150: out.close();
151: String text = out.toString();
152: Script script = new Script(text, code);
153: return script;
154: } catch (Exception ex) {
155: throw new OpenEditException(ex);
156: }
157: }
158:
159: public void saveScript(String code, String filepath, String inScript)
160: throws OpenEditException {
161: try {
162: String relativecode = PathUtilities.buildRelative(code,
163: filepath);
164: Page scriptPage = getPageManager().getPage(relativecode);
165: ContentItem scriptItem = new StringItem(relativecode,
166: inScript, scriptPage.getCharacterEncoding());
167: scriptPage.setContentItem(scriptItem);
168: getPageManager().putPage(scriptPage);
169: } catch (Exception ex) {
170: throw new OpenEditException(ex);
171: }
172: }
173:
174: /**
175: * DOCUMENT ME!
176: *
177: * @param runner
178: * @param context
179: *
180: * @throws ScriptException DOCME
181: */
182: protected void declareAll(ScriptRunner runner, Map context)
183: throws OpenEditException {
184: if (context != null) {
185: for (Iterator iter = context.keySet().iterator(); iter
186: .hasNext();) {
187: String element = (String) iter.next();
188: runner.declareBean((String) element, context
189: .get(element));
190: }
191: }
192: runner.declareBean("beanFactory", getBeanFactory());
193: }
194:
195: protected void execWithBsf(Script script, Map context)
196: throws BSFException, IOException, FileNotFoundException {
197: BSFManager bsfManager = new BSFManager();
198:
199: // expose standard items in the context
200: if (context != null) {
201: //TODO: Why not add all the items in there? Performance?
202: ServletContext application = (ServletContext) context
203: .get(SERVLET_CONTEXT);
204: HttpServletRequest request = (HttpServletRequest) context
205: .get(REQUEST);
206: HttpServletResponse response = (HttpServletResponse) context
207: .get(RESPONSE);
208: HttpSession session = (HttpSession) context.get(SESSION);
209: Page page = (Page) context.get(PAGE);
210: PageStreamer pages = (PageStreamer) context.get(PAGES);
211:
212: // expose the context
213: bsfManager.declareBean("context", context.get("context"),
214: WebPageRequest.class);
215: bsfManager.declareBean(URL_UTILITIES, context
216: .get(URL_UTILITIES), URLUtilities.class);
217:
218: // expose the page object.
219: if (page == null) {
220: log.debug("Page request is null");
221: } else {
222: bsfManager.declareBean(PAGE, page, Page.class);
223: }
224:
225: // expose the pages object.
226: if (pages == null) {
227: log.debug("Pages request is null");
228: } else {
229: bsfManager
230: .declareBean(PAGES, pages, PageStreamer.class);
231: }
232:
233: // expose standard HttpServlet objects
234: if (request == null) {
235: log.debug("HTTP request is null");
236: } else {
237: bsfManager.declareBean(REQUEST, request,
238: HttpServletRequest.class);
239: }
240:
241: if (response == null) {
242: log.debug("HTTP response is null");
243: } else {
244: bsfManager.declareBean(RESPONSE, response,
245: HttpServletResponse.class);
246: }
247:
248: if (session == null) {
249: log.debug("HTTP session is null");
250: } else {
251: bsfManager.declareBean(SESSION, session,
252: HttpSession.class);
253: }
254:
255: if (application == null) {
256: log.debug("ServletContext is null");
257: } else {
258: bsfManager.declareBean(SERVLET_CONTEXT, application,
259: ServletContext.class);
260: }
261:
262: //bsfManager.declareBean( PAGEMANAGER, getPageManager(), PageManager.class );
263: //bsfManager.declareBean( USERMANAGER, getUserManager(), UserManager.class );
264: bsfManager.declareBean("beanFactory", getBeanFactory(),
265: BeanFactory.class);
266: }
267:
268: // these objects are exposed regardless if there is a context
269: // object or not. In other words they are accesible to startup
270: // actions
271: //bsfManager.declareBean("syslog", LogSystem.syslog, Logger.class);
272: //bsfManager.declareBean("site", getSiteContext(), SiteContext.class);
273:
274: // if(configuration == null){
275: // log.debug("Configuration is null");
276: // } else {
277: // bsfManager.declareBean("configuration", configuration, Configuration.class);
278: // }
279: bsfManager.exec(BSFManager.getLangFromFilename(script
280: .getDescription()), script.getDescription(), 0, 0,
281: script.getScriptText());
282: }
283:
284: protected void execWithRhino(Script inScript, Map inState)
285: throws Exception {
286:
287: ScriptRunner runner = new RhinoScriptRunner(inScript);
288:
289: //runner.declareBean("context", context);
290: declareAll(runner, inState);
291: runner.init();
292: runner.terminate();
293:
294: //CB One day we should be able to call functions within a single cached JavaScript file
295: //that would be really cool! the syntax could be ./myfile.js#somefunction
296: }
297:
298: }
|