View Javadoc
1 /* 2 * $Header: /cvsroot/xwing/projects/xwing/src/java/org/apache/commons/jelly/JellyContext.java,v 1.1 2003/10/06 17:53:49 jshowlett Exp $ 3 * $Revision: 1.1 $ 4 * $Date: 2003/10/06 17:53:49 $ 5 * 6 * ==================================================================== 7 * 8 * The Apache Software License, Version 1.1 9 * 10 * Copyright (c) 2002 The Apache Software Foundation. All rights 11 * reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 25 * 3. The end-user documentation included with the redistribution, if 26 * any, must include the following acknowlegement: 27 * "This product includes software developed by the 28 * Apache Software Foundation (http://www.apache.org/)." 29 * Alternately, this acknowlegement may appear in the software itself, 30 * if and wherever such third-party acknowlegements normally appear. 31 * 32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software 33 * Foundation" must not be used to endorse or promote products derived 34 * from this software without prior written permission. For written 35 * permission, please contact apache@apache.org. 36 * 37 * 5. Products derived from this software may not be called "Apache" 38 * nor may "Apache" appear in their names without prior written 39 * permission of the Apache Group. 40 * 41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This software consists of voluntary contributions made by many 56 * individuals on behalf of the Apache Software Foundation. For more 57 * information on the Apache Software Foundation, please see 58 * <http://www.apache.org/>. 59 * 60 * $Id: JellyContext.java,v 1.1 2003/10/06 17:53:49 jshowlett Exp $ 61 */ 62 package org.apache.commons.jelly; 63 64 import java.io.File; 65 import java.io.InputStream; 66 import java.io.IOException; 67 import java.net.MalformedURLException; 68 import java.net.URL; 69 import java.util.Hashtable; 70 import java.util.Iterator; 71 import java.util.Map; 72 73 import org.apache.commons.jelly.parser.XMLParser; 74 import org.apache.commons.logging.Log; 75 import org.apache.commons.logging.LogFactory; 76 77 import org.xml.sax.SAXException; 78 79 /*** <p><code>JellyContext</code> represents the Jelly context.</p> 80 * 81 * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> 82 * @version $Revision: 1.1 $ 83 */ 84 public class JellyContext { 85 86 /*** The Log to which logging calls will be made. */ 87 private static Log log = LogFactory.getLog(JellyContext.class); 88 89 /*** The root URL context (where scripts are located from) */ 90 private URL rootURL; 91 92 /*** The current URL context (where relative scripts are located from) */ 93 private URL currentURL; 94 95 /*** Tag libraries found so far */ 96 private Map taglibs = new Hashtable(); 97 98 /*** synchronized access to the variables in scope */ 99 private Map variables = new Hashtable(); 100 101 /*** The parent context */ 102 private JellyContext parent; 103 104 /*** Default for inheritance of variables **/ 105 private static boolean DEFAULT_INHERIT = true; 106 107 /*** Do we inherit variables from parent context? */ 108 private boolean inherit = JellyContext.DEFAULT_INHERIT; 109 110 /*** Default for export of variables **/ 111 private static boolean DEFAULT_EXPORT = false; 112 113 /*** Do we export our variables to parent context? */ 114 private boolean export = JellyContext.DEFAULT_EXPORT; 115 116 /*** Should we export tag libraries to our parents context */ 117 private boolean exportLibraries = true; 118 119 /*** Should we cache Tag instances, per thread, to reduce object contruction overhead? */ 120 private boolean cacheTags = false; 121 122 /*** a Thread local cache of XMLParsers to avoid startup overhead of an XMLParser */ 123 private ThreadLocal parserPool = new ThreadLocal(); 124 125 /*** 126 * The class loader to use for instantiating application objects. 127 * If not specified, the context class loader, or the class loader 128 * used to load this class itself, is used, based on the value of the 129 * <code>useContextClassLoader</code> variable. 130 */ 131 protected ClassLoader classLoader; 132 133 /*** 134 * Do we want to use the Context ClassLoader when loading classes 135 * for instantiating new objects? Default is <code>false</code>. 136 */ 137 protected boolean useContextClassLoader = false; 138 139 140 public JellyContext() { 141 this.currentURL = rootURL; 142 init(); 143 } 144 145 public JellyContext(URL rootURL) { 146 this( rootURL, rootURL ); 147 } 148 149 public JellyContext(URL rootURL, URL currentURL) { 150 this.rootURL = rootURL; 151 this.currentURL = currentURL; 152 init(); 153 } 154 155 public JellyContext(JellyContext parent) { 156 this.parent = parent; 157 this.rootURL = parent.rootURL; 158 this.currentURL = parent.currentURL; 159 this.variables.put("parentScope", parent.variables); 160 this.cacheTags = parent.cacheTags; 161 init(); 162 } 163 164 public JellyContext(JellyContext parentJellyContext, URL currentURL) { 165 this(parentJellyContext); 166 this.currentURL = currentURL; 167 } 168 169 public JellyContext(JellyContext parentJellyContext, URL rootURL, URL currentURL) { 170 this(parentJellyContext, currentURL); 171 this.rootURL = rootURL; 172 } 173 174 private void init() { 175 variables.put("context", this); 176 try { 177 variables.put("systemScope", System.getProperties()); 178 } 179 catch (SecurityException e) { 180 // ignore security exceptions 181 } 182 } 183 184 /*** 185 * @return the parent context for this context 186 */ 187 public JellyContext getParent() { 188 return parent; 189 } 190 191 /*** 192 * @return the scope of the given name, such as the 'parent' scope. 193 * If Jelly is used in a Servlet situation then 'request', 'session' and 'application' are other names 194 * for scopes 195 */ 196 public JellyContext getScope(String name) { 197 if ( "parent".equals( name ) ) { 198 return getParent(); 199 } 200 return null; 201 } 202 203 /*** 204 * Finds the variable value of the given name in this context or in any other parent context. 205 * If this context does not contain the variable, then its parent is used and then its parent 206 * and so forth until the context with no parent is found. 207 * 208 * @return the value of the variable in this or one of its descendant contexts or null 209 * if the variable could not be found. 210 */ 211 public Object findVariable(String name) { 212 Object answer = variables.get(name); 213 if ( answer == null && parent != null ) { 214 answer = parent.findVariable(name); 215 } 216 // ### this is a hack - remove this when we have support for pluggable Scopes 217 if ( answer == null ) { 218 try { 219 answer = System.getProperty(name); 220 } 221 catch (SecurityException e) { 222 // ignore security exceptions 223 } 224 } 225 226 if (log.isDebugEnabled()) { 227 log.debug("findVariable: " + name + " value: " + answer ); 228 } 229 return answer; 230 } 231 232 233 /*** @return the value of the given variable name */ 234 public Object getVariable(String name) { 235 Object value = variables.get(name); 236 237 if ( value == null && isInherit() ) { 238 JellyContext parent = getParent(); 239 if (parent != null) { 240 value = parent.getVariable( name ); 241 } 242 } 243 244 return value; 245 } 246 247 /*** 248 * @return the value of the given variable name in the given variable scope 249 * @param name is the name of the variable 250 * @param scopeName is the optional scope name such as 'parent'. For servlet environments 251 * this could be 'application', 'session' or 'request'. 252 */ 253 public Object getVariable(String name, String scopeName) { 254 JellyContext scope = getScope(scopeName); 255 if ( scope != null ) { 256 return scope.getVariable(name); 257 } 258 return null; 259 } 260 261 262 263 /*** Sets the value of the given variable name */ 264 public void setVariable(String name, Object value) { 265 if ( isExport() ) { 266 getParent().setVariable( name, value ); 267 return; 268 } 269 if (value == null) { 270 variables.remove(name); 271 } 272 else { 273 variables.put(name, value); 274 } 275 } 276 277 /*** 278 * Sets the value of the given variable name in the given variable scope 279 * @param name is the name of the variable 280 * @param scopeName is the optional scope name such as 'parent'. For servlet environments 281 * this could be 'application', 'session' or 'request'. 282 * @param value is the value of the attribute 283 */ 284 public void setVariable(String name, String scopeName, Object value) { 285 JellyContext scope = getScope(scopeName); 286 if ( scope != null ) { 287 scope.setVariable(name, value); 288 } 289 } 290 291 /*** Removes the given variable */ 292 public void removeVariable(String name) { 293 variables.remove(name); 294 } 295 296 /*** 297 * Removes the given variable in the specified scope. 298 * 299 * @param name is the name of the variable 300 * @param scopeName is the optional scope name such as 'parent'. For servlet environments 301 * this could be 'application', 'session' or 'request'. 302 */ 303 public void removeVariable(String name, String scopeName) { 304 JellyContext scope = getScope(scopeName); 305 if ( scope != null ) { 306 scope.removeVariable(name); 307 } 308 } 309 310 /*** 311 * @return an Iterator over the current variable names in this 312 * context 313 */ 314 public Iterator getVariableNames() { 315 return variables.keySet().iterator(); 316 } 317 318 /*** 319 * @return the Map of variables in this scope 320 */ 321 public Map getVariables() { 322 return variables; 323 } 324 325 /*** 326 * Sets the Map of variables to use 327 */ 328 public void setVariables(Map variables) { 329 // I have seen this fail when the passed Map contains a key, value 330 // pair where the value is null 331 for (Iterator iter = variables.entrySet().iterator(); iter.hasNext();) { 332 Map.Entry element = (Map.Entry) iter.next(); 333 if (element.getValue() != null) { 334 this.variables.put(element.getKey(), element.getValue()); 335 } 336 } 337 //this.variables.putAll( variables ); 338 } 339 340 /*** 341 * A factory method to create a new child context of the 342 * current context. 343 */ 344 public JellyContext newJellyContext(Map newVariables) { 345 // XXXX: should allow this new context to 346 // XXXX: inherit parent contexts? 347 // XXXX: Or at least publish the parent scope 348 // XXXX: as a Map in this new variable scope? 349 newVariables.put("parentScope", variables); 350 JellyContext answer = createChildContext(); 351 answer.setVariables(newVariables); 352 return answer; 353 } 354 355 /*** 356 * A factory method to create a new child context of the 357 * current context. 358 */ 359 public JellyContext newJellyContext() { 360 return createChildContext(); 361 } 362 363 /*** Registers the given tag library against the given namespace URI. 364 * This should be called before the parser is used. 365 */ 366 public void registerTagLibrary(String namespaceURI, TagLibrary taglib) { 367 if (log.isDebugEnabled()) { 368 log.debug("Registering tag library to: " + namespaceURI + " taglib: " + taglib); 369 } 370 taglibs.put(namespaceURI, taglib); 371 372 if (isExportLibraries() && parent != null) { 373 parent.registerTagLibrary( namespaceURI, taglib ); 374 } 375 } 376 377 /*** Registers the given tag library class name against the given namespace URI. 378 * The class will be loaded via the given ClassLoader 379 * This should be called before the parser is used. 380 */ 381 public void registerTagLibrary( 382 String namespaceURI, 383 String className) { 384 385 if (log.isDebugEnabled()) { 386 log.debug("Registering tag library to: " + namespaceURI + " taglib: " + className); 387 } 388 taglibs.put(namespaceURI, className); 389 390 if (isExportLibraries() && parent != null) { 391 parent.registerTagLibrary( namespaceURI, className ); 392 } 393 } 394 395 public boolean isTagLibraryRegistered(String namespaceURI) { 396 boolean answer = taglibs.containsKey( namespaceURI ); 397 if (answer) { 398 return true; 399 } 400 else if ( parent != null ) { 401 return parent.isTagLibraryRegistered(namespaceURI); 402 } 403 else { 404 return false; 405 } 406 } 407 408 /*** 409 * @return the TagLibrary for the given namespace URI or null if one could not be found 410 */ 411 public TagLibrary getTagLibrary(String namespaceURI) { 412 413 // use my own mapping first, so that namespaceURIs can 414 // be redefined inside child contexts... 415 416 Object answer = taglibs.get(namespaceURI); 417 418 if ( answer == null && parent != null ) { 419 answer = parent.getTagLibrary( namespaceURI ); 420 } 421 422 if ( answer instanceof TagLibrary ) { 423 return (TagLibrary) answer; 424 } 425 else if ( answer instanceof String ) { 426 String className = (String) answer; 427 Class theClass = null; 428 try { 429 theClass = getClassLoader().loadClass(className); 430 } 431 catch (ClassNotFoundException e) { 432 log.error("Could not find the class: " + className, e); 433 } 434 if ( theClass != null ) { 435 try { 436 Object object = theClass.newInstance(); 437 if (object instanceof TagLibrary) { 438 taglibs.put(namespaceURI, object); 439 return (TagLibrary) object; 440 } 441 else { 442 log.error( 443 "The tag library object mapped to: " 444 + namespaceURI 445 + " is not a TagLibrary. Object = " 446 + object); 447 } 448 } 449 catch (Exception e) { 450 log.error( 451 "Could not instantiate instance of class: " + className + ". Reason: " + e, 452 e); 453 } 454 } 455 } 456 457 return null; 458 } 459 460 /*** 461 * Attempts to parse the script from the given uri using the 462 * {@link #getResource} method then returns the compiled script. 463 */ 464 public Script compileScript(String uri) throws JellyException { 465 XMLParser parser = getXMLParser(); 466 parser.setContext(this); 467 InputStream in = getResourceAsStream(uri); 468 if (in == null) { 469 throw new JellyException("Could not find Jelly script: " + uri); 470 } 471 Script script = null; 472 try { 473 script = parser.parse(in); 474 } catch (IOException e) { 475 throw new JellyException("Could not parse Jelly script",e); 476 } catch (SAXException e) { 477 throw new JellyException("Could not parse Jelly script",e); 478 } 479 480 return script.compile(); 481 } 482 483 /*** 484 * Attempts to parse the script from the given URL using the 485 * {@link #getResource} method then returns the compiled script. 486 */ 487 public Script compileScript(URL url) throws JellyException { 488 XMLParser parser = getXMLParser(); 489 parser.setContext(this); 490 491 Script script = null; 492 try { 493 script = parser.parse(url.toString()); 494 } catch (IOException e) { 495 throw new JellyException("Could not parse Jelly script",e); 496 } catch (SAXException e) { 497 throw new JellyException("Could not parse Jelly script",e); 498 } 499 500 return script.compile(); 501 } 502 503 /*** 504 * @return a thread pooled XMLParser to avoid the startup overhead 505 * of the XMLParser 506 */ 507 protected XMLParser getXMLParser() { 508 XMLParser parser = (XMLParser) parserPool.get(); 509 if (parser == null) { 510 parser = createXMLParser(); 511 parserPool.set(parser); 512 } 513 return parser; 514 } 515 516 /*** 517 * Factory method to allow JellyContext implementations to overload how an XMLParser 518 * is created - such as to overload what the default ExpressionFactory should be. 519 */ 520 protected XMLParser createXMLParser() { 521 return new XMLParser(); 522 } 523 524 /*** 525 * Parses the script from the given File then compiles it and runs it. 526 * 527 * @return the new child context that was used to run the script 528 */ 529 public JellyContext runScript(File file, XMLOutput output) throws JellyException { 530 try { 531 return runScript(file.toURL(), output, JellyContext.DEFAULT_EXPORT, 532 JellyContext.DEFAULT_INHERIT); 533 } catch (MalformedURLException e) { 534 throw new JellyException(e.toString()); 535 } 536 } 537 538 /*** 539 * Parses the script from the given URL then compiles it and runs it. 540 * 541 * @return the new child context that was used to run the script 542 */ 543 public JellyContext runScript(URL url, XMLOutput output) throws JellyException { 544 return runScript(url, output, JellyContext.DEFAULT_EXPORT, 545 JellyContext.DEFAULT_INHERIT); 546 } 547 548 /*** 549 * Parses the script from the given uri using the 550 * JellyContext.getResource() API then compiles it and runs it. 551 * 552 * @return the new child context that was used to run the script 553 */ 554 public JellyContext runScript(String uri, XMLOutput output) throws JellyException { 555 URL url = null; 556 try { 557 url = getResource(uri); 558 } catch (MalformedURLException e) { 559 throw new JellyException(e.toString()); 560 } 561 562 if (url == null) { 563 throw new JellyException("Could not find Jelly script: " + url); 564 } 565 return runScript(url, output, JellyContext.DEFAULT_EXPORT, 566 JellyContext.DEFAULT_INHERIT); 567 } 568 569 /*** 570 * Parses the script from the given uri using the 571 * JellyContext.getResource() API then compiles it and runs it. 572 * 573 * @return the new child context that was used to run the script 574 */ 575 public JellyContext runScript(String uri, XMLOutput output, 576 boolean export, boolean inherit) throws JellyException { 577 URL url = null; 578 try { 579 url = getResource(uri); 580 } catch (MalformedURLException e) { 581 throw new JellyException(e.toString()); 582 } 583 584 if (url == null) { 585 throw new JellyException("Could not find Jelly script: " + url); 586 } 587 588 return runScript(url, output, export, inherit); 589 } 590 591 /*** 592 * Parses the script from the given file then compiles it and runs it. 593 * 594 * @return the new child context that was used to run the script 595 */ 596 public JellyContext runScript(File file, XMLOutput output, 597 boolean export, boolean inherit) throws JellyException { 598 try { 599 return runScript(file.toURL(), output, export, inherit); 600 } catch (MalformedURLException e) { 601 throw new JellyException(e.toString()); 602 } 603 } 604 605 /*** 606 * Parses the script from the given URL then compiles it and runs it. 607 * 608 * @return the new child context that was used to run the script 609 */ 610 public JellyContext runScript(URL url, XMLOutput output, 611 boolean export, boolean inherit) throws JellyException { 612 Script script = compileScript(url); 613 614 URL newJellyContextURL = null; 615 try { 616 newJellyContextURL = getJellyContextURL(url); 617 } catch (MalformedURLException e) { 618 throw new JellyException(e.toString()); 619 } 620 621 JellyContext newJellyContext = newJellyContext(); 622 newJellyContext.setRootURL( newJellyContextURL ); 623 newJellyContext.setCurrentURL( newJellyContextURL ); 624 newJellyContext.setExport( export ); 625 newJellyContext.setInherit( inherit ); 626 627 if ( inherit ) { 628 // use the same variable scopes 629 newJellyContext.variables = this.variables; 630 } 631 632 if (log.isDebugEnabled() ) { 633 log.debug( "About to run script: " + url ); 634 log.debug( "root context URL: " + newJellyContext.rootURL ); 635 log.debug( "current context URL: " + newJellyContext.currentURL ); 636 } 637 638 script.run(newJellyContext, output); 639 640 return newJellyContext; 641 } 642 643 /*** 644 * Returns a URL for the given resource from the specified path. 645 * If the uri starts with "/" then the path is taken as relative to 646 * the current context root. 647 * If the uri is a well formed URL then it is used. 648 * If the uri is a file that exists and can be read then it is used. 649 * Otherwise the uri is interpreted as relative to the current context (the 650 * location of the current script). 651 */ 652 public URL getResource(String uri) throws MalformedURLException { 653 if (uri.startsWith("/")) { 654 // append this uri to the context root 655 return createRelativeURL(rootURL, uri.substring(1)); 656 } 657 else { 658 try { 659 return new URL(uri); 660 } 661 catch (MalformedURLException e) { 662 // lets try find a relative resource 663 try { 664 return createRelativeURL(currentURL, uri); 665 } catch (MalformedURLException e2) { 666 throw e; 667 } 668 } 669 } 670 } 671 672 /*** 673 * Attempts to open an InputStream to the given resource at the specified path. 674 * If the uri starts with "/" then the path is taken as relative to 675 * the current context root. If the uri is a well formed URL then it 676 * is used. Otherwise the uri is interpreted as relative to the current 677 * context (the location of the current script). 678 * 679 * @return null if this resource could not be loaded, otherwise the resources 680 * input stream is returned. 681 */ 682 public InputStream getResourceAsStream(String uri) { 683 try { 684 URL url = getResource(uri); 685 return url.openStream(); 686 } 687 catch (Exception e) { 688 if (log.isTraceEnabled()) { 689 log.trace( 690 "Caught exception attempting to open: " + uri + ". Exception: " + e, 691 e); 692 } 693 return null; 694 } 695 } 696 697 698 // Properties 699 //------------------------------------------------------------------------- 700 701 /*** 702 * @return the current root context URL from which all absolute resource URIs 703 * will be relative to. For example in a web application the root URL will 704 * map to the web directory which contains the WEB-INF directory. 705 */ 706 public URL getRootURL() { 707 return rootURL; 708 } 709 710 /*** 711 * Sets the current root context URL from which all absolute resource URIs 712 * will be relative to. For example in a web application the root URL will 713 * map to the web directory which contains the WEB-INF directory. 714 */ 715 public void setRootURL(URL rootURL) { 716 this.rootURL = rootURL; 717 } 718 719 720 /*** 721 * @return the current URL context of the current script that is executing. 722 * This URL context is used to deduce relative scripts when relative URIs are 723 * used in calls to {@link #getResource} to process relative scripts. 724 */ 725 public URL getCurrentURL() { 726 return currentURL; 727 } 728 729 /*** 730 * Sets the current URL context of the current script that is executing. 731 * This URL context is used to deduce relative scripts when relative URIs are 732 * used in calls to {@link #getResource} to process relative scripts. 733 */ 734 public void setCurrentURL(URL currentURL) { 735 this.currentURL = currentURL; 736 } 737 738 /*** 739 * Returns whether caching of Tag instances, per thread, is enabled. 740 * Caching Tags can boost performance, on some JVMs, by reducing the cost of 741 * object construction when running Jelly inside a multi-threaded application server 742 * such as a Servlet engine. 743 * 744 * @return whether caching of Tag instances is enabled. 745 */ 746 public boolean isCacheTags() { 747 return cacheTags; 748 } 749 750 /*** 751 * Sets whether caching of Tag instances, per thread, is enabled. 752 * Caching Tags can boost performance, on some JVMs, by reducing the cost of 753 * object construction when running Jelly inside a multi-threaded application server 754 * such as a Servlet engine. 755 * 756 * @param cacheTags Whether caching should be enabled or disabled. 757 */ 758 public void setCacheTags(boolean cacheTags) { 759 this.cacheTags = cacheTags; 760 } 761 762 /*** 763 * Returns whether we export tag libraries to our parents context 764 * @return boolean 765 */ 766 public boolean isExportLibraries() { 767 return exportLibraries; 768 } 769 770 /*** 771 * Sets whether we export tag libraries to our parents context 772 * @param exportLibraries The exportLibraries to set 773 */ 774 public void setExportLibraries(boolean exportLibraries) { 775 this.exportLibraries = exportLibraries; 776 } 777 778 779 /*** 780 * Sets whether we should export variable definitions to our parent context 781 */ 782 public void setExport(boolean export) { 783 this.export = export; 784 } 785 786 public boolean isExport() { 787 return this.export; 788 } 789 790 /*** 791 * Sets whether we should inherit variables from our parent context 792 */ 793 public void setInherit(boolean inherit) { 794 this.inherit = inherit; 795 } 796 797 public boolean isInherit() { 798 return this.inherit; 799 } 800 801 802 /*** 803 * Return the class loader to be used for instantiating application objects 804 * when required. This is determined based upon the following rules: 805 * <ul> 806 * <li>The class loader set by <code>setClassLoader()</code>, if any</li> 807 * <li>The thread context class loader, if it exists and the 808 * <code>useContextClassLoader</code> property is set to true</li> 809 * <li>The class loader used to load the XMLParser class itself. 810 * </ul> 811 */ 812 public ClassLoader getClassLoader() { 813 if (this.classLoader != null) { 814 return (this.classLoader); 815 } 816 if (this.useContextClassLoader) { 817 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 818 if (classLoader != null) { 819 return (classLoader); 820 } 821 } 822 return (this.getClass().getClassLoader()); 823 } 824 825 /*** 826 * Set the class loader to be used for instantiating application objects 827 * when required. 828 * 829 * @param classLoader The new class loader to use, or <code>null</code> 830 * to revert to the standard rules 831 */ 832 public void setClassLoader(ClassLoader classLoader) { 833 this.classLoader = classLoader; 834 } 835 836 /*** 837 * Return the boolean as to whether the context classloader should be used. 838 */ 839 public boolean getUseContextClassLoader() { 840 return useContextClassLoader; 841 } 842 843 /*** 844 * Determine whether to use the Context ClassLoader (the one found by 845 * calling <code>Thread.currentThread().getContextClassLoader()</code>) 846 * to resolve/load classes. If not 847 * using Context ClassLoader, then the class-loading defaults to 848 * using the calling-class' ClassLoader. 849 * 850 * @param use determines whether to use JellyContext ClassLoader. 851 */ 852 public void setUseContextClassLoader(boolean use) { 853 useContextClassLoader = use; 854 } 855 856 857 // Implementation methods 858 //------------------------------------------------------------------------- 859 /*** 860 * @return a new relative URL from the given root and with the addition of the 861 * extra relative URI 862 * 863 * @param rootURL is the root context from which the relative URI will be applied 864 * @param relativeURI is the relative URI (without a leading "/") 865 * @throws MalformedURLException if the URL is invalid. 866 */ 867 protected URL createRelativeURL(URL rootURL, String relativeURI) 868 throws MalformedURLException { 869 if (rootURL == null) { 870 File file = new File(System.getProperty("user.dir")); 871 rootURL = file.toURL(); 872 } 873 String urlText = rootURL.toString() + relativeURI; 874 if ( log.isDebugEnabled() ) { 875 log.debug("Attempting to open url: " + urlText); 876 } 877 return new URL(urlText); 878 } 879 880 /*** 881 * Strips off the name of a script to create a new context URL 882 */ 883 protected URL getJellyContextURL(URL url) throws MalformedURLException { 884 String text = url.toString(); 885 int idx = text.lastIndexOf('/'); 886 text = text.substring(0, idx + 1); 887 return new URL(text); 888 } 889 890 /*** 891 * Factory method to create a new child of this context 892 */ 893 protected JellyContext createChildContext() { 894 return new JellyContext(this); 895 } 896 897 /*** 898 * Change the parent context to the one provided 899 * @param context the new parent context 900 */ 901 protected void setParent(JellyContext context) 902 { 903 parent = context; 904 this.variables.put("parentScope", parent.variables); 905 // need to re-export tag libraries to the new parent 906 if (isExportLibraries() && parent != null) { 907 for (Iterator keys = taglibs.keySet().iterator(); keys.hasNext();) 908 { 909 String namespaceURI = (String) keys.next(); 910 Object tagLibOrClassName = taglibs.get(namespaceURI); 911 if (tagLibOrClassName instanceof TagLibrary) 912 { 913 parent.registerTagLibrary( namespaceURI, (TagLibrary) tagLibOrClassName ); 914 } 915 else 916 { 917 parent.registerTagLibrary( namespaceURI, (String) tagLibOrClassName ); 918 } 919 } 920 } 921 922 } 923 924 }

This page was automatically generated by Maven