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