/*
* Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com>
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: Groovy2Site.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.engine;
import com.uwyn.rife.config.RifeConfig;
import com.uwyn.rife.engine.exceptions.EngineException;
import com.uwyn.rife.engine.exceptions.NotFoundProcessingErrorException;
import com.uwyn.rife.engine.exceptions.ParsingErrorException;
import com.uwyn.rife.engine.exceptions.ProcessingErrorException;
import com.uwyn.rife.ioc.PropertyValueObject;
import com.uwyn.rife.resources.ResourceFinder;
import com.uwyn.rife.resources.exceptions.ResourceFinderErrorException;
import com.uwyn.rife.tools.Convert;
import com.uwyn.rife.tools.exceptions.InnerClassException;
import com.uwyn.rife.tools.InputStreamUser;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyCodeSource;
import groovy.lang.Script;
import groovy.util.BuilderSupport;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.runtime.InvokerHelper;
class Groovy2Site implements SiteProcessor
{
Groovy2Site()
{
}
public void processSite(SiteBuilder builder, String declarationName, ResourceFinder resourceFinder)
throws EngineException
{
GroovyProcessor processor = new GroovyProcessor(builder);
String processed_path = null;
try
{
// process the site declaration
try
{
processed_path = declarationName;
processor.processGroovy(processed_path, resourceFinder);
}
catch (NotFoundProcessingErrorException e)
{
processed_path = DEFAULT_SITES_PATH+declarationName;
processor.processGroovy(processed_path, resourceFinder);
}
}
catch (Exception e)
{
throw new ProcessingErrorException("site", declarationName, e);
}
// obtain the modification time
if (RifeConfig.Engine.getSiteAutoReload())
{
URL resource = resourceFinder.getResource(processed_path);
if (null == resource)
{
throw new NotFoundProcessingErrorException("site", processed_path, null);
}
try
{
builder.addResourceModificationTime(new UrlResource(resource, processed_path), resourceFinder.getModificationTime(resource));
}
catch (ResourceFinderErrorException e)
{
throw new ProcessingErrorException("site", declarationName, "Error while retrieving the modification time.", e);
}
}
}
private class GroovyProcessor extends BuilderSupport
{
private SiteBuilder mSiteBuilder = null;
private String mGroovyPath = null;
private ElementInfoBuilder mCurrentElementInfoBuilder = null;
private FlowLinkBuilder mCurrentFlowLinkBuilder = null;
private String mCurrentGlobalVar = null;
private ArrayList<String> mCurrentGlobalVarDefaults = null;
private String mCurrentGlobalCookie = null;
private String mCurrentGlobalCookieDefault = null;
private GroovyProcessor(SiteBuilder builder)
{
mSiteBuilder = builder;
}
public synchronized void processGroovy(final String groovyPath, ResourceFinder resourceFinder)
{
if (null == groovyPath) throw new IllegalArgumentException("groovyPath can't be null.");
if (groovyPath.length() == 0) throw new IllegalArgumentException("groovyPath can't be empty.");
if (null == resourceFinder) throw new IllegalArgumentException("resourceFinder can't be null.");
mGroovyPath = groovyPath;
// retrieve a stream towards the groovy script
Class script_class = null;
try
{
script_class = resourceFinder.useStream(groovyPath, new InputStreamUser() {
public Class useInputStream(InputStream stream)
throws InnerClassException
{
if (null == stream)
{
throw new NotFoundProcessingErrorException("site", groovyPath, null);
}
// parse the groovy script and create a class
try
{
GroovyClassLoader mLoader = new GroovyClassLoader(getClass().getClassLoader(), new CompilerConfiguration());
GroovyCodeSource code_source = new GroovyCodeSource(stream, "sitebuilder.groovy", "/groovy/shell");
try
{
return mLoader.parseClass(code_source);
}
catch (Throwable e)
{
throw new ParsingErrorException("site", groovyPath, e);
}
}
finally
{
try
{
stream.close();
}
catch (IOException e)
{
// don't do anything
}
}
}
});
}
catch (ResourceFinderErrorException e)
{
throw new NotFoundProcessingErrorException("site", groovyPath, e);
}
// setup the script bindings and run it
Binding binding = new Binding();
binding.setVariable("processor", this);
binding.setVariable("builder", mSiteBuilder);
Script script = InvokerHelper.createScript(script_class, binding);
script.run();
}
protected void setParent(Object parent, Object child)
{
// System.out.println("setParent "+parent+", "+child);
}
protected Object createNode(Object name)
{
return createNode(name, null, null);
}
protected Object createNode(Object node, Object value)
{
return createNode(node, null, value);
}
protected Object createNode(Object node, Map attributes)
{
return createNode(node, attributes, null);
}
protected Object createNode(Object node, Map atts, Object value)
{
// System.out.println("createNode "+qName+", "+atts+", "+value);
if (null == atts)
{
atts = new HashMap();
}
if (node.equals("site"))
{
mSiteBuilder.setFallback(Convert.toString(atts.get("fallbackid")));
}
else if (node.equals("subsite"))
{
mSiteBuilder
.enterSubsiteDeclaration(Convert.toString(atts.get("file")))
.setId(Convert.toString(atts.get("id")))
.setUrlPrefix(Convert.toString(atts.get("urlprefix")))
.enterSubsite()
.setInherits(Convert.toString(atts.get("inherits")))
.setPre(Convert.toString(atts.get("pre")))
.leaveSubsite()
.leaveSubsiteDeclaration();
}
else if (node.equals("group"))
{
String inherits = Convert.toString(atts.get("inherits"));
String pre = Convert.toString(atts.get("pre"));
mSiteBuilder.enterGroup()
.setInherits(inherits)
.setPre(pre);
}
else if (node.equals("globalvar"))
{
mCurrentGlobalVar = Convert.toString(atts.get("name"));
mCurrentGlobalVarDefaults = new ArrayList<String>();
}
else if (node.equals("globalcookie"))
{
mCurrentGlobalCookie = Convert.toString(atts.get("name"));
mCurrentGlobalCookieDefault = null;
}
else if (node.equals("globalbean"))
{
String classname = Convert.toString(atts.get("classname"));
String prefix = Convert.toString(atts.get("prefix"));
String name = Convert.toString(atts.get("name"));
String group = Convert.toString(atts.get("group"));
mSiteBuilder.addGlobalBean(classname, prefix, name, group);
}
else if (node.equals("globalexit"))
{
String name = Convert.toString(atts.get("name"));
String destid = Convert.toString(atts.get("destid"));
boolean reflective = Convert.toBoolean(atts.get("reflect"), false);
boolean snapback = Convert.toBoolean(atts.get("snapback"), false);
boolean redirect = Convert.toBoolean(atts.get("redirect"), false);
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean cancel_continuations = false;
String inheritance = Convert.toString(atts.get("inheritance"));
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = Convert.toString(atts.get("embedding"));
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = Convert.toString(atts.get("continuations"));
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mSiteBuilder.addGlobalExit(name, destid, reflective, snapback, cancel_inheritance, cancel_embedding, redirect, cancel_continuations);
}
else if (node.equals("arrival"))
{
boolean redirect = Convert.toBoolean(atts.get("redirect"), false);
mSiteBuilder.setArrival(Convert.toString(atts.get("destid")), redirect);
}
else if (node.equals("departure"))
{
mSiteBuilder.addDeparture(Convert.toString(atts.get("srcid")));
}
else if (node.equals("state"))
{
mSiteBuilder.enterState(Convert.toString(atts.get("store")));
}
else if (node.equals("element"))
{
mCurrentElementInfoBuilder = mSiteBuilder.enterElement(Convert.toString(atts.get("file")))
.setId(Convert.toString(atts.get("id")))
.setUrl(Convert.toString(atts.get("url")))
.setInherits(Convert.toString(atts.get("inherits")))
.setPre(Convert.toString(atts.get("pre")));
}
else if (node.equals("datalink"))
{
String srcoutput = Convert.toString(atts.get("srcoutput"));
String srcoutbean = Convert.toString(atts.get("srcoutbean"));
String dest_id = Convert.toString(atts.get("destid"));
boolean snapback = Convert.toBoolean(atts.get("snapback"), false);
String destinput = Convert.toString(atts.get("destinput"));
String destinbean = Convert.toString(atts.get("destinbean"));
if (mCurrentFlowLinkBuilder != null)
{
mCurrentFlowLinkBuilder.addDataLink(srcoutput, srcoutbean, snapback, destinput, destinbean);
}
else
{
mCurrentElementInfoBuilder.addDataLink(srcoutput, srcoutbean, dest_id, snapback, destinput, destinbean);
}
}
else if (node.equals("flowlink"))
{
String srcexit = Convert.toString(atts.get("srcexit"));
String destid = Convert.toString(atts.get("destid"));
boolean snapback = Convert.toBoolean(atts.get("snapback"), false);
boolean redirect = Convert.toBoolean(atts.get("redirect"), false);
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean cancel_continuations = false;
String inheritance = Convert.toString(atts.get("inheritance"));
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = Convert.toString(atts.get("embedding"));
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = Convert.toString(atts.get("continuations"));
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mCurrentFlowLinkBuilder = mCurrentElementInfoBuilder.enterFlowLink(srcexit)
.destId(destid)
.snapback(snapback)
.cancelInheritance(cancel_inheritance)
.cancelEmbedding(cancel_embedding)
.redirect(redirect)
.cancelContinuations(cancel_continuations);
}
else if (node.equals("autolink"))
{
String srcexit = Convert.toString(atts.get("srcexit"));
String destid = Convert.toString(atts.get("destid"));
boolean redirect = Convert.toBoolean(atts.get("redirect"), false);
boolean cancel_inheritance = false;
boolean cancel_embedding = false;
boolean cancel_continuations = false;
String inheritance = Convert.toString(atts.get("inheritance"));
if (inheritance != null &&
inheritance.equals("cancel"))
{
cancel_inheritance = true;
}
String embedding = Convert.toString(atts.get("embedding"));
if (embedding != null &&
embedding.equals("cancel"))
{
cancel_embedding = true;
}
String continuations = Convert.toString(atts.get("continuations"));
if (continuations != null &&
continuations.equals("cancel"))
{
cancel_continuations = true;
}
mCurrentElementInfoBuilder.addAutoLink(srcexit, destid, cancel_inheritance, cancel_embedding, redirect, cancel_continuations);
}
else if (node.equals("property"))
{
mCurrentElementInfoBuilder.addProperty(Convert.toString(atts.get("name")), new PropertyValueObject(value));
}
else if (node.equals("defaultvalue"))
{
if (null != mCurrentGlobalCookie)
{
mCurrentGlobalCookieDefault = (String)value;
}
else if( null != mCurrentGlobalVar )
{
mCurrentGlobalVarDefaults.add((String)value);
}
}
else
{
throw new ParsingErrorException("site", mGroovyPath, "Unsupport element name '"+node+"'.", null);
}
return node;
}
protected void nodeCompleted(Object parent, Object node)
{
// System.out.println("nodeCompleted "+parent+", "+node);
if (node.equals("element"))
{
mCurrentElementInfoBuilder.leaveElement();
mCurrentElementInfoBuilder = null;
}
else if (node.equals("flowlink"))
{
mCurrentFlowLinkBuilder.leaveFlowLink();
mCurrentFlowLinkBuilder = null;
}
else if (node.equals("state"))
{
mSiteBuilder.leaveState();
}
else if (node.equals("group"))
{
mSiteBuilder.leaveGroup();
}
else if (node.equals("globalvar"))
{
String[] defaults = null;
if (mCurrentGlobalVarDefaults.size() > 0)
{
defaults = new String[mCurrentGlobalVarDefaults.size()];
defaults = mCurrentGlobalVarDefaults.toArray(defaults);
}
mSiteBuilder.addGlobalVar(mCurrentGlobalVar, defaults);
mCurrentGlobalVar = null;
mCurrentGlobalVarDefaults = null;
}
else if (node.equals("globalcookie"))
{
mSiteBuilder.addGlobalCookie(mCurrentGlobalCookie, mCurrentGlobalCookieDefault);
mCurrentGlobalCookie = null;
mCurrentGlobalCookieDefault = null;
}
}
}
}