jstrachan 02/04/26 04:28:55 Modified: jelly/src/java/org/apache/commons/jelly Context.java Jelly.java jelly/src/java/org/apache/commons/jelly/tags/define DynamicTag.java InvokeBodyTag.java Log: Added support in the Context for getResource() to allow loading of resources via explicit URL or relative URI as well as a compile and run methods to invoke other jelly scripts from inside jelly. This needs testing but the code is just about there I think. Also fixed the invokeBody tag so that it works fine now - though it uses a private variable 'jelly.body' which is not ideal but works fine. Revision Changes Path 1.9 +130 -9 jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Context.java Index: Context.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Context.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- Context.java 25 Apr 2002 18:58:47 -0000 1.8 +++ Context.java 26 Apr 2002 11:28:55 -0000 1.9 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Context.java,v 1.8 2002/04/25 18:58:47 jstrachan Exp $ - * $Revision: 1.8 $ - * $Date: 2002/04/25 18:58:47 $ + * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Context.java,v 1.9 2002/04/26 11:28:55 jstrachan Exp $ + * $Revision: 1.9 $ + * $Date: 2002/04/26 11:28:55 $ * * ==================================================================== * @@ -57,14 +57,20 @@ * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * - * $Id: Context.java,v 1.8 2002/04/25 18:58:47 jstrachan Exp $ + * $Id: Context.java,v 1.9 2002/04/26 11:28:55 jstrachan Exp $ */ package org.apache.commons.jelly; +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; +import org.apache.commons.jelly.parser.XMLParser; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -72,10 +78,16 @@ /** <p><code>Context</code> represents the Jelly context.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.8 $ + * @version $Revision: 1.9 $ */ public class Context { + /** The root URL context (where scripts are located from) */ + private URL rootContext; + + /** The current URL context (where relative scripts are located from) */ + private URL currentContext; + /** Tag libraries found so far */ private Map taglibs = new Hashtable(); @@ -86,12 +98,30 @@ private Log log = LogFactory.getLog( Context.class ); public Context() { + this.currentContext = rootContext; } - public Context(Map variables) { - this.variables.putAll( variables ); + public Context(URL rootContext) { + this.rootContext = rootContext; + this.currentContext = rootContext; } + public Context(URL rootContext, URL currentContext) { + this.rootContext = rootContext; + this.currentContext = currentContext; + } + + public Context(Context parentContext) { + this.rootContext = parentContext.rootContext; + this.currentContext = parentContext.currentContext; + this.taglibs = parentContext.taglibs; + } + + public Context(Context parentContext, URL currentContext) { + this( parentContext ); + this.currentContext = currentContext; + } + /** @return the value of the given variable name */ public Object getVariable( String name ) { return variables.get( name ); @@ -145,8 +175,8 @@ // XXXX: Or at least publish the parent scope // XXXX: as a Map in this new variable scope? newVariables.put( "parentScope", variables ); - Context answer = new Context( newVariables ); - answer.taglibs = this.taglibs; + Context answer = new Context( this ); + answer.setVariables( newVariables ); return answer; } @@ -191,5 +221,96 @@ */ public TagLibrary getTagLibrary(String namespaceURI) { return (TagLibrary) taglibs.get( namespaceURI ); + } + + + /** + * Attempts to parse the script from the given uri using the + * {#link getResource()} method then returns the compiled script. + */ + public Script compileScript(String uri) throws Exception { + XMLParser parser = new XMLParser(); + parser.setContext( this ); + + Script script = parser.parse( getResourceAsStream( uri ) ); + return script.compile(); + } + + /** + * Attempts to parse the script from the given uri using the + * Context.getResource() API then compiles it and runs it. + */ + public void runScript(String uri, XMLOutput output) throws Exception { + Script script = compileScript( uri ); + script.run( this, output ); + } + + /** + * Returns a URL for the given resource from the specified path. + * If the uri starts with "/" then the path is taken as relative to + * the current context root. If the uri is a well formed URL then it + * is used. Otherwise the uri is interpreted as relative to the current + * context (the location of the current script). + */ + public URL getResource(String uri) throws MalformedURLException { + if ( uri.startsWith( "/" ) ) { + // append this uri to the context root + return createRelativeURL( rootContext, uri.substring(1) ); + } + else { + try { + return new URL( uri ); + } + catch (MalformedURLException e) { + // lets try find a relative resource + try { + return createRelativeURL( currentContext, uri ); + } + catch (MalformedURLException e2) { + throw e; + } + } + } + } + + /** + * Attempts to open an InputStream to the given resource at the specified path. + * If the uri starts with "/" then the path is taken as relative to + * the current context root. If the uri is a well formed URL then it + * is used. Otherwise the uri is interpreted as relative to the current + * context (the location of the current script). + * + * @return null if this resource could not be loaded, otherwise the resources + * input stream is returned. + */ + public InputStream getResourceAsStream(String uri) { + try { + URL url = getResource( uri ); + return url.openStream(); + } + catch (Exception e) { + if ( log.isTraceEnabled() ) { + log.trace( "Caught exception attempting to open: " + uri + ". Exception: " + e, e ); + } + return null; + } + } + + // Implementation methods + //------------------------------------------------------------------------- + + /** + * @return a new relative URL from the given root and with the addition of the + * extra relative URI + * + * @param rootURL is the root context from which the relative URI will be applied + * @param relativeURI is the relative URI (without a leading "/") + * @throws MalformedURLException if the URL is invalid. + */ + protected URL createRelativeURL(URL rootURL, String relativeURI) throws MalformedURLException { + if ( rootURL == null ) { + return new URL( "file://" + relativeURI ); + } + return new URL( rootURL.toString() + relativeURI ); } } 1.6 +95 -23 jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Jelly.java Index: Jelly.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Jelly.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- Jelly.java 25 Apr 2002 18:58:47 -0000 1.5 +++ Jelly.java 26 Apr 2002 11:28:55 -0000 1.6 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Jelly.java,v 1.5 2002/04/25 18:58:47 jstrachan Exp $ - * $Revision: 1.5 $ - * $Date: 2002/04/25 18:58:47 $ + * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/Jelly.java,v 1.6 2002/04/26 11:28:55 jstrachan Exp $ + * $Revision: 1.6 $ + * $Date: 2002/04/26 11:28:55 $ * * ==================================================================== * @@ -57,37 +57,56 @@ * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * - * $Id: Jelly.java,v 1.5 2002/04/25 18:58:47 jstrachan Exp $ + * $Id: Jelly.java,v 1.6 2002/04/26 11:28:55 jstrachan Exp $ */ package org.apache.commons.jelly; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; +import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.net.MalformedURLException; +import java.net.URL; import org.apache.commons.jelly.parser.XMLParser; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -/** <p><code>Jelly</code> an application which runs a Jelly script.</p> - * - * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.5 $ - */ +/** + * <p><code>Jelly</code> is a helper class which is capable of + * running a Jelly script. This class can be used from the command line + * or can be used as the basis of an Ant task.</p> + * + * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> + * @version $Revision: 1.6 $ + */ public class Jelly { /** The Log to which logging calls will be made. */ private static final Log log = LogFactory.getLog( Jelly.class ); - + /** The Context to use */ + private Context context; + + /** The URL of the script to execute */ + private URL url; + + public Jelly() { + } + + public static void main(String[] args) throws Exception { if ( args.length <= 0 ) { System.out.println( "Usage: Jelly scriptFile [outputFile]" ); return; } - String input = args[0]; + + Jelly jelly = new Jelly(); + jelly.setScript( args[0] ); + /* // later we might wanna add some command line arguments @@ -103,25 +122,78 @@ new OutputStreamWriter( System.out ) ); + Script script = jelly.compileScript(); + XMLOutput output = XMLOutput.createXMLOutput( writer ); + // add the system properties and the command line arguments - //Context context = new Context( System.getProperties() ); - Context context = new Context(); + Context context = jelly.getContext(); context.setVariable( "args", args ); + + script.run( context, output ); + writer.close(); + } + + /** + * Compiles the script + */ + public Script compileScript() throws Exception { XMLParser parser = new XMLParser(); - parser.setContext( context ); - Script script = parser.parse( input ); - + parser.setContext( getContext() ); + Script script = parser.parse( getUrl().openStream() ); script = script.compile(); if ( log.isDebugEnabled() ) { - log.debug( "Compiled script: " + script ); + log.debug( "Compiled script: " + getUrl() ); } + return script; + } + - XMLOutput output = XMLOutput.createXMLOutput( writer ); - - script.run( context, output ); - - writer.close(); - } + // Properties + //------------------------------------------------------------------------- + + /** + * Sets the script URL to use as an absolute URL or a relative filename + */ + public void setScript(String script) throws MalformedURLException { + setUrl( resolveURL( script ) ); + } + + public URL getUrl() { + return url; + } + + /** + * Sets the script URL to use + */ + public void setUrl(URL url) { + this.url = url; + } + + + /** + * The context to use + */ + public Context getContext() { + if ( context == null ) { + context = new Context( getUrl() ); + } + return context; + } + + // Properties + //------------------------------------------------------------------------- + + /** + * @return the URL for the relative file name or absolute URL + */ + protected URL resolveURL(String name) throws MalformedURLException { + File file = new File(name); + if ( file.exists() ) { + return file.toURL(); + } + return new URL( name ); + } + } 1.3 +7 -5 jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/DynamicTag.java Index: DynamicTag.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/DynamicTag.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- DynamicTag.java 25 Apr 2002 18:58:47 -0000 1.2 +++ DynamicTag.java 26 Apr 2002 11:28:55 -0000 1.3 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/DynamicTag.java,v 1.2 2002/04/25 18:58:47 jstrachan Exp $ - * $Revision: 1.2 $ - * $Date: 2002/04/25 18:58:47 $ + * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/DynamicTag.java,v 1.3 2002/04/26 11:28:55 jstrachan Exp $ + * $Revision: 1.3 $ + * $Date: 2002/04/26 11:28:55 $ * * ==================================================================== * @@ -57,7 +57,7 @@ * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * - * $Id: DynamicTag.java,v 1.2 2002/04/25 18:58:47 jstrachan Exp $ + * $Id: DynamicTag.java,v 1.3 2002/04/26 11:28:55 jstrachan Exp $ */ package org.apache.commons.jelly.tags.define; @@ -81,7 +81,7 @@ * as variables and will allow the template to invoke its instance body.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ */ public class DynamicTag extends TagSupport implements DynaTag { @@ -106,6 +106,8 @@ public void run(Context context, XMLOutput output) throws Exception { log.info( "Invoking dynamic tag with attributes: " + attributes ); + + attributes.put( "jelly.body", getBody() ); // create new context based on current attributes Context newContext = context.newContext( attributes ); 1.3 +20 -13 jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/InvokeBodyTag.java Index: InvokeBodyTag.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/InvokeBodyTag.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- InvokeBodyTag.java 25 Apr 2002 18:58:47 -0000 1.2 +++ InvokeBodyTag.java 26 Apr 2002 11:28:55 -0000 1.3 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/InvokeBodyTag.java,v 1.2 2002/04/25 18:58:47 jstrachan Exp $ - * $Revision: 1.2 $ - * $Date: 2002/04/25 18:58:47 $ + * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/tags/define/InvokeBodyTag.java,v 1.3 2002/04/26 11:28:55 jstrachan Exp $ + * $Revision: 1.3 $ + * $Date: 2002/04/26 11:28:55 $ * * ==================================================================== * @@ -57,12 +57,13 @@ * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * - * $Id: InvokeBodyTag.java,v 1.2 2002/04/25 18:58:47 jstrachan Exp $ + * $Id: InvokeBodyTag.java,v 1.3 2002/04/26 11:28:55 jstrachan Exp $ */ package org.apache.commons.jelly.tags.define; import org.apache.commons.jelly.Context; import org.apache.commons.jelly.JellyException; +import org.apache.commons.jelly.Script; import org.apache.commons.jelly.Tag; import org.apache.commons.jelly.TagSupport; import org.apache.commons.jelly.XMLOutput; @@ -77,7 +78,7 @@ * body.</p> * * @author <a href="mailto:[EMAIL PROTECTED]">James Strachan</a> - * @version $Revision: 1.2 $ + * @version $Revision: 1.3 $ */ public class InvokeBodyTag extends TagSupport { @@ -91,16 +92,22 @@ // Tag interface //------------------------------------------------------------------------- public void run(Context context, XMLOutput output) throws Exception { - - // #### note this mechanism does not work properly for arbitrarily - // #### nested dynamic tags. A better way is required. - Tag tag = findAncestorWithClass(this, DynamicTag.class); - if ( tag == null ) { - // throw new JellyException( "Cannot invoke body, no dynamic tag is defined in this block" ); - log.warn( "Cannot invoke body, no dynamic tag is defined in this block" ); + + // Try find find the body from the reserved 'jelly.body' variable + Script script = (Script) context.getVariable( "jelly.body" ); + if ( script != null ) { + script.run( context, output ); } else { - tag.getBody().run(context, output); + // note this mechanism does not work properly for arbitrarily + // nested dynamic tags. A better way is required. + Tag tag = findAncestorWithClass(this, DynamicTag.class); + if ( tag == null ) { + throw new JellyException( "Cannot invoke body, no dynamic tag is defined in this block" ); + } + else { + tag.getBody().run(context, output); + } } } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>