Clover coverage report - Code Coverage for tapestry release 4.0-beta-9
Coverage timestamp: Sat Oct 1 2005 08:36:20 EDT
file stats: LOC: 830   Methods: 29
NCLOC: 432   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
PageLoader.java 88% 96% 100% 94.9%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry.pageload;
 16   
 17    import java.util.ArrayList;
 18    import java.util.Iterator;
 19    import java.util.List;
 20    import java.util.Locale;
 21   
 22    import org.apache.commons.logging.Log;
 23    import org.apache.hivemind.ApplicationRuntimeException;
 24    import org.apache.hivemind.ClassResolver;
 25    import org.apache.hivemind.HiveMind;
 26    import org.apache.hivemind.Location;
 27    import org.apache.hivemind.Resource;
 28    import org.apache.hivemind.service.ThreadLocale;
 29    import org.apache.hivemind.util.ContextResource;
 30    import org.apache.tapestry.AbstractComponent;
 31    import org.apache.tapestry.BaseComponent;
 32    import org.apache.tapestry.IAsset;
 33    import org.apache.tapestry.IBinding;
 34    import org.apache.tapestry.IComponent;
 35    import org.apache.tapestry.IEngine;
 36    import org.apache.tapestry.INamespace;
 37    import org.apache.tapestry.IPage;
 38    import org.apache.tapestry.IRequestCycle;
 39    import org.apache.tapestry.ITemplateComponent;
 40    import org.apache.tapestry.asset.AssetSource;
 41    import org.apache.tapestry.binding.BindingConstants;
 42    import org.apache.tapestry.binding.BindingSource;
 43    import org.apache.tapestry.binding.ExpressionBinding;
 44    import org.apache.tapestry.binding.ListenerBinding;
 45    import org.apache.tapestry.coerce.ValueConverter;
 46    import org.apache.tapestry.engine.IPageLoader;
 47    import org.apache.tapestry.event.ChangeObserver;
 48    import org.apache.tapestry.resolver.ComponentSpecificationResolver;
 49    import org.apache.tapestry.services.BSFManagerFactory;
 50    import org.apache.tapestry.services.ComponentConstructor;
 51    import org.apache.tapestry.services.ComponentConstructorFactory;
 52    import org.apache.tapestry.services.ComponentTemplateLoader;
 53    import org.apache.tapestry.spec.BindingType;
 54    import org.apache.tapestry.spec.ContainedComponent;
 55    import org.apache.tapestry.spec.IAssetSpecification;
 56    import org.apache.tapestry.spec.IBindingSpecification;
 57    import org.apache.tapestry.spec.IComponentSpecification;
 58    import org.apache.tapestry.spec.IContainedComponent;
 59    import org.apache.tapestry.spec.IListenerBindingSpecification;
 60    import org.apache.tapestry.spec.IParameterSpecification;
 61    import org.apache.tapestry.web.WebContextResource;
 62   
 63    /**
 64    * Runs the process of building the component hierarchy for an entire page.
 65    * <p>
 66    * This implementation is not threadsafe, therefore the pooled service model must be used.
 67    *
 68    * @author Howard Lewis Ship
 69    */
 70   
 71    public class PageLoader implements IPageLoader
 72    {
 73    private Log _log;
 74   
 75    /** @since 4.0 */
 76   
 77    private ComponentSpecificationResolver _componentResolver;
 78   
 79    /** @since 4.0 */
 80   
 81    private String _defaultScriptLanguage;
 82   
 83    /** @since 4.0 */
 84   
 85    private BindingSource _bindingSource;
 86   
 87    /** @since 4.0 */
 88   
 89    private ComponentTemplateLoader _componentTemplateLoader;
 90   
 91    /** @since 4.0 */
 92   
 93    private BSFManagerFactory _managerFactory;
 94   
 95    private List _inheritedBindingQueue = new ArrayList();
 96   
 97    /** @since 4.0 */
 98    private IComponentVisitor _establishDefaultParameterValuesVisitor;
 99   
 100    private ComponentTreeWalker _establishDefaultParameterValuesWalker;
 101   
 102    private ComponentTreeWalker _verifyRequiredParametersWalker;
 103   
 104    /** @since 4.0 */
 105   
 106    private ComponentConstructorFactory _componentConstructorFactory;
 107   
 108    /** @since 4.0 */
 109   
 110    private ValueConverter _valueConverter;
 111   
 112    /** @since 4.0 */
 113   
 114    private AssetSource _assetSource;
 115   
 116    /**
 117    * Used to find the correct Java component class for a page.
 118    *
 119    * @since 4.0
 120    */
 121   
 122    private ComponentClassProvider _pageClassProvider;
 123   
 124    /**
 125    * Used to find the correct Java component class for a component (a similar process to resolving
 126    * a page, but with slightly differen steps and defaults).
 127    *
 128    * @since 4.0
 129    */
 130   
 131    private ComponentClassProvider _componentClassProvider;
 132   
 133    /**
 134    * Tracks the current locale into which pages are loaded.
 135    *
 136    * @since 4.0
 137    */
 138   
 139    private ThreadLocale _threadLocale;
 140   
 141    /**
 142    * The locale of the application, which is also the locale of the page being loaded.
 143    */
 144   
 145    private Locale _locale;
 146   
 147    /**
 148    * Number of components instantiated, excluding the page itself.
 149    */
 150   
 151    private int _count;
 152   
 153    /**
 154    * The recursion depth. A page with no components is zero. A component on a page is one.
 155    */
 156   
 157    private int _depth;
 158   
 159    /**
 160    * The maximum depth reached while building the page.
 161    */
 162   
 163    private int _maxDepth;
 164   
 165    /** @since 4.0 */
 166   
 167    private ClassResolver _classResolver;
 168   
 169  41 public void initializeService()
 170    {
 171   
 172    // Create the mechanisms for walking the component tree when it is
 173    // complete
 174  41 IComponentVisitor verifyRequiredParametersVisitor = new VerifyRequiredParametersVisitor();
 175   
 176  41 _verifyRequiredParametersWalker = new ComponentTreeWalker(new IComponentVisitor[]
 177    { verifyRequiredParametersVisitor });
 178   
 179  41 _establishDefaultParameterValuesWalker = new ComponentTreeWalker(new IComponentVisitor[]
 180    { _establishDefaultParameterValuesVisitor });
 181    }
 182   
 183    /**
 184    * Binds properties of the component as defined by the container's specification.
 185    * <p>
 186    * This implementation is very simple, we will need a lot more sanity checking and eror checking
 187    * in the final version.
 188    *
 189    * @param container
 190    * The containing component. For a dynamic binding ({@link ExpressionBinding}) the
 191    * property name is evaluated with the container as the root.
 192    * @param component
 193    * The contained component being bound.
 194    * @param spec
 195    * The specification of the contained component.
 196    * @param contained
 197    * The contained component specification (from the container's
 198    * {@link IComponentSpecification}).
 199    */
 200   
 201  378 void bind(IComponent container, IComponent component, IContainedComponent contained)
 202    {
 203  378 IComponentSpecification spec = component.getSpecification();
 204  378 boolean formalOnly = !spec.getAllowInformalParameters();
 205   
 206  378 if (contained.getInheritInformalParameters())
 207    {
 208  3 if (formalOnly)
 209  1 throw new ApplicationRuntimeException(PageloadMessages
 210    .inheritInformalInvalidComponentFormalOnly(component), component, contained
 211    .getLocation(), null);
 212   
 213  2 IComponentSpecification containerSpec = container.getSpecification();
 214   
 215  2 if (!containerSpec.getAllowInformalParameters())
 216  1 throw new ApplicationRuntimeException(PageloadMessages
 217    .inheritInformalInvalidContainerFormalOnly(container, component),
 218    component, contained.getLocation(), null);
 219   
 220  1 IQueuedInheritedBinding queued = new QueuedInheritInformalBindings(component);
 221  1 _inheritedBindingQueue.add(queued);
 222    }
 223   
 224  376 Iterator i = contained.getBindingNames().iterator();
 225   
 226  376 while (i.hasNext())
 227    {
 228  509 String name = (String) i.next();
 229   
 230  509 IParameterSpecification pspec = spec.getParameter(name);
 231   
 232  509 boolean isFormal = pspec != null;
 233   
 234  509 String parameterName = isFormal ? pspec.getParameterName() : name;
 235   
 236  509 IBindingSpecification bspec = contained.getBinding(name);
 237   
 238    // If not allowing informal parameters, check that each binding
 239    // matches
 240    // a formal parameter.
 241   
 242  509 if (formalOnly && !isFormal)
 243  0 throw new ApplicationRuntimeException(PageloadMessages.formalParametersOnly(
 244    component,
 245    name), component, bspec.getLocation(), null);
 246   
 247    // If an informal parameter that conflicts with a reserved name,
 248    // then skip it.
 249   
 250  509 if (!isFormal && spec.isReservedParameterName(name))
 251  0 continue;
 252   
 253  509 if (isFormal)
 254    {
 255  487 if (!name.equals(parameterName))
 256    {
 257  1 _log.warn(PageloadMessages.usedParameterAlias(
 258    contained,
 259    name,
 260    parameterName,
 261    bspec.getLocation()));
 262    }
 263  486 else if (pspec.isDeprecated())
 264  1 _log.warn(PageloadMessages.deprecatedParameter(
 265    name,
 266    bspec.getLocation(),
 267    contained.getType()));
 268    }
 269   
 270    // The type determines how to interpret the value:
 271    // As a simple static String
 272    // As a nested property name (relative to the component)
 273    // As the name of a binding inherited from the containing component.
 274    // As the name of a public field
 275    // As a script for a listener
 276   
 277  509 BindingType type = bspec.getType();
 278   
 279    // For inherited bindings, defer until later. This gives components
 280    // a chance to setup bindings from static values and expressions in
 281    // the template. The order of operations is tricky, template bindings
 282    // come later. Note that this is a hold over from the Tapestry 3.0 DTD
 283    // and will some day no longer be supported.
 284   
 285  509 if (type == BindingType.INHERITED)
 286    {
 287  1 QueuedInheritedBinding queued = new QueuedInheritedBinding(component, bspec
 288    .getValue(), parameterName);
 289  1 _inheritedBindingQueue.add(queued);
 290  1 continue;
 291    }
 292   
 293  508 if (type == BindingType.LISTENER)
 294    {
 295  3 constructListenerBinding(
 296    component,
 297    parameterName,
 298    (IListenerBindingSpecification) bspec);
 299  3 continue;
 300    }
 301   
 302  505 String description = PageloadMessages.parameterName(name);
 303   
 304  505 IBinding binding = convert(container, description, BindingConstants.OGNL_PREFIX, bspec);
 305   
 306  505 addBindingToComponent(component, parameterName, binding);
 307    }
 308    }
 309   
 310    /**
 311    * Adds a binding to the component, checking to see if there's a name conflict (an existing
 312    * binding for the same parameter ... possibly because parameter names can be aliased).
 313    *
 314    * @param component
 315    * to which the binding should be added
 316    * @param parameterName
 317    * the name of the parameter to bind, which should be a true name, not an alias
 318    * @param binding
 319    * the binding to add
 320    * @throws ApplicationRuntimeException
 321    * if a binding already exists
 322    * @since 4.0
 323    */
 324   
 325  509 static void addBindingToComponent(IComponent component, String parameterName, IBinding binding)
 326    {
 327  509 IBinding existing = component.getBinding(parameterName);
 328   
 329  509 if (existing != null)
 330  1 throw new ApplicationRuntimeException(PageloadMessages.duplicateParameter(
 331    parameterName,
 332    existing), component, binding.getLocation(), null);
 333   
 334  508 component.setBinding(parameterName, binding);
 335    }
 336   
 337  505 private IBinding convert(IComponent container, String description, String defaultBindingType,
 338    IBindingSpecification spec)
 339    {
 340  505 Location location = spec.getLocation();
 341  505 String bindingReference = spec.getValue();
 342   
 343  505 return _bindingSource.createBinding(
 344    container,
 345    description,
 346    bindingReference,
 347    defaultBindingType,
 348    location);
 349    }
 350   
 351    /**
 352    * Construct a {@link ListenerBinding} for the component, and add it.
 353    *
 354    * @since 3.0
 355    */
 356   
 357  3 private void constructListenerBinding(IComponent component, String parameterName,
 358    IListenerBindingSpecification spec)
 359    {
 360  3 String language = spec.getLanguage();
 361   
 362    // If not provided in the page or component specification, then
 363    // search for a default (factory default is "jython").
 364   
 365  3 if (HiveMind.isBlank(language))
 366  0 language = _defaultScriptLanguage;
 367   
 368    // Construct the binding. The first parameter is the compononent
 369    // (not the DirectLink or Form, but the page or component containing the
 370    // link or form).
 371   
 372  3 String description = PageloadMessages.parameterName(parameterName);
 373   
 374  3 IBinding binding = new ListenerBinding(description, _valueConverter, spec.getLocation(),
 375    component.getContainer(), language, spec.getScript(), _managerFactory);
 376   
 377  3 addBindingToComponent(component, parameterName, binding);
 378    }
 379   
 380    /**
 381    * Sets up a component. This involves:
 382    * <ul>
 383    * <li>Instantiating any contained components.
 384    * <li>Add the contained components to the container.
 385    * <li>Setting up bindings between container and containees.
 386    * <li>Construct the containees recursively.
 387    * <li>Invoking
 388    * {@link IComponent#finishLoad(IRequestCycle, IPageLoader, IComponentSpecification)}
 389    * </ul>
 390    *
 391    * @param cycle
 392    * the request cycle for which the page is being (initially) constructed
 393    * @param page
 394    * The page on which the container exists.
 395    * @param container
 396    * The component to be set up.
 397    * @param containerSpec
 398    * The specification for the container.
 399    * @param the
 400    * namespace of the container
 401    */
 402   
 403  1105 private void constructComponent(IRequestCycle cycle, IPage page, IComponent container,
 404    IComponentSpecification containerSpec, INamespace namespace)
 405    {
 406  1105 _depth++;
 407  1105 if (_depth > _maxDepth)
 408  310 _maxDepth = _depth;
 409   
 410  1105 List ids = new ArrayList(containerSpec.getComponentIds());
 411  1105 int count = ids.size();
 412   
 413  1105 try
 414    {
 415  1105 for (int i = 0; i < count; i++)
 416    {
 417  376 String id = (String) ids.get(i);
 418   
 419    // Get the sub-component specification from the
 420    // container's specification.
 421   
 422  376 IContainedComponent contained = containerSpec.getComponent(id);
 423   
 424  376 String type = contained.getType();
 425  376 Location location = contained.getLocation();
 426   
 427  376 _componentResolver.resolve(cycle, namespace, type, location);
 428   
 429  376 IComponentSpecification componentSpecification = _componentResolver
 430    .getSpecification();
 431  376 INamespace componentNamespace = _componentResolver.getNamespace();
 432   
 433    // Instantiate the contained component.
 434   
 435  376 IComponent component = instantiateComponent(
 436    page,
 437    container,
 438    id,
 439    componentSpecification,
 440    _componentResolver.getType(),
 441    componentNamespace,
 442    contained);
 443   
 444    // Add it, by name, to the container.
 445   
 446  376 container.addComponent(component);
 447   
 448    // Set up any bindings in the IContainedComponent specification
 449   
 450  376 bind(container, component, contained);
 451   
 452    // Now construct the component recusively; it gets its chance
 453    // to create its subcomponents and set their bindings.
 454   
 455  374 constructComponent(
 456    cycle,
 457    page,
 458    component,
 459    componentSpecification,
 460    componentNamespace);
 461    }
 462   
 463  1103 addAssets(container, containerSpec);
 464   
 465    // Finish the load of the component; most components (which
 466    // subclass BaseComponent) load their templates here.
 467    // Properties with initial values will be set here (or the
 468    // initial value will be recorded for later use in pageDetach().
 469    // That may cause yet more components to be created, and more
 470    // bindings to be set, so we defer some checking until
 471    // later.
 472   
 473  1103 container.finishLoad(cycle, this, containerSpec);
 474   
 475    // Have the component switch over to its active state.
 476   
 477  1096 container.enterActiveState();
 478    }
 479    catch (ApplicationRuntimeException ex)
 480    {
 481  9 throw ex;
 482    }
 483    catch (RuntimeException ex)
 484    {
 485  0 throw new ApplicationRuntimeException(PageloadMessages.unableToInstantiateComponent(
 486    container,
 487    ex), container, null, ex);
 488    }
 489   
 490  1096 _depth--;
 491    }
 492   
 493    /**
 494    * Invoked to create an implicit component (one which is defined in the containing component's
 495    * template, rather that in the containing component's specification).
 496    *
 497    * @see org.apache.tapestry.services.impl.ComponentTemplateLoaderImpl
 498    * @since 3.0
 499    */
 500   
 501  603 public IComponent createImplicitComponent(IRequestCycle cycle, IComponent container,
 502    String componentId, String componentType, Location location)
 503    {
 504  603 IPage page = container.getPage();
 505   
 506  603 _componentResolver.resolve(cycle, container.getNamespace(), componentType, location);
 507   
 508  603 INamespace componentNamespace = _componentResolver.getNamespace();
 509  603 IComponentSpecification spec = _componentResolver.getSpecification();
 510   
 511  603 IContainedComponent contained = new ContainedComponent();
 512  603 contained.setLocation(location);
 513  603 contained.setType(componentType);
 514   
 515  603 IComponent result = instantiateComponent(
 516    page,
 517    container,
 518    componentId,
 519    spec,
 520    _componentResolver.getType(),
 521    componentNamespace,
 522    contained);
 523   
 524  602 container.addComponent(result);
 525   
 526    // Recusively build the component.
 527   
 528  602 constructComponent(cycle, page, result, spec, componentNamespace);
 529   
 530  600 return result;
 531    }
 532   
 533    /**
 534    * Instantiates a component from its specification. We instantiate the component object, then
 535    * set its specification, page, container and id.
 536    *
 537    * @see AbstractComponent
 538    */
 539   
 540  979 private IComponent instantiateComponent(IPage page, IComponent container, String id,
 541    IComponentSpecification spec, String type, INamespace namespace,
 542    IContainedComponent containedComponent)
 543    {
 544  979 ComponentClassProviderContext context = new ComponentClassProviderContext(type, spec,
 545    namespace);
 546  979 String className = _componentClassProvider.provideComponentClassName(context);
 547   
 548    // String className = spec.getComponentClassName();
 549   
 550  979 if (HiveMind.isBlank(className))
 551  0 className = BaseComponent.class.getName();
 552    else
 553    {
 554  979 Class componentClass = _classResolver.findClass(className);
 555   
 556  979 if (!IComponent.class.isAssignableFrom(componentClass))
 557  1 throw new ApplicationRuntimeException(PageloadMessages
 558    .classNotComponent(componentClass), container, spec.getLocation(), null);
 559   
 560  978 if (IPage.class.isAssignableFrom(componentClass))
 561  0 throw new ApplicationRuntimeException(PageloadMessages.pageNotAllowed(id),
 562    container, spec.getLocation(), null);
 563    }
 564   
 565  978 ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(
 566    spec,
 567    className);
 568   
 569  978 IComponent result = (IComponent) cc.newInstance();
 570   
 571  978 result.setNamespace(namespace);
 572  978 result.setPage(page);
 573  978 result.setContainer(container);
 574  978 result.setId(id);
 575  978 result.setContainedComponent(containedComponent);
 576  978 result.setLocation(containedComponent.getLocation());
 577   
 578  978 _count++;
 579   
 580  978 return result;
 581    }
 582   
 583    /**
 584    * Instantitates a page from its specification.
 585    *
 586    * @param name
 587    * the unqualified, simple, name for the page
 588    * @param namespace
 589    * the namespace containing the page's specification
 590    * @param spec
 591    * the page's specification We instantiate the page object, then set its
 592    * specification, names and locale.
 593    * @see IEngine
 594    * @see ChangeObserver
 595    */
 596   
 597  131 private IPage instantiatePage(String name, INamespace namespace, IComponentSpecification spec)
 598    {
 599  131 Location location = spec.getLocation();
 600  131 ComponentClassProviderContext context = new ComponentClassProviderContext(name, spec,
 601    namespace);
 602  131 String className = _pageClassProvider.provideComponentClassName(context);
 603   
 604  131 Class pageClass = _classResolver.findClass(className);
 605   
 606  130 if (!IPage.class.isAssignableFrom(pageClass))
 607  1 throw new ApplicationRuntimeException(PageloadMessages.classNotPage(pageClass),
 608    location, null);
 609   
 610  129 String pageName = namespace.constructQualifiedName(name);
 611   
 612  129 ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor(
 613    spec,
 614    className);
 615   
 616  129 IPage result = (IPage) cc.newInstance();
 617   
 618  129 result.setNamespace(namespace);
 619  129 result.setPageName(pageName);
 620  129 result.setPage(result);
 621  129 result.setLocale(_locale);
 622  129 result.setLocation(location);
 623   
 624  129 return result;
 625    }
 626   
 627  131 public IPage loadPage(String name, INamespace namespace, IRequestCycle cycle,
 628    IComponentSpecification specification)
 629    {
 630  131 IPage page = null;
 631   
 632  131 _count = 0;
 633  131 _depth = 0;
 634  131 _maxDepth = 0;
 635   
 636  131 _locale = _threadLocale.getLocale();
 637   
 638  131 try
 639    {
 640  131 page = instantiatePage(name, namespace, specification);
 641   
 642  129 constructComponent(cycle, page, page, specification, namespace);
 643   
 644    // Walk through the complete component tree to set up the default
 645    // parameter values.
 646  122 _establishDefaultParameterValuesWalker.walkComponentTree(page);
 647   
 648  122 establishInheritedBindings();
 649   
 650    // Walk through the complete component tree to ensure that required
 651    // parameters are bound
 652  122 _verifyRequiredParametersWalker.walkComponentTree(page);
 653    }
 654    finally
 655    {
 656  131 _locale = null;
 657  131 _inheritedBindingQueue.clear();
 658    }
 659   
 660  122 if (_log.isDebugEnabled())
 661  0 _log.debug("Loaded page " + page + " with " + _count + " components (maximum depth "
 662    + _maxDepth + ")");
 663   
 664  122 return page;
 665    }
 666   
 667    /** @since 4.0 */
 668   
 669  213 public void loadTemplateForComponent(IRequestCycle cycle, ITemplateComponent component)
 670    {
 671  213 _componentTemplateLoader.loadTemplate(cycle, component);
 672    }
 673   
 674  122 private void establishInheritedBindings()
 675    {
 676  122 _log.debug("Establishing inherited bindings");
 677   
 678  122 int count = _inheritedBindingQueue.size();
 679   
 680  122 for (int i = 0; i < count; i++)
 681    {
 682  2 IQueuedInheritedBinding queued = (IQueuedInheritedBinding) _inheritedBindingQueue
 683    .get(i);
 684   
 685  2 queued.connect();
 686    }
 687    }
 688   
 689  1103 private void addAssets(IComponent component, IComponentSpecification specification)
 690    {
 691  1103 List names = specification.getAssetNames();
 692   
 693  1103 if (names.isEmpty())
 694  1050 return;
 695   
 696  53 Iterator i = names.iterator();
 697   
 698  53 while (i.hasNext())
 699    {
 700  57 String name = (String) i.next();
 701   
 702  57 IAssetSpecification assetSpec = specification.getAsset(name);
 703   
 704  57 IAsset asset = convertAsset(assetSpec);
 705   
 706  57 component.addAsset(name, asset);
 707    }
 708    }
 709   
 710    /**
 711    * Builds an instance of {@link IAsset} from the specification.
 712    */
 713   
 714  57 private IAsset convertAsset(IAssetSpecification spec)
 715    {
 716    // AssetType type = spec.getType();
 717  57 String path = spec.getPath();
 718  57 Location location = spec.getLocation();
 719   
 720  57 Resource specResource = location.getResource();
 721   
 722    // And ugly, ugly kludge. For page and component specifications in the
 723    // context (typically, somewhere under WEB-INF), we evaluate them
 724    // relative the web application root.
 725   
 726  57 if (isContextResource(specResource))
 727  1 specResource = specResource.getRelativeResource("/");
 728   
 729  57 return _assetSource.findAsset(specResource, path, _locale, location);
 730    }
 731   
 732  57 private boolean isContextResource(Resource resource)
 733    {
 734  57 return (resource instanceof WebContextResource) || (resource instanceof ContextResource);
 735    }
 736   
 737    /** @since 4.0 */
 738   
 739  43 public void setLog(Log log)
 740    {
 741  43 _log = log;
 742    }
 743   
 744    /** @since 4.0 */
 745   
 746  41 public void setComponentResolver(ComponentSpecificationResolver resolver)
 747    {
 748  41 _componentResolver = resolver;
 749    }
 750   
 751    /** @since 4.0 */
 752   
 753  41 public void setDefaultScriptLanguage(String string)
 754    {
 755  41 _defaultScriptLanguage = string;
 756    }
 757   
 758    /** @since 4.0 */
 759   
 760  43 public void setBindingSource(BindingSource bindingSource)
 761    {
 762  43 _bindingSource = bindingSource;
 763    }
 764   
 765    /**
 766    * @since 4.0
 767    */
 768  41 public void setComponentTemplateLoader(ComponentTemplateLoader componentTemplateLoader)
 769    {
 770  41 _componentTemplateLoader = componentTemplateLoader;
 771    }
 772   
 773    /** @since 4.0 */
 774  41 public void setEstablishDefaultParameterValuesVisitor(
 775    IComponentVisitor establishDefaultParameterValuesVisitor)
 776    {
 777  41 _establishDefaultParameterValuesVisitor = establishDefaultParameterValuesVisitor;
 778    }
 779   
 780    /** @since 4.0 */
 781  41 public void setComponentConstructorFactory(
 782    ComponentConstructorFactory componentConstructorFactory)
 783    {
 784  41 _componentConstructorFactory = componentConstructorFactory;
 785    }
 786   
 787    /** @since 4.0 */
 788  41 public void setValueConverter(ValueConverter valueConverter)
 789    {
 790  41 _valueConverter = valueConverter;
 791    }
 792   
 793    /** @since 4.0 */
 794  41 public void setAssetSource(AssetSource assetSource)
 795    {
 796  41 _assetSource = assetSource;
 797    }
 798   
 799    /** @since 4.0 */
 800  41 public void setManagerFactory(BSFManagerFactory managerFactory)
 801    {
 802  41 _managerFactory = managerFactory;
 803    }
 804   
 805    /** @since 4.0 */
 806  41 public void setPageClassProvider(ComponentClassProvider pageClassProvider)
 807    {
 808  41 _pageClassProvider = pageClassProvider;
 809    }
 810   
 811    /** @since 4.0 */
 812  41 public void setClassResolver(ClassResolver classResolver)
 813    {
 814  41 _classResolver = classResolver;
 815    }
 816   
 817    /**
 818    * @since 4.0
 819    */
 820  41 public void setComponentClassProvider(ComponentClassProvider componentClassProvider)
 821    {
 822  41 _componentClassProvider = componentClassProvider;
 823    }
 824   
 825    /** @since 4.0 */
 826  41 public void setThreadLocale(ThreadLocale threadLocale)
 827    {
 828  41 _threadLocale = threadLocale;
 829    }
 830    }