001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Groovy2Site.java 3701 2007-03-18 12:24:23Z gbevin $
007: */
008: package com.uwyn.rife.engine;
009:
010: import com.uwyn.rife.config.RifeConfig;
011: import com.uwyn.rife.engine.exceptions.EngineException;
012: import com.uwyn.rife.engine.exceptions.NotFoundProcessingErrorException;
013: import com.uwyn.rife.engine.exceptions.ParsingErrorException;
014: import com.uwyn.rife.engine.exceptions.ProcessingErrorException;
015: import com.uwyn.rife.ioc.PropertyValueObject;
016: import com.uwyn.rife.resources.ResourceFinder;
017: import com.uwyn.rife.resources.exceptions.ResourceFinderErrorException;
018: import com.uwyn.rife.tools.Convert;
019: import com.uwyn.rife.tools.InnerClassException;
020: import com.uwyn.rife.tools.InputStreamUser;
021: import groovy.lang.Binding;
022: import groovy.lang.GroovyClassLoader;
023: import groovy.lang.GroovyCodeSource;
024: import groovy.lang.Script;
025: import groovy.util.BuilderSupport;
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.net.URL;
029: import java.util.ArrayList;
030: import java.util.HashMap;
031: import java.util.Map;
032: import org.codehaus.groovy.control.CompilerConfiguration;
033: import org.codehaus.groovy.runtime.InvokerHelper;
034:
035: class Groovy2Site implements SiteProcessor {
036: Groovy2Site() {
037: }
038:
039: public void processSite(SiteBuilder builder,
040: String declarationName, ResourceFinder resourceFinder)
041: throws EngineException {
042: GroovyProcessor processor = new GroovyProcessor(builder);
043:
044: String processed_path = null;
045: try {
046: // process the site declaration
047: try {
048: processed_path = declarationName;
049: processor.processGroovy(processed_path, resourceFinder);
050: } catch (NotFoundProcessingErrorException e) {
051: processed_path = DEFAULT_SITES_PATH + declarationName;
052: processor.processGroovy(processed_path, resourceFinder);
053: }
054: } catch (Exception e) {
055: throw new ProcessingErrorException("site", declarationName,
056: e);
057: }
058:
059: // obtain the modification time
060: if (RifeConfig.Engine.getSiteAutoReload()) {
061: URL resource = resourceFinder.getResource(processed_path);
062: if (null == resource) {
063: throw new NotFoundProcessingErrorException("site",
064: processed_path, null);
065: }
066:
067: try {
068: builder.addResourceModificationTime(new UrlResource(
069: resource, processed_path), resourceFinder
070: .getModificationTime(resource));
071: } catch (ResourceFinderErrorException e) {
072: throw new ProcessingErrorException(
073: "site",
074: declarationName,
075: "Error while retrieving the modification time.",
076: e);
077: }
078: }
079: }
080:
081: private class GroovyProcessor extends BuilderSupport {
082: private SiteBuilder mSiteBuilder = null;
083: private String mGroovyPath = null;
084:
085: private ElementInfoBuilder mCurrentElementInfoBuilder = null;
086: private FlowLinkBuilder mCurrentFlowLinkBuilder = null;
087:
088: private String mCurrentGlobalVar = null;
089: private ArrayList<String> mCurrentGlobalVarDefaults = null;
090:
091: private String mCurrentGlobalCookie = null;
092: private String mCurrentGlobalCookieDefault = null;
093:
094: private GroovyProcessor(SiteBuilder builder) {
095: mSiteBuilder = builder;
096: }
097:
098: public synchronized void processGroovy(final String groovyPath,
099: ResourceFinder resourceFinder) {
100: if (null == groovyPath)
101: throw new IllegalArgumentException(
102: "groovyPath can't be null.");
103: if (groovyPath.length() == 0)
104: throw new IllegalArgumentException(
105: "groovyPath can't be empty.");
106: if (null == resourceFinder)
107: throw new IllegalArgumentException(
108: "resourceFinder can't be null.");
109:
110: mGroovyPath = groovyPath;
111:
112: // retrieve a stream towards the groovy script
113: Class script_class = null;
114: try {
115: script_class = resourceFinder.useStream(groovyPath,
116: new InputStreamUser() {
117: public Class useInputStream(
118: InputStream stream)
119: throws InnerClassException {
120: if (null == stream) {
121: throw new NotFoundProcessingErrorException(
122: "site", groovyPath, null);
123: }
124:
125: // parse the groovy script and create a class
126: try {
127: GroovyClassLoader mLoader = new GroovyClassLoader(
128: getClass().getClassLoader(),
129: new CompilerConfiguration());
130: GroovyCodeSource code_source = new GroovyCodeSource(
131: stream,
132: "sitebuilder.groovy",
133: "/groovy/shell");
134: try {
135: return mLoader
136: .parseClass(code_source);
137: } catch (Throwable e) {
138: throw new ParsingErrorException(
139: "site", groovyPath, e);
140: }
141: } finally {
142: try {
143: stream.close();
144: } catch (IOException e) {
145: // don't do anything
146: }
147: }
148: }
149: });
150: } catch (ResourceFinderErrorException e) {
151: throw new NotFoundProcessingErrorException("site",
152: groovyPath, e);
153: }
154:
155: // setup the script bindings and run it
156: Binding binding = new Binding();
157: binding.setVariable("processor", this );
158: binding.setVariable("builder", mSiteBuilder);
159: Script script = InvokerHelper.createScript(script_class,
160: binding);
161: script.run();
162: }
163:
164: protected void setParent(Object parent, Object child) {
165: // System.out.println("setParent "+parent+", "+child);
166: }
167:
168: protected Object createNode(Object name) {
169: return createNode(name, null, null);
170: }
171:
172: protected Object createNode(Object node, Object value) {
173: return createNode(node, null, value);
174: }
175:
176: protected Object createNode(Object node, Map attributes) {
177: return createNode(node, attributes, null);
178: }
179:
180: protected Object createNode(Object node, Map atts, Object value) {
181: // System.out.println("createNode "+qName+", "+atts+", "+value);
182:
183: if (null == atts) {
184: atts = new HashMap();
185: }
186:
187: if (node.equals("site")) {
188: mSiteBuilder.setFallback(Convert.toString(atts
189: .get("fallbackid")));
190: } else if (node.equals("subsite")) {
191: mSiteBuilder.enterSubsiteDeclaration(
192: Convert.toString(atts.get("file"))).setId(
193: Convert.toString(atts.get("id"))).setUrlPrefix(
194: Convert.toString(atts.get("urlprefix")))
195: .enterSubsite().setInherits(
196: Convert.toString(atts.get("inherits")))
197: .setPre(Convert.toString(atts.get("pre")))
198: .leaveSubsite().leaveSubsiteDeclaration();
199: } else if (node.equals("group")) {
200: String inherits = Convert
201: .toString(atts.get("inherits"));
202: String pre = Convert.toString(atts.get("pre"));
203:
204: mSiteBuilder.enterGroup().setInherits(inherits).setPre(
205: pre);
206: } else if (node.equals("globalvar")) {
207: mCurrentGlobalVar = Convert.toString(atts.get("name"));
208: mCurrentGlobalVarDefaults = new ArrayList<String>();
209: } else if (node.equals("globalcookie")) {
210: mCurrentGlobalCookie = Convert.toString(atts
211: .get("name"));
212: mCurrentGlobalCookieDefault = null;
213: } else if (node.equals("globalbean")) {
214: String classname = Convert.toString(atts
215: .get("classname"));
216: String prefix = Convert.toString(atts.get("prefix"));
217: String name = Convert.toString(atts.get("name"));
218: String group = Convert.toString(atts.get("group"));
219:
220: mSiteBuilder.addGlobalBean(classname, prefix, name,
221: group);
222: } else if (node.equals("globalexit")) {
223: String name = Convert.toString(atts.get("name"));
224: String destid = Convert.toString(atts.get("destid"));
225: boolean reflective = Convert.toBoolean(atts
226: .get("reflect"), false);
227: boolean snapback = Convert.toBoolean(atts
228: .get("snapback"), false);
229: boolean redirect = Convert.toBoolean(atts
230: .get("redirect"), false);
231: boolean cancel_inheritance = false;
232: boolean cancel_embedding = false;
233: boolean cancel_continuations = false;
234:
235: String inheritance = Convert.toString(atts
236: .get("inheritance"));
237: if (inheritance != null && inheritance.equals("cancel")) {
238: cancel_inheritance = true;
239: }
240:
241: String embedding = Convert.toString(atts
242: .get("embedding"));
243: if (embedding != null && embedding.equals("cancel")) {
244: cancel_embedding = true;
245: }
246:
247: String continuations = Convert.toString(atts
248: .get("continuations"));
249: if (continuations != null
250: && continuations.equals("cancel")) {
251: cancel_continuations = true;
252: }
253:
254: mSiteBuilder.addGlobalExit(name, destid, reflective,
255: snapback, cancel_inheritance, cancel_embedding,
256: redirect, cancel_continuations);
257: } else if (node.equals("arrival")) {
258: boolean redirect = Convert.toBoolean(atts
259: .get("redirect"), false);
260: mSiteBuilder.setArrival(Convert.toString(atts
261: .get("destid")), redirect);
262: } else if (node.equals("departure")) {
263: mSiteBuilder.addDeparture(Convert.toString(atts
264: .get("srcid")));
265: } else if (node.equals("state")) {
266: mSiteBuilder.enterState(Convert.toString(atts
267: .get("store")));
268: } else if (node.equals("element")) {
269: mCurrentElementInfoBuilder = mSiteBuilder.enterElement(
270: Convert.toString(atts.get("file"))).setId(
271: Convert.toString(atts.get("id"))).setUrl(
272: Convert.toString(atts.get("url"))).setInherits(
273: Convert.toString(atts.get("inherits"))).setPre(
274: Convert.toString(atts.get("pre")));
275: } else if (node.equals("datalink")) {
276: String srcoutput = Convert.toString(atts
277: .get("srcoutput"));
278: String srcoutbean = Convert.toString(atts
279: .get("srcoutbean"));
280:
281: String dest_id = Convert.toString(atts.get("destid"));
282: boolean snapback = Convert.toBoolean(atts
283: .get("snapback"), false);
284:
285: String destinput = Convert.toString(atts
286: .get("destinput"));
287: String destinbean = Convert.toString(atts
288: .get("destinbean"));
289:
290: if (mCurrentFlowLinkBuilder != null) {
291: mCurrentFlowLinkBuilder
292: .addDataLink(srcoutput, srcoutbean,
293: snapback, destinput, destinbean);
294: } else {
295: mCurrentElementInfoBuilder.addDataLink(srcoutput,
296: srcoutbean, dest_id, snapback, destinput,
297: destinbean);
298: }
299: } else if (node.equals("flowlink")) {
300: String srcexit = Convert.toString(atts.get("srcexit"));
301: String destid = Convert.toString(atts.get("destid"));
302: boolean snapback = Convert.toBoolean(atts
303: .get("snapback"), false);
304: boolean redirect = Convert.toBoolean(atts
305: .get("redirect"), false);
306: boolean cancel_inheritance = false;
307: boolean cancel_embedding = false;
308: boolean cancel_continuations = false;
309:
310: String inheritance = Convert.toString(atts
311: .get("inheritance"));
312: if (inheritance != null && inheritance.equals("cancel")) {
313: cancel_inheritance = true;
314: }
315:
316: String embedding = Convert.toString(atts
317: .get("embedding"));
318: if (embedding != null && embedding.equals("cancel")) {
319: cancel_embedding = true;
320: }
321:
322: String continuations = Convert.toString(atts
323: .get("continuations"));
324: if (continuations != null
325: && continuations.equals("cancel")) {
326: cancel_continuations = true;
327: }
328:
329: mCurrentFlowLinkBuilder = mCurrentElementInfoBuilder
330: .enterFlowLink(srcexit).destId(destid)
331: .snapback(snapback).cancelInheritance(
332: cancel_inheritance).cancelEmbedding(
333: cancel_embedding).redirect(redirect)
334: .cancelContinuations(cancel_continuations);
335: } else if (node.equals("autolink")) {
336: String srcexit = Convert.toString(atts.get("srcexit"));
337: String destid = Convert.toString(atts.get("destid"));
338: boolean redirect = Convert.toBoolean(atts
339: .get("redirect"), false);
340: boolean cancel_inheritance = false;
341: boolean cancel_embedding = false;
342: boolean cancel_continuations = false;
343:
344: String inheritance = Convert.toString(atts
345: .get("inheritance"));
346: if (inheritance != null && inheritance.equals("cancel")) {
347: cancel_inheritance = true;
348: }
349:
350: String embedding = Convert.toString(atts
351: .get("embedding"));
352: if (embedding != null && embedding.equals("cancel")) {
353: cancel_embedding = true;
354: }
355:
356: String continuations = Convert.toString(atts
357: .get("continuations"));
358: if (continuations != null
359: && continuations.equals("cancel")) {
360: cancel_continuations = true;
361: }
362:
363: mCurrentElementInfoBuilder.addAutoLink(srcexit, destid,
364: cancel_inheritance, cancel_embedding, redirect,
365: cancel_continuations);
366: } else if (node.equals("property")) {
367: mCurrentElementInfoBuilder.addProperty(Convert
368: .toString(atts.get("name")),
369: new PropertyValueObject(value));
370: } else if (node.equals("defaultvalue")) {
371: if (null != mCurrentGlobalCookie) {
372: mCurrentGlobalCookieDefault = (String) value;
373: } else if (null != mCurrentGlobalVar) {
374: mCurrentGlobalVarDefaults.add((String) value);
375: }
376: } else {
377: throw new ParsingErrorException("site", mGroovyPath,
378: "Unsupport element name '" + node + "'.", null);
379: }
380:
381: return node;
382: }
383:
384: protected void nodeCompleted(Object parent, Object node) {
385: // System.out.println("nodeCompleted "+parent+", "+node);
386:
387: if (node.equals("element")) {
388: mCurrentElementInfoBuilder.leaveElement();
389: mCurrentElementInfoBuilder = null;
390: } else if (node.equals("flowlink")) {
391: mCurrentFlowLinkBuilder.leaveFlowLink();
392: mCurrentFlowLinkBuilder = null;
393: } else if (node.equals("state")) {
394: mSiteBuilder.leaveState();
395: } else if (node.equals("group")) {
396: mSiteBuilder.leaveGroup();
397: } else if (node.equals("globalvar")) {
398: String[] defaults = null;
399: if (mCurrentGlobalVarDefaults.size() > 0) {
400: defaults = new String[mCurrentGlobalVarDefaults
401: .size()];
402: defaults = mCurrentGlobalVarDefaults
403: .toArray(defaults);
404: }
405: mSiteBuilder.addGlobalVar(mCurrentGlobalVar, defaults);
406: mCurrentGlobalVar = null;
407: mCurrentGlobalVarDefaults = null;
408: } else if (node.equals("globalcookie")) {
409: mSiteBuilder.addGlobalCookie(mCurrentGlobalCookie,
410: mCurrentGlobalCookieDefault);
411: mCurrentGlobalCookie = null;
412: mCurrentGlobalCookieDefault = null;
413: }
414: }
415: }
416: }
|