| /* |
| * $Header: /home/cvs/jakarta-commons-sandbox/jelly/src/java/org/apache/commons/jelly/JellyContext.java,v 1.10 2002/04/26 12:20:12 jstrachan Exp $ |
| * $Revision: 1.10 $ |
| * $Date: 2002/04/26 12:20:12 $ |
| * |
| * ==================================================================== |
| * |
| * The Apache Software License, Version 1.1 |
| * |
| * Copyright (c) 2002 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, if |
| * any, must include the following acknowlegement: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowlegement may appear in the software itself, |
| * if and wherever such third-party acknowlegements normally appear. |
| * |
| * 4. The names "The Jakarta Project", "Commons", and "Apache Software |
| * Foundation" must not be used to endorse or promote products derived |
| * from this software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache" |
| * nor may "Apache" appear in their names without prior written |
| * permission of the Apache Group. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| * |
| * $Id: JellyContext.java,v 1.10 2002/04/26 12:20:12 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; |
| |
| /** <p><code>JellyContext</code> represents the Jelly context.</p> |
| * |
| * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
| * @version $Revision: 1.10 $ |
| */ |
| public class JellyContext { |
| |
| /** The Log to which logging calls will be made. */ |
| private static Log log = LogFactory.getLog(JellyContext.class); |
| |
| /** The root URL context (where scripts are located from) */ |
| private URL rootURL; |
| |
| /** The current URL context (where relative scripts are located from) */ |
| private URL currentURL; |
| |
| /** Tag libraries found so far */ |
| private Map taglibs = new Hashtable(); |
| |
| /** synchronized access to the variables in scope */ |
| private Map variables = new Hashtable(); |
| |
| /** The parent context */ |
| private JellyContext parent; |
| |
| /** Default for inheritance of variables **/ |
| private static boolean DEFAULT_INHERIT = true; |
| |
| /** Do we inherit variables from parent context? */ |
| private boolean inherit = JellyContext.DEFAULT_INHERIT; |
| |
| /** Default for export of variables **/ |
| private static boolean DEFAULT_EXPORT = false; |
| |
| /** Do we export our variables to parent context? */ |
| private boolean export = JellyContext.DEFAULT_EXPORT; |
| |
| /** Should we export tag libraries to our parents context */ |
| private boolean exportLibraries = true; |
| |
| /** Should we cache Tag instances, per thread, to reduce object contruction overhead? */ |
| private boolean cacheTags = false; |
| |
| /** a Thread local cache of XMLParsers to avoid startup overhead of an XMLParser */ |
| private ThreadLocal parserPool = new ThreadLocal(); |
| |
| /** |
| * The class loader to use for instantiating application objects. |
| * If not specified, the context class loader, or the class loader |
| * used to load this class itself, is used, based on the value of the |
| * <code>useContextClassLoader</code> variable. |
| */ |
| protected ClassLoader classLoader; |
| |
| /** |
| * Do we want to use the Context ClassLoader when loading classes |
| * for instantiating new objects? Default is <code>false</code>. |
| */ |
| protected boolean useContextClassLoader = false; |
| |
| |
| public JellyContext() { |
| this.currentURL = rootURL; |
| init(); |
| } |
| |
| public JellyContext(URL rootURL) { |
| this( rootURL, rootURL ); |
| } |
| |
| public JellyContext(URL rootURL, URL currentURL) { |
| this.rootURL = rootURL; |
| this.currentURL = currentURL; |
| init(); |
| } |
| |
| public JellyContext(JellyContext parent) { |
| this.parent = parent; |
| this.rootURL = parent.rootURL; |
| this.currentURL = parent.currentURL; |
| this.variables.put("parentScope", parent.variables); |
| this.cacheTags = parent.cacheTags; |
| init(); |
| } |
| |
| public JellyContext(JellyContext parentJellyContext, URL currentURL) { |
| this(parentJellyContext); |
| this.currentURL = currentURL; |
| } |
| |
| public JellyContext(JellyContext parentJellyContext, URL rootURL, URL currentURL) { |
| this(parentJellyContext, currentURL); |
| this.rootURL = rootURL; |
| } |
| |
| private void init() { |
| variables.put("context", this); |
| variables.put("systemScope", System.getProperties()); |
| } |
| |
| /** |
| * @return the parent context for this context |
| */ |
| public JellyContext getParent() { |
| return parent; |
| } |
| |
| /** |
| * @return the scope of the given name, such as the 'parent' scope. |
| * If Jelly is used in a Servlet situation then 'request', 'session' and 'application' are other names |
| * for scopes |
| */ |
| public JellyContext getScope(String name) { |
| if ( "parent".equals( name ) ) { |
| return getParent(); |
| } |
| return null; |
| } |
| |
| /** |
| * Finds the variable value of the given name in this context or in any other parent context. |
| * If this context does not contain the variable, then its parent is used and then its parent |
| * and so forth until the context with no parent is found. |
| * |
| * @return the value of the variable in this or one of its descendant contexts or null |
| * if the variable could not be found. |
| */ |
| public Object findVariable(String name) { |
| Object answer = variables.get(name); |
| if ( answer == null && parent != null ) { |
| answer = parent.findVariable(name); |
| } |
| // ### this is a hack - remove this when we have support for pluggable Scopes |
| if ( answer == null ) { |
| try { |
| answer = System.getProperty(name); |
| } |
| catch (Throwable t) { |
| // ignore security exceptions |
| } |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("findVariable: " + name + " value: " + answer ); |
| } |
| return answer; |
| } |
| |
| |
| /** @return the value of the given variable name */ |
| public Object getVariable(String name) { |
| Object value = variables.get(name); |
| |
| if ( value == null && isInherit() ) { |
| JellyContext parent = getParent(); |
| if (parent != null) { |
| value = parent.findVariable( name ); |
| } |
| } |
| |
| return value; |
| } |
| |
| /** |
| * @return the value of the given variable name in the given variable scope |
| * @param name is the name of the variable |
| * @param scopeName is the optional scope name such as 'parent'. For servlet environments |
| * this could be 'application', 'session' or 'request'. |
| */ |
| public Object getVariable(String name, String scopeName) { |
| JellyContext scope = getScope(scopeName); |
| if ( scope != null ) { |
| return scope.getVariable(name); |
| } |
| return null; |
| } |
| |
| |
| |
| /** Sets the value of the given variable name */ |
| public void setVariable(String name, Object value) { |
| if ( isExport() ) { |
| getParent().setVariable( name, value ); |
| return; |
| } |
| if (value == null) { |
| variables.remove(name); |
| } |
| else { |
| variables.put(name, value); |
| } |
| } |
| |
| /** |
| * Sets the value of the given variable name in the given variable scope |
| * @param name is the name of the variable |
| * @param scopeName is the optional scope name such as 'parent'. For servlet environments |
| * this could be 'application', 'session' or 'request'. |
| * @param value is the value of the attribute |
| */ |
| public void setVariable(String name, String scopeName, Object value) { |
| JellyContext scope = getScope(scopeName); |
| if ( scope != null ) { |
| scope.setVariable(name, value); |
| } |
| } |
| |
| /** Removes the given variable */ |
| public void removeVariable(String name) { |
| variables.remove(name); |
| } |
| |
| /** |
| * Removes the given variable in the specified scope. |
| * |
| * @param name is the name of the variable |
| * @param scopeName is the optional scope name such as 'parent'. For servlet environments |
| * this could be 'application', 'session' or 'request'. |
| * @param value is the value of the attribute |
| */ |
| public void removeVariable(String name, String scopeName) { |
| JellyContext scope = getScope(scopeName); |
| if ( scope != null ) { |
| scope.removeVariable(name); |
| } |
| } |
| |
| /** |
| * @return an Iterator over the current variable names in this |
| * context |
| */ |
| public Iterator getVariableNames() { |
| return variables.keySet().iterator(); |
| } |
| |
| /** |
| * @return the Map of variables in this scope |
| */ |
| public Map getVariables() { |
| return variables; |
| } |
| |
| /** |
| * Sets the Map of variables to use |
| */ |
| |
| public void setVariables(Map variables) { |
| this.variables = variables; |
| } |
| |
| /** |
| * A factory method to create a new child context of the |
| * current context. |
| */ |
| public JellyContext newJellyContext(Map newVariables) { |
| // XXXX: should allow this new context to |
| // XXXX: inherit parent contexts? |
| // XXXX: Or at least publish the parent scope |
| // XXXX: as a Map in this new variable scope? |
| newVariables.put("parentScope", variables); |
| JellyContext answer = createChildContext(); |
| answer.setVariables(newVariables); |
| return answer; |
| } |
| |
| /** |
| * A factory method to create a new child context of the |
| * current context. |
| */ |
| public JellyContext newJellyContext() { |
| return createChildContext(); |
| } |
| |
| /** Registers the given tag library against the given namespace URI. |
| * This should be called before the parser is used. |
| */ |
| public void registerTagLibrary(String namespaceURI, TagLibrary taglib) { |
| if (log.isDebugEnabled()) { |
| log.debug("Registering tag library to: " + namespaceURI + " taglib: " + taglib); |
| } |
| taglibs.put(namespaceURI, taglib); |
| |
| if (isExportLibraries() && parent != null) { |
| parent.registerTagLibrary( namespaceURI, taglib ); |
| } |
| |
| if (isExportLibraries() && parent != null) { |
| parent.registerTagLibrary( namespaceURI, taglib ); |
| } |
| } |
| |
| /** Registers the given tag library class name against the given namespace URI. |
| * The class will be loaded via the given ClassLoader |
| * This should be called before the parser is used. |
| */ |
| public void registerTagLibrary( |
| String namespaceURI, |
| String className) { |
| |
| if (log.isDebugEnabled()) { |
| log.debug("Registering tag library to: " + namespaceURI + " taglib: " + className); |
| } |
| taglibs.put(namespaceURI, className); |
| |
| if (isExportLibraries() && parent != null) { |
| parent.registerTagLibrary( namespaceURI, className ); |
| } |
| } |
| |
| public boolean isTagLibraryRegistered(String namespaceURI) { |
| boolean answer = taglibs.containsKey( namespaceURI ); |
| if (answer) { |
| return true; |
| } |
| else if ( parent != null ) { |
| return parent.isTagLibraryRegistered(namespaceURI); |
| } |
| else { |
| return false; |
| } |
| } |
| |
| /** |
| * @return the TagLibrary for the given namespace URI or null if one could not be found |
| */ |
| public TagLibrary getTagLibrary(String namespaceURI) { |
| |
| // use my own mapping first, so that namespaceURIs can |
| // be redefined inside child contexts... |
| |
| Object answer = taglibs.get(namespaceURI); |
| |
| if ( answer == null && parent != null ) { |
| answer = parent.getTagLibrary( namespaceURI ); |
| } |
| |
| if ( answer instanceof TagLibrary ) { |
| return (TagLibrary) answer; |
| } |
| else if ( answer instanceof String ) { |
| String className = (String) answer; |
| Class theClass = null; |
| try { |
| theClass = getClassLoader().loadClass(className); |
| } |
| catch (ClassNotFoundException e) { |
| log.error("Could not find the class: " + className, e); |
| } |
| if ( theClass != null ) { |
| try { |
| Object object = theClass.newInstance(); |
| if (object instanceof TagLibrary) { |
| taglibs.put(namespaceURI, object); |
| return (TagLibrary) object; |
| } |
| else { |
| log.error( |
| "The tag library object mapped to: " |
| + namespaceURI |
| + " is not a TagLibrary. Object = " |
| + object); |
| } |
| } |
| catch (Exception e) { |
| log.error( |
| "Could not instantiate instance of class: " + className + ". Reason: " + e, |
| e); |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * 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); |
| InputStream in = getResourceAsStream(uri); |
| if (in == null) { |
| throw new JellyException("Could not find Jelly script: " + uri); |
| } |
| Script script = parser.parse(in); |
| return script.compile(); |
| } |
| |
| /** |
| * Attempts to parse the script from the given URL using the |
| * {@link #getResource} method then returns the compiled script. |
| */ |
| public Script compileScript(URL url) throws Exception { |
| XMLParser parser = getXMLParser(); |
| parser.setContext(this); |
| Script script = parser.parse(url.toString()); |
| return script.compile(); |
| } |
| |
| /** |
| * @return a thread pooled XMLParser to avoid the startup overhead |
| * of the XMLParser |
| */ |
| protected XMLParser getXMLParser() { |
| XMLParser parser = (XMLParser) parserPool.get(); |
| if (parser == null) { |
| parser = new XMLParser(); |
| parserPool.set(parser); |
| } |
| return parser; |
| } |
| |
| /** |
| * Parses the script from the given File then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(File file, XMLOutput output) throws Exception { |
| return runScript(file.toURL(), output, JellyContext.DEFAULT_EXPORT, |
| JellyContext.DEFAULT_INHERIT); |
| } |
| |
| /** |
| * Parses the script from the given URL then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(URL url, XMLOutput output) throws Exception { |
| return runScript(url, output, JellyContext.DEFAULT_EXPORT, |
| JellyContext.DEFAULT_INHERIT); |
| } |
| |
| /** |
| * Parses the script from the given uri using the |
| * JellyContext.getResource() API then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(String uri, XMLOutput output) throws Exception { |
| URL url = getResource(uri); |
| if (url == null) { |
| throw new JellyException("Could not find Jelly script: " + url); |
| } |
| return runScript(url, output, JellyContext.DEFAULT_EXPORT, |
| JellyContext.DEFAULT_INHERIT); |
| } |
| |
| /** |
| * Parses the script from the given uri using the |
| * JellyContext.getResource() API then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(String uri, XMLOutput output, |
| boolean export, boolean inherit) throws Exception { |
| URL url = getResource(uri); |
| if (url == null) { |
| throw new JellyException("Could not find Jelly script: " + url); |
| } |
| |
| return runScript(url, output, export, inherit); |
| } |
| |
| /** |
| * Parses the script from the given file then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(File file, XMLOutput output, |
| boolean export, boolean inherit) throws Exception { |
| return runScript(file.toURL(), output, export, inherit); |
| } |
| |
| /** |
| * Parses the script from the given URL then compiles it and runs it. |
| * |
| * @return the new child context that was used to run the script |
| */ |
| public JellyContext runScript(URL url, XMLOutput output, |
| boolean export, boolean inherit) throws Exception { |
| Script script = compileScript(url); |
| |
| URL newJellyContextURL = getJellyContextURL(url); |
| |
| JellyContext newJellyContext = new JellyContext(this, newJellyContextURL); |
| newJellyContext.setExport( export ); |
| newJellyContext.setInherit( inherit ); |
| |
| if ( inherit ) { |
| // use the same variable scopes |
| newJellyContext.variables = this.variables; |
| } |
| |
| if (log.isDebugEnabled() ) { |
| log.debug( "About to run script: " + url ); |
| log.debug( "root context URL: " + newJellyContext.rootURL ); |
| log.debug( "current context URL: " + newJellyContext.currentURL ); |
| } |
| |
| script.run(newJellyContext, output); |
| |
| return newJellyContext; |
| } |
| |
| /** |
| * 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. |
| * If the uri is a file that exists and can be read 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(rootURL, uri.substring(1)); |
| } |
| else { |
| try { |
| return new URL(uri); |
| } |
| catch (MalformedURLException e) { |
| // lets try find a relative resource |
| try { |
| return createRelativeURL(currentURL, 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; |
| } |
| } |
| |
| |
| // Properties |
| //------------------------------------------------------------------------- |
| |
| /** |
| * @return the current root context URL from which all absolute resource URIs |
| * will be relative to. For example in a web application the root URL will |
| * map to the web directory which contains the WEB-INF directory. |
| */ |
| public URL getRootURL() { |
| return rootURL; |
| } |
| |
| /** |
| * Sets the current root context URL from which all absolute resource URIs |
| * will be relative to. For example in a web application the root URL will |
| * map to the web directory which contains the WEB-INF directory. |
| */ |
| public void setRootURL(URL rootURL) { |
| this.rootURL = rootURL; |
| } |
| |
| |
| /** |
| * @return the current URL context of the current script that is executing. |
| * This URL context is used to deduce relative scripts when relative URIs are |
| * used in calls to {@link #getResource} to process relative scripts. |
| */ |
| public URL getCurrentURL() { |
| return currentURL; |
| } |
| |
| /** |
| * Sets the current URL context of the current script that is executing. |
| * This URL context is used to deduce relative scripts when relative URIs are |
| * used in calls to {@link #getResource} to process relative scripts. |
| */ |
| public void setCurrentURL(URL currentURL) { |
| this.currentURL = currentURL; |
| } |
| |
| /** |
| * Returns whether caching of Tag instances, per thread, is enabled. |
| * Caching Tags can boost performance, on some JVMs, by reducing the cost of |
| * object construction when running Jelly inside a multi-threaded application server |
| * such as a Servlet engine. |
| * |
| * @return whether caching of Tag instances is enabled. |
| */ |
| public boolean isCacheTags() { |
| return cacheTags; |
| } |
| |
| /** |
| * Sets whether caching of Tag instances, per thread, is enabled. |
| * Caching Tags can boost performance, on some JVMs, by reducing the cost of |
| * object construction when running Jelly inside a multi-threaded application server |
| * such as a Servlet engine. |
| * |
| * @param cacheTags Whether caching should be enabled or disabled. |
| */ |
| public void setCacheTags(boolean cacheTags) { |
| this.cacheTags = cacheTags; |
| } |
| |
| /** |
| * Returns whether we export tag libraries to our parents context |
| * @return boolean |
| */ |
| public boolean isExportLibraries() { |
| return exportLibraries; |
| } |
| |
| /** |
| * Sets whether we export tag libraries to our parents context |
| * @param exportLibraries The exportLibraries to set |
| */ |
| public void setExportLibraries(boolean exportLibraries) { |
| this.exportLibraries = exportLibraries; |
| } |
| |
| |
| /** |
| * Sets whether we should export variable definitions to our parent context |
| */ |
| public void setExport(boolean export) { |
| this.export = export; |
| } |
| |
| public boolean isExport() { |
| return this.export; |
| } |
| |
| /** |
| * Sets whether we should inherit variables from our parent context |
| */ |
| public void setInherit(boolean inherit) { |
| this.inherit = inherit; |
| } |
| |
| public boolean isInherit() { |
| return this.inherit; |
| } |
| |
| |
| /** |
| * Return the class loader to be used for instantiating application objects |
| * when required. This is determined based upon the following rules: |
| * <ul> |
| * <li>The class loader set by <code>setClassLoader()</code>, if any</li> |
| * <li>The thread context class loader, if it exists and the |
| * <code>useContextClassLoader</code> property is set to true</li> |
| * <li>The class loader used to load the XMLParser class itself. |
| * </ul> |
| */ |
| public ClassLoader getClassLoader() { |
| if (this.classLoader != null) { |
| return (this.classLoader); |
| } |
| if (this.useContextClassLoader) { |
| ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); |
| if (classLoader != null) { |
| return (classLoader); |
| } |
| } |
| return (this.getClass().getClassLoader()); |
| } |
| |
| /** |
| * Set the class loader to be used for instantiating application objects |
| * when required. |
| * |
| * @param classLoader The new class loader to use, or <code>null</code> |
| * to revert to the standard rules |
| */ |
| public void setClassLoader(ClassLoader classLoader) { |
| this.classLoader = classLoader; |
| } |
| |
| /** |
| * Return the boolean as to whether the context classloader should be used. |
| */ |
| public boolean getUseContextClassLoader() { |
| return useContextClassLoader; |
| } |
| |
| /** |
| * Determine whether to use the Context ClassLoader (the one found by |
| * calling <code>Thread.currentThread().getContextClassLoader()</code>) |
| * to resolve/load classes. If not |
| * using Context ClassLoader, then the class-loading defaults to |
| * using the calling-class' ClassLoader. |
| * |
| * @param boolean determines whether to use JellyContext ClassLoader. |
| */ |
| public void setUseContextClassLoader(boolean use) { |
| useContextClassLoader = use; |
| } |
| |
| |
| // 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) { |
| File file = new File(System.getProperty("user.dir")); |
| rootURL = file.toURL(); |
| } |
| String urlText = rootURL.toString() + relativeURI; |
| if ( log.isDebugEnabled() ) { |
| log.debug("Attempting to open url: " + urlText); |
| } |
| return new URL(urlText); |
| } |
| |
| /** |
| * Strips off the name of a script to create a new context URL |
| */ |
| protected URL getJellyContextURL(URL url) throws MalformedURLException { |
| String text = url.toString(); |
| int idx = text.lastIndexOf('/'); |
| text = text.substring(0, idx + 1); |
| return new URL(text); |
| } |
| |
| /** |
| * Factory method to create a new child of this context |
| */ |
| protected JellyContext createChildContext() { |
| return new JellyContext(this); |
| } |
| |
| } |