KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jelly > JellyContext


1 /*
2  * Copyright 2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.jelly;
17
18 import java.io.File JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStream JavaDoc;
21 import java.net.MalformedURLException JavaDoc;
22 import java.net.URL JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.HashMap JavaDoc;
27
28 import org.apache.commons.jelly.parser.XMLParser;
29 import org.apache.commons.jelly.util.ClassLoaderUtils;
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import org.xml.sax.InputSource JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35
36 /**
37   * <p><code>JellyContext</code> represents the Jelly context.</p>
38   *
39   * @author <a HREF="mailto:jstrachan@apache.org">James Strachan</a>
40   * @version $Revision: 227285 $
41   */

42 public class JellyContext {
43
44     /** The Log to which logging calls will be made. */
45     private static final Log log = LogFactory.getLog(JellyContext.class);
46
47     /** Default for inheritance of variables **/
48     private static final boolean DEFAULT_INHERIT = true;
49
50     /** Default for export of variables **/
51     private static final boolean DEFAULT_EXPORT = false;
52
53     /** String used to denote a script can't be parsed */
54     private static final String JavaDoc BAD_PARSE = "Could not parse Jelly script";
55
56     /**
57      * The class loader to use for instantiating application objects.
58      * If not specified, the context class loader, or the class loader
59      * used to load this class itself, is used, based on the value of the
60      * <code>useContextClassLoader</code> variable.
61      */

62     protected ClassLoader JavaDoc classLoader;
63
64     /**
65      * Do we want to use the Context ClassLoader when loading classes
66      * for instantiating new objects? Default is <code>false</code>.
67      */

68     protected boolean useContextClassLoader = false;
69
70     /** The root URL context (where scripts are located from) */
71     private URL JavaDoc rootURL;
72
73     /** The current URL context (where relative scripts are located from) */
74     private URL JavaDoc currentURL;
75
76     /** Tag libraries found so far */
77     private Map JavaDoc taglibs = new Hashtable JavaDoc();
78
79     /** synchronized access to the variables in scope */
80     private Map JavaDoc variables = new HashMap JavaDoc();
81
82     /** The parent context */
83     private JellyContext parent;
84
85     /** Do we inherit variables from parent context? */
86     private boolean inherit = JellyContext.DEFAULT_INHERIT;
87
88     /** Do we export our variables to parent context? */
89     private boolean export = JellyContext.DEFAULT_EXPORT;
90
91     /** Should we export tag libraries to our parents context */
92     private boolean exportLibraries = true;
93
94     /** Should we cache Tag instances, per thread, to reduce object contruction overhead? */
95     private boolean cacheTags = false;
96
97     /**
98      * Create a new context with the currentURL set to the rootURL
99      */

100     public JellyContext() {
101         this.currentURL = rootURL;
102         init();
103     }
104
105     /**
106      * Create a new context with the given rootURL
107      * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'
108      */

109     public JellyContext(URL JavaDoc rootURL) {
110         this( rootURL, rootURL );
111     }
112
113     /**
114      * Create a new context with the given rootURL and currentURL
115      * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'
116      * @param currentURL the root URL used in resolving relative resources
117      */

118     public JellyContext(URL JavaDoc rootURL, URL JavaDoc currentURL) {
119         this.rootURL = rootURL;
120         this.currentURL = currentURL;
121         init();
122     }
123
124
125     /**
126      * Create a new context with the given parent context.
127      * The parent's rootURL and currentURL are set on the child, and the parent's variables are
128      * available in the child context under the name <code>parentScope</code>.
129      *
130      * @param parent the parent context for the newly created context.
131      */

132     public JellyContext(JellyContext parent) {
133         this.parent = parent;
134         this.rootURL = parent.rootURL;
135         this.currentURL = parent.currentURL;
136         this.variables.put("parentScope", parent.variables);
137         this.cacheTags = parent.cacheTags;
138         init();
139     }
140
141     /**
142      * Create a new context with the given parent context.
143      * The parent's rootURL are set on the child, and the parent's variables are
144      * available in the child context under the name <code>parentScope</code>.
145      *
146      * @param parentJellyContext the parent context for the newly created context.
147      * @param currentURL the root URL used in resolving relative resources
148      */

149     public JellyContext(JellyContext parentJellyContext, URL JavaDoc currentURL) {
150         this(parentJellyContext);
151         this.currentURL = currentURL;
152     }
153
154     /**
155      * Create a new context with the given parent context.
156      * The parent's variables are available in the child context under the name <code>parentScope</code>.
157      *
158      * @param parentJellyContext the parent context for the newly created context.
159      * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'
160      * @param currentURL the root URL used in resolving relative resources
161      */

162     public JellyContext(JellyContext parentJellyContext, URL JavaDoc rootURL, URL JavaDoc currentURL) {
163         this(parentJellyContext, currentURL);
164         this.rootURL = rootURL;
165     }
166
167     /**
168      * Initialize the context.
169      * This includes adding the context to itself under the name <code>context</code> and
170      * making the System Properties available as <code>systemScope</code>
171      */

172     private void init() {
173         variables.put("context",this);
174         try {
175             variables.put("systemScope", System.getProperties() );
176         } catch (SecurityException JavaDoc e) {
177             log.debug("security exception accessing system properties", e);
178         }
179     }
180
181     /**
182      * @return the parent context for this context
183      */

184     public JellyContext getParent() {
185         return parent;
186     }
187
188     /**
189      * @return the scope of the given name, such as the 'parent' scope.
190      * If Jelly is used in a Servlet situation then 'request', 'session' and 'application' are other names
191      * for scopes
192      */

193     public JellyContext getScope(String JavaDoc name) {
194         if ( "parent".equals( name ) ) {
195             return getParent();
196         }
197         return null;
198     }
199
200     /**
201      * Finds the variable value of the given name in this context or in any other parent context.
202      * If this context does not contain the variable, then its parent is used and then its parent
203      * and so forth until the context with no parent is found.
204      *
205      * @return the value of the variable in this or one of its descendant contexts or null
206      * if the variable could not be found.
207      */

208     public Object JavaDoc findVariable(String JavaDoc name) {
209         Object JavaDoc answer = variables.get(name);
210         boolean definedHere = answer != null || variables.containsKey(name);
211
212         if (definedHere) return answer;
213
214         if ( answer == null && parent != null ) {
215             answer = parent.findVariable(name);
216         }
217         // ### this is a hack - remove this when we have support for pluggable Scopes
218
if ( answer == null ) {
219             answer = getSystemProperty(name);
220         }
221
222         if (log.isDebugEnabled()) {
223             log.debug("findVariable: " + name + " value: " + answer );
224         }
225         return answer;
226     }
227
228
229     /** @return the value of the given variable name */
230     public Object JavaDoc getVariable(String JavaDoc name) {
231         Object JavaDoc value = variables.get(name);
232         boolean definedHere = value != null || variables.containsKey(name);
233
234         if (definedHere) return value;
235
236         if ( value == null && isInherit() ) {
237             JellyContext parentContext = getParent();
238             if (parentContext != null) {
239                 value = parentContext.getVariable( name );
240             }
241         }
242
243         // ### this is a hack - remove this when we have support for pluggable Scopes
244
if ( value == null ) {
245             value = getSystemProperty(name);
246         }
247
248         return value;
249     }
250
251     /**
252      * Get a system property and handle security exceptions
253      * @param name the name of the property to retrieve
254      * @return the value of the property, or null if a SecurityException occurs
255      */

256     private Object JavaDoc getSystemProperty(String JavaDoc name) {
257         try {
258             return System.getProperty(name);
259         }
260         catch (SecurityException JavaDoc e) {
261             log.debug("security exception accessing system properties", e);
262         }
263         return null;
264     }
265
266     /**
267      * @return the value of the given variable name in the given variable scope
268      * @param name is the name of the variable
269      * @param scopeName is the optional scope name such as 'parent'. For servlet environments
270      * this could be 'application', 'session' or 'request'.
271      */

272     public Object JavaDoc getVariable(String JavaDoc name, String JavaDoc scopeName) {
273         JellyContext scope = getScope(scopeName);
274         if ( scope != null ) {
275             return scope.getVariable(name);
276         }
277         return null;
278     }
279
280
281
282     /** Sets the value of the named variable */
283     public void setVariable(String JavaDoc name, Object JavaDoc value) {
284         if ( isExport() ) {
285             getParent().setVariable( name, value );
286             return;
287         }
288         variables.put(name, value);
289     }
290
291     /**
292      * Sets the value of the given variable name in the given variable scope
293      * @param name is the name of the variable
294      * @param scopeName is the optional scope name such as 'parent'. For servlet environments
295      * this could be 'application', 'session' or 'request'.
296      * @param value is the value of the attribute
297      */

298     public void setVariable(String JavaDoc name, String JavaDoc scopeName, Object JavaDoc value) {
299         JellyContext scope = getScope(scopeName);
300         if ( scope != null ) {
301             scope.setVariable(name, value);
302         }
303     }
304
305     /** Removes the given variable */
306     public void removeVariable(String JavaDoc name) {
307         variables.remove(name);
308     }
309
310     /**
311      * Removes the given variable in the specified scope.
312      *
313      * @param name is the name of the variable
314      * @param scopeName is the optional scope name such as 'parent'. For servlet environments
315      * this could be 'application', 'session' or 'request'.
316      */

317     public void removeVariable(String JavaDoc name, String JavaDoc scopeName) {
318         JellyContext scope = getScope(scopeName);
319         if ( scope != null ) {
320             scope.removeVariable(name);
321         }
322     }
323
324     /**
325      * @return an Iterator over the current variable names in this
326      * context
327      */

328     public Iterator JavaDoc getVariableNames() {
329         return variables.keySet().iterator();
330     }
331
332     /**
333      * @return the Map of variables in this scope
334      */

335     public Map JavaDoc getVariables() {
336         return variables;
337     }
338
339     /**
340      * Sets the Map of variables to use
341      */

342     public void setVariables(Map JavaDoc variables) {
343         // I have seen this fail when the passed Map contains a key, value
344
// pair where the value is null
345
for (Iterator JavaDoc iter = variables.entrySet().iterator(); iter.hasNext();) {
346             Map.Entry JavaDoc element = (Map.Entry JavaDoc) iter.next();
347             if (element.getValue() != null) {
348                 this.variables.put(element.getKey(), element.getValue());
349             }
350         }
351         //this.variables.putAll( variables );
352
}
353
354     /**
355      * A factory method to create a new child context of the
356      * current context.
357      */

358     public JellyContext newJellyContext(Map JavaDoc newVariables) {
359         // XXXX: should allow this new context to
360
// XXXX: inherit parent contexts?
361
// XXXX: Or at least publish the parent scope
362
// XXXX: as a Map in this new variable scope?
363
newVariables.put("parentScope", variables);
364         JellyContext answer = createChildContext();
365         answer.setVariables(newVariables);
366         return answer;
367     }
368
369     /**
370      * A factory method to create a new child context of the
371      * current context.
372      */

373     public JellyContext newJellyContext() {
374         return createChildContext();
375     }
376     
377     /** Clears variables set by Tags.
378      * @see #clearVariables()
379       */

380     public void clear() {
381         clearVariables();
382     }
383     
384     /** Clears variables set by Tags (variables set while running a Jelly script)
385      * @see #clear()
386      */

387     protected void clearVariables() {
388         variables.clear();
389     }
390     
391     /** Registers the given tag library against the given namespace URI.
392      * This should be called before the parser is used.
393      */

394     public void registerTagLibrary(String JavaDoc namespaceURI, TagLibrary taglib) {
395         if (log.isDebugEnabled()) {
396             log.debug("Registering tag library to: " + namespaceURI + " taglib: " + taglib);
397         }
398         taglibs.put(namespaceURI, taglib);
399
400         if (isExportLibraries() && parent != null) {
401             parent.registerTagLibrary( namespaceURI, taglib );
402         }
403     }
404
405     /** Registers the given tag library class name against the given namespace URI.
406      * The class will be loaded via the given ClassLoader
407      * This should be called before the parser is used.
408      */

409     public void registerTagLibrary(
410         String JavaDoc namespaceURI,
411         String JavaDoc className) {
412
413         if (log.isDebugEnabled()) {
414             log.debug("Registering tag library to: " + namespaceURI + " taglib: " + className);
415         }
416         taglibs.put(namespaceURI, className);
417
418         if (isExportLibraries() && parent != null) {
419             parent.registerTagLibrary( namespaceURI, className );
420         }
421     }
422
423     public boolean isTagLibraryRegistered(String JavaDoc namespaceURI) {
424         boolean answer = taglibs.containsKey( namespaceURI );
425         if (answer) {
426             return true;
427         }
428         else if ( parent != null ) {
429             return parent.isTagLibraryRegistered(namespaceURI);
430         }
431         else {
432             return false;
433         }
434     }
435
436     /**
437      * @return the TagLibrary for the given namespace URI or null if one could not be found
438      */

439     public TagLibrary getTagLibrary(String JavaDoc namespaceURI) {
440
441         // use my own mapping first, so that namespaceURIs can
442
// be redefined inside child contexts...
443

444         Object JavaDoc answer = taglibs.get(namespaceURI);
445
446         if ( answer == null && parent != null ) {
447             answer = parent.getTagLibrary( namespaceURI );
448         }
449
450         if ( answer instanceof TagLibrary ) {
451             return (TagLibrary) answer;
452         }
453         else if ( answer instanceof String JavaDoc ) {
454             String JavaDoc className = (String JavaDoc) answer;
455             Class JavaDoc theClass = null;
456             try {
457                 theClass = getClassLoader().loadClass(className);
458             }
459             catch (ClassNotFoundException JavaDoc e) {
460                 log.error("Could not find the class: " + className, e);
461             }
462             if ( theClass != null ) {
463                 try {
464                     Object JavaDoc object = theClass.newInstance();
465                     if (object instanceof TagLibrary) {
466                         taglibs.put(namespaceURI, object);
467                         return (TagLibrary) object;
468                     }
469                     else {
470                         log.error(
471                             "The tag library object mapped to: "
472                                 + namespaceURI
473                                 + " is not a TagLibrary. Object = "
474                                 + object);
475                     }
476                 }
477                 catch (Exception JavaDoc e) {
478                     log.error(
479                         "Could not instantiate instance of class: " + className + ". Reason: " + e,
480                         e);
481                 }
482             }
483         }
484
485         return null;
486     }
487
488     /**
489      * Attempts to parse the script from the given uri using the
490      * {@link #getResource} method then returns the compiled script.
491      */

492     public Script compileScript(String JavaDoc uri) throws JellyException {
493         XMLParser parser = getXMLParser();
494         parser.setContext(this);
495         InputStream JavaDoc in = getResourceAsStream(uri);
496         if (in == null) {
497             throw new JellyException("Could not find Jelly script: " + uri);
498         }
499         Script script = null;
500         try {
501             script = parser.parse(in);
502         } catch (IOException JavaDoc e) {
503             throw new JellyException(JellyContext.BAD_PARSE, e);
504         } catch (SAXException JavaDoc e) {
505             throw new JellyException(JellyContext.BAD_PARSE, e);
506         }
507
508         return script.compile();
509     }
510
511     /**
512      * Attempts to parse the script from the given URL using the
513      * {@link #getResource} method then returns the compiled script.
514      */

515     public Script compileScript(URL JavaDoc url) throws JellyException {
516         XMLParser parser = getXMLParser();
517         parser.setContext(this);
518
519         Script script = null;
520         try {
521             script = parser.parse(url.toString());
522         } catch (IOException JavaDoc e) {
523             throw new JellyException(JellyContext.BAD_PARSE, e);
524         } catch (SAXException JavaDoc e) {
525             throw new JellyException(JellyContext.BAD_PARSE, e);
526         }
527
528         return script.compile();
529     }
530
531     /**
532      * Attempts to parse the script from the given InputSource using the
533      * {@link #getResource} method then returns the compiled script.
534      */

535     public Script compileScript(InputSource JavaDoc source) throws JellyException {
536         XMLParser parser = getXMLParser();
537         parser.setContext(this);
538
539         Script script = null;
540         try {
541             script = parser.parse(source);
542         } catch (IOException JavaDoc e) {
543             throw new JellyException(JellyContext.BAD_PARSE, e);
544         } catch (SAXException JavaDoc e) {
545             throw new JellyException(JellyContext.BAD_PARSE, e);
546         }
547
548         return script.compile();
549     }
550
551     /**
552      * @return a thread pooled XMLParser to avoid the startup overhead
553      * of the XMLParser
554      */

555     protected XMLParser getXMLParser() {
556         XMLParser parser = createXMLParser();
557         return parser;
558     }
559
560     /**
561      * Factory method to allow JellyContext implementations to overload how an XMLParser
562      * is created - such as to overload what the default ExpressionFactory should be.
563      */

564     protected XMLParser createXMLParser() {
565         return new XMLParser();
566     }
567
568     /**
569      * Parses the script from the given File then compiles it and runs it.
570      *
571      * @return the new child context that was used to run the script
572      */

573     public JellyContext runScript(File JavaDoc file, XMLOutput output) throws JellyException {
574         try {
575             return runScript(file.toURL(), output, JellyContext.DEFAULT_EXPORT,
576                 JellyContext.DEFAULT_INHERIT);
577         } catch (MalformedURLException JavaDoc e) {
578             throw new JellyException(e.toString());
579         }
580     }
581
582     /**
583      * Parses the script from the given URL then compiles it and runs it.
584      *
585      * @return the new child context that was used to run the script
586      */

587     public JellyContext runScript(URL JavaDoc url, XMLOutput output) throws JellyException {
588         return runScript(url, output, JellyContext.DEFAULT_EXPORT,
589             JellyContext.DEFAULT_INHERIT);
590     }
591
592     /**
593      * Parses the script from the given InputSource then compiles it and runs it.
594      *
595      * @return the new child context that was used to run the script
596      */

597     public JellyContext runScript(InputSource JavaDoc source, XMLOutput output) throws JellyException {
598         return runScript(source, output, JellyContext.DEFAULT_EXPORT,
599             JellyContext.DEFAULT_INHERIT);
600     }
601
602     /**
603      * Parses the script from the given uri using the
604      * JellyContext.getResource() API then compiles it and runs it.
605      *
606      * @return the new child context that was used to run the script
607      */

608     public JellyContext runScript(String JavaDoc uri, XMLOutput output) throws JellyException {
609         URL JavaDoc url = null;
610         try {
611             url = getResource(uri);
612         } catch (MalformedURLException JavaDoc e) {
613             throw new JellyException(e.toString());
614         }
615
616         if (url == null) {
617             throw new JellyException("Could not find Jelly script: " + url);
618         }
619         return runScript(url, output, JellyContext.DEFAULT_EXPORT,
620             JellyContext.DEFAULT_INHERIT);
621     }
622
623     /**
624      * Parses the script from the given uri using the
625      * JellyContext.getResource() API then compiles it and runs it.
626      *
627      * @return the new child context that was used to run the script
628      */

629     public JellyContext runScript(String JavaDoc uri, XMLOutput output,
630                           boolean export, boolean inherit) throws JellyException {
631         URL JavaDoc url = null;
632         try {
633             url = getResource(uri);
634         } catch (MalformedURLException JavaDoc e) {
635             throw new JellyException(e.toString());
636         }
637
638         if (url == null) {
639             throw new JellyException("Could not find Jelly script: " + url);
640         }
641
642         return runScript(url, output, export, inherit);
643     }
644
645     /**
646      * Parses the script from the given file then compiles it and runs it.
647      *
648      * @return the new child context that was used to run the script
649      */

650     public JellyContext runScript(File JavaDoc file, XMLOutput output,
651                           boolean export, boolean inherit) throws JellyException {
652         try {
653             return runScript(file.toURL(), output, export, inherit);
654         } catch (MalformedURLException JavaDoc e) {
655             throw new JellyException(e.toString());
656         }
657     }
658
659     /**
660      * Parses the script from the given URL then compiles it and runs it.
661      *
662      * @return the new child context that was used to run the script
663      */

664     public JellyContext runScript(URL JavaDoc url, XMLOutput output,
665                           boolean export, boolean inherit) throws JellyException {
666         return runScript(new InputSource JavaDoc(url.toString()), output, export, inherit);
667     }
668
669     /**
670      * Parses the script from the given InputSource then compiles it and runs it.
671      *
672      * @return the new child context that was used to run the script
673      */

674     public JellyContext runScript(InputSource JavaDoc source, XMLOutput output,
675                           boolean export, boolean inherit) throws JellyException {
676         Script script = compileScript(source);
677
678         URL JavaDoc newJellyContextURL = null;
679         try {
680             newJellyContextURL = getJellyContextURL(source);
681         } catch (MalformedURLException JavaDoc e) {
682             throw new JellyException(e.toString());
683         }
684
685         JellyContext newJellyContext = newJellyContext();
686         newJellyContext.setRootURL( newJellyContextURL );
687         newJellyContext.setCurrentURL( newJellyContextURL );
688         newJellyContext.setExport( export );
689         newJellyContext.setInherit( inherit );
690
691         if ( inherit ) {
692             // use the same variable scopes
693
newJellyContext.variables = this.variables;
694         }
695
696         if (log.isDebugEnabled() ) {
697             log.debug( "About to run script: " + source.getSystemId() );
698             log.debug( "root context URL: " + newJellyContext.rootURL );
699             log.debug( "current context URL: " + newJellyContext.currentURL );
700         }
701
702         script.run(newJellyContext, output);
703
704         return newJellyContext;
705     }
706
707     /**
708      * Returns a URL for the given resource from the specified path.
709      * If the uri starts with "/" then the path is taken as relative to
710      * the current context root.
711      * If the uri is a well formed URL then it is used.
712      * If the uri is a file that exists and can be read then it is used.
713      * Otherwise the uri is interpreted as relative to the current context (the
714      * location of the current script).
715      */

716     public URL JavaDoc getResource(String JavaDoc uri) throws MalformedURLException JavaDoc {
717         if (uri.startsWith("/")) {
718             // append this uri to the context root
719
return createRelativeURL(rootURL, uri.substring(1));
720         }
721         else {
722             try {
723                 return new URL JavaDoc(uri);
724             }
725             catch (MalformedURLException JavaDoc e) {
726                 // lets try find a relative resource
727
try {
728                     return createRelativeURL(currentURL, uri);
729                 } catch (MalformedURLException JavaDoc e2) {
730                     throw e;
731                 }
732             }
733         }
734     }
735
736     /**
737      * Attempts to open an InputStream to the given resource at the specified path.
738      * If the uri starts with "/" then the path is taken as relative to
739      * the current context root. If the uri is a well formed URL then it
740      * is used. Otherwise the uri is interpreted as relative to the current
741      * context (the location of the current script).
742      *
743      * @return null if this resource could not be loaded, otherwise the resources
744      * input stream is returned.
745      */

746     public InputStream JavaDoc getResourceAsStream(String JavaDoc uri) {
747         try {
748             URL JavaDoc url = getResource(uri);
749             return url.openStream();
750         }
751         catch (Exception JavaDoc e) {
752             if (log.isTraceEnabled()) {
753                 log.trace(
754                     "Caught exception attempting to open: " + uri + ". Exception: " + e,
755                     e);
756             }
757             return null;
758         }
759     }
760
761
762     // Properties
763
//-------------------------------------------------------------------------
764

765     /**
766      * @return the current root context URL from which all absolute resource URIs
767      * will be relative to. For example in a web application the root URL will
768      * map to the web directory which contains the WEB-INF directory.
769      */

770     public URL JavaDoc getRootURL() {
771         return rootURL;
772     }
773
774     /**
775      * Sets the current root context URL from which all absolute resource URIs
776      * will be relative to. For example in a web application the root URL will
777      * map to the web directory which contains the WEB-INF directory.
778      */

779     public void setRootURL(URL JavaDoc rootURL) {
780         this.rootURL = rootURL;
781     }
782
783
784     /**
785      * @return the current URL context of the current script that is executing.
786      * This URL context is used to deduce relative scripts when relative URIs are
787      * used in calls to {@link #getResource} to process relative scripts.
788      */

789     public URL JavaDoc getCurrentURL() {
790         return currentURL;
791     }
792
793     /**
794      * Sets the current URL context of the current script that is executing.
795      * This URL context is used to deduce relative scripts when relative URIs are
796      * used in calls to {@link #getResource} to process relative scripts.
797      */

798     public void setCurrentURL(URL JavaDoc currentURL) {
799         this.currentURL = currentURL;
800     }
801
802     /**
803      * Returns whether caching of Tag instances, per thread, is enabled.
804      * Caching Tags can boost performance, on some JVMs, by reducing the cost of
805      * object construction when running Jelly inside a multi-threaded application server
806      * such as a Servlet engine.
807      *
808      * @return whether caching of Tag instances is enabled.
809      */

810     public boolean isCacheTags() {
811         return cacheTags;
812     }
813
814     /**
815      * Sets whether caching of Tag instances, per thread, is enabled.
816      * Caching Tags can boost performance, on some JVMs, by reducing the cost of
817      * object construction when running Jelly inside a multi-threaded application server
818      * such as a Servlet engine.
819      *
820      * @param cacheTags Whether caching should be enabled or disabled.
821      */

822     public void setCacheTags(boolean cacheTags) {
823         this.cacheTags = cacheTags;
824     }
825
826     /**
827      * Returns whether we export tag libraries to our parents context
828      * @return boolean
829      */

830     public boolean isExportLibraries() {
831         return exportLibraries;
832     }
833
834     /**
835      * Sets whether we export tag libraries to our parents context
836      * @param exportLibraries The exportLibraries to set
837      */

838     public void setExportLibraries(boolean exportLibraries) {
839         this.exportLibraries = exportLibraries;
840     }
841
842
843     /**
844      * Sets whether we should export variable definitions to our parent context
845      */

846     public void setExport(boolean export) {
847         this.export = export;
848     }
849
850     /**
851      * @return whether we should export variable definitions to our parent context
852      */

853     public boolean isExport() {
854         return this.export;
855     }
856
857     /**
858      * Sets whether we should inherit variables from our parent context
859      */

860     public void setInherit(boolean inherit) {
861         this.inherit = inherit;
862     }
863
864     /**
865      * @return whether we should inherit variables from our parent context
866      */

867     public boolean isInherit() {
868         return this.inherit;
869     }
870
871
872     /**
873      * Return the class loader to be used for instantiating application objects
874      * when required. This is determined based upon the following rules:
875      * <ul>
876      * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
877      * <li>The thread context class loader, if it exists and the
878      * <code>useContextClassLoader</code> property is set to true</li>
879      * <li>The class loader used to load the XMLParser class itself.
880      * </ul>
881      */

882     public ClassLoader JavaDoc getClassLoader() {
883         return ClassLoaderUtils.getClassLoader(classLoader, useContextClassLoader, getClass());
884     }
885
886     /**
887      * Set the class loader to be used for instantiating application objects
888      * when required.
889      *
890      * @param classLoader The new class loader to use, or <code>null</code>
891      * to revert to the standard rules
892      */

893     public void setClassLoader(ClassLoader JavaDoc classLoader) {
894         this.classLoader = classLoader;
895     }
896
897     /**
898      * Return the boolean as to whether the context classloader should be used.
899      */

900     public boolean getUseContextClassLoader() {
901         return useContextClassLoader;
902     }
903
904     /**
905      * Determine whether to use the Context ClassLoader (the one found by
906      * calling <code>Thread.currentThread().getContextClassLoader()</code>)
907      * to resolve/load classes. If not
908      * using Context ClassLoader, then the class-loading defaults to
909      * using the calling-class' ClassLoader.
910      *
911      * @param use determines whether to use JellyContext ClassLoader.
912      */

913     public void setUseContextClassLoader(boolean use) {
914         useContextClassLoader = use;
915     }
916
917
918     // Implementation methods
919
//-------------------------------------------------------------------------
920
/**
921      * @return a new relative URL from the given root and with the addition of the
922      * extra relative URI
923      *
924      * @param rootURL is the root context from which the relative URI will be applied
925      * @param relativeURI is the relative URI (without a leading "/")
926      * @throws MalformedURLException if the URL is invalid.
927      */

928     protected URL JavaDoc createRelativeURL(URL JavaDoc rootURL, String JavaDoc relativeURI)
929         throws MalformedURLException JavaDoc {
930         URL JavaDoc url = rootURL;
931         if (url == null) {
932             File JavaDoc file = new File JavaDoc(System.getProperty("user.dir"));
933             url = file.toURL();
934         }
935         String JavaDoc urlText = url.toString() + relativeURI;
936         if ( log.isDebugEnabled() ) {
937             log.debug("Attempting to open url: " + urlText);
938         }
939         return new URL JavaDoc(urlText);
940     }
941
942     /**
943      * Strips off the name of a script to create a new context URL
944      */

945     protected URL JavaDoc getJellyContextURL(URL JavaDoc url) throws MalformedURLException JavaDoc {
946         String JavaDoc text = url.toString();
947         int idx = text.lastIndexOf('/');
948         text = text.substring(0, idx + 1);
949         return new URL JavaDoc(text);
950     }
951
952     /**
953      * Strips off the name of a script to create a new context URL
954      */

955     protected URL JavaDoc getJellyContextURL(InputSource JavaDoc source) throws MalformedURLException JavaDoc {
956         String JavaDoc text = source.getSystemId();
957         if (text != null) {
958             int idx = text.lastIndexOf('/');
959             text = text.substring(0, idx + 1);
960             return new URL JavaDoc(text);
961         } else {
962             return null;
963         }
964         
965     }
966
967     /**
968      * Factory method to create a new child of this context
969      */

970     protected JellyContext createChildContext() {
971         return new JellyContext(this);
972     }
973
974     /**
975      * Change the parent context to the one provided
976      * @param context the new parent context
977      */

978     protected void setParent(JellyContext context)
979     {
980         parent = context;
981         this.variables.put("parentScope", parent.variables);
982         // need to re-export tag libraries to the new parent
983
if (isExportLibraries() && parent != null) {
984             for (Iterator JavaDoc keys = taglibs.keySet().iterator(); keys.hasNext();)
985             {
986                 String JavaDoc namespaceURI = (String JavaDoc) keys.next();
987                 Object JavaDoc tagLibOrClassName = taglibs.get(namespaceURI);
988                 if (tagLibOrClassName instanceof TagLibrary)
989                 {
990                     parent.registerTagLibrary( namespaceURI, (TagLibrary) tagLibOrClassName );
991                 }
992                 else
993                 {
994                     parent.registerTagLibrary( namespaceURI, (String JavaDoc) tagLibOrClassName );
995                 }
996             }
997         }
998
999     }
1000
1001}
1002
Popular Tags