1 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.service.ThreadLocale; 28 import org.apache.tapestry.AbstractComponent; 29 import org.apache.tapestry.BaseComponent; 30 import org.apache.tapestry.IAsset; 31 import org.apache.tapestry.IBinding; 32 import org.apache.tapestry.IComponent; 33 import org.apache.tapestry.IEngine; 34 import org.apache.tapestry.INamespace; 35 import org.apache.tapestry.IPage; 36 import org.apache.tapestry.IRequestCycle; 37 import org.apache.tapestry.ITemplateComponent; 38 import org.apache.tapestry.asset.AssetSource; 39 import org.apache.tapestry.binding.BindingConstants; 40 import org.apache.tapestry.binding.BindingSource; 41 import org.apache.tapestry.binding.BindingUtils; 42 import org.apache.tapestry.binding.ExpressionBinding; 43 import org.apache.tapestry.binding.ListenerBinding; 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.BSFManagerFactory; 49 import org.apache.tapestry.services.ComponentConstructor; 50 import org.apache.tapestry.services.ComponentConstructorFactory; 51 import org.apache.tapestry.services.ComponentTemplateLoader; 52 import org.apache.tapestry.spec.BindingType; 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.IListenerBindingSpecification; 58 import org.apache.tapestry.spec.IParameterSpecification; 59 60 67 68 public class PageLoader implements IPageLoader 69 { 70 private Log _log; 71 72 73 74 private ComponentSpecificationResolver _componentResolver; 75 76 77 78 private String _defaultScriptLanguage; 79 80 81 82 private BindingSource _bindingSource; 83 84 85 86 private ComponentTemplateLoader _componentTemplateLoader; 87 88 89 90 private BSFManagerFactory _managerFactory; 91 92 private List _inheritedBindingQueue = new ArrayList (); 93 94 95 private IComponentVisitor _establishDefaultParameterValuesVisitor; 96 97 private ComponentTreeWalker _establishDefaultParameterValuesWalker; 98 99 private ComponentTreeWalker _verifyRequiredParametersWalker; 100 101 102 103 private ComponentConstructorFactory _componentConstructorFactory; 104 105 106 107 private ValueConverter _valueConverter; 108 109 110 111 private AssetSource _assetSource; 112 113 118 119 private ComponentClassProvider _pageClassProvider; 120 121 127 128 private ComponentClassProvider _componentClassProvider; 129 130 135 136 private ThreadLocale _threadLocale; 137 138 141 142 private Locale _locale; 143 144 147 148 private int _count; 149 150 153 154 private int _depth; 155 156 159 160 private int _maxDepth; 161 162 163 164 private ClassResolver _classResolver; 165 166 public void initializeService() 167 { 168 169 IComponentVisitor verifyRequiredParametersVisitor = new VerifyRequiredParametersVisitor(); 172 173 _verifyRequiredParametersWalker = new ComponentTreeWalker(new IComponentVisitor[] 174 { verifyRequiredParametersVisitor }); 175 176 _establishDefaultParameterValuesWalker = new ComponentTreeWalker(new IComponentVisitor[] 177 { _establishDefaultParameterValuesVisitor }); 178 } 179 180 197 198 void bind(IComponent container, IComponent component, IContainedComponent contained) 199 { 200 IComponentSpecification spec = component.getSpecification(); 201 boolean formalOnly = !spec.getAllowInformalParameters(); 202 203 if (contained.getInheritInformalParameters()) 204 { 205 if (formalOnly) 206 throw new ApplicationRuntimeException(PageloadMessages 207 .inheritInformalInvalidComponentFormalOnly(component), component, contained 208 .getLocation(), null); 209 210 IComponentSpecification containerSpec = container.getSpecification(); 211 212 if (!containerSpec.getAllowInformalParameters()) 213 throw new ApplicationRuntimeException(PageloadMessages 214 .inheritInformalInvalidContainerFormalOnly(container, component), 215 component, contained.getLocation(), null); 216 217 IQueuedInheritedBinding queued = new QueuedInheritInformalBindings(component); 218 _inheritedBindingQueue.add(queued); 219 } 220 221 Iterator i = contained.getBindingNames().iterator(); 222 223 while (i.hasNext()) 224 { 225 String name = (String ) i.next(); 226 227 IParameterSpecification pspec = spec.getParameter(name); 228 229 boolean isFormal = pspec != null; 230 231 String parameterName = isFormal ? pspec.getParameterName() : name; 232 233 IBindingSpecification bspec = contained.getBinding(name); 234 235 239 if (formalOnly && !isFormal) 240 throw new ApplicationRuntimeException(PageloadMessages.formalParametersOnly( 241 component, 242 name), component, bspec.getLocation(), null); 243 244 247 if (!isFormal && spec.isReservedParameterName(name)) 248 continue; 249 250 if (isFormal) 251 { 252 if (!name.equals(parameterName)) 253 { 254 _log.error(PageloadMessages.usedParameterAlias( 255 contained, 256 name, 257 parameterName, 258 bspec.getLocation())); 259 } 260 else if (pspec.isDeprecated()) 261 _log.error(PageloadMessages.deprecatedParameter( 262 name, 263 bspec.getLocation(), 264 contained.getType())); 265 } 266 267 274 BindingType type = bspec.getType(); 275 276 282 if (type == BindingType.INHERITED) 283 { 284 QueuedInheritedBinding queued = new QueuedInheritedBinding(component, bspec 285 .getValue(), parameterName); 286 _inheritedBindingQueue.add(queued); 287 continue; 288 } 289 290 if (type == BindingType.LISTENER) 291 { 292 constructListenerBinding( 293 component, 294 parameterName, 295 (IListenerBindingSpecification) bspec); 296 continue; 297 } 298 299 String description = PageloadMessages.parameterName(name); 300 301 304 String defaultBindingType = BindingUtils.getDefaultBindingType( 305 spec, 306 parameterName, 307 BindingConstants.OGNL_PREFIX); 308 309 IBinding binding = convert(container, description, defaultBindingType, bspec); 310 311 addBindingToComponent(component, parameterName, binding); 312 } 313 } 314 315 329 330 static void addBindingToComponent(IComponent component, String parameterName, IBinding binding) 331 { 332 IBinding existing = component.getBinding(parameterName); 333 334 if (existing != null) 335 throw new ApplicationRuntimeException(PageloadMessages.duplicateParameter( 336 parameterName, 337 existing), component, binding.getLocation(), null); 338 339 component.setBinding(parameterName, binding); 340 } 341 342 private IBinding convert(IComponent container, String description, String defaultBindingType, 343 IBindingSpecification spec) 344 { 345 Location location = spec.getLocation(); 346 String bindingReference = spec.getValue(); 347 348 return _bindingSource.createBinding( 349 container, 350 description, 351 bindingReference, 352 defaultBindingType, 353 location); 354 } 355 356 361 362 private void constructListenerBinding(IComponent component, String parameterName, 363 IListenerBindingSpecification spec) 364 { 365 String language = spec.getLanguage(); 366 367 370 if (HiveMind.isBlank(language)) 371 language = _defaultScriptLanguage; 372 373 377 String description = PageloadMessages.parameterName(parameterName); 378 379 IBinding binding = new ListenerBinding(description, _valueConverter, spec.getLocation(), 380 component.getContainer(), language, spec.getScript(), _managerFactory); 381 382 addBindingToComponent(component, parameterName, binding); 383 } 384 385 407 408 private void constructComponent(IRequestCycle cycle, IPage page, IComponent container, 409 IComponentSpecification containerSpec, INamespace namespace) 410 { 411 _depth++; 412 if (_depth > _maxDepth) 413 _maxDepth = _depth; 414 415 List ids = new ArrayList (containerSpec.getComponentIds()); 416 int count = ids.size(); 417 418 try 419 { 420 for (int i = 0; i < count; i++) 421 { 422 String id = (String ) ids.get(i); 423 424 427 IContainedComponent contained = containerSpec.getComponent(id); 428 429 String type = contained.getType(); 430 Location location = contained.getLocation(); 431 432 _componentResolver.resolve(cycle, namespace, type, location); 433 434 IComponentSpecification componentSpecification = _componentResolver 435 .getSpecification(); 436 INamespace componentNamespace = _componentResolver.getNamespace(); 437 438 440 IComponent component = instantiateComponent( 441 page, 442 container, 443 id, 444 componentSpecification, 445 _componentResolver.getType(), 446 componentNamespace, 447 location); 448 449 451 container.addComponent(component); 452 453 455 bind(container, component, contained); 456 457 460 constructComponent( 461 cycle, 462 page, 463 component, 464 componentSpecification, 465 componentNamespace); 466 } 467 468 addAssets(container, containerSpec); 469 470 478 container.finishLoad(cycle, this, containerSpec); 479 480 482 container.enterActiveState(); 483 } 484 catch (ApplicationRuntimeException ex) 485 { 486 throw ex; 487 } 488 catch (RuntimeException ex) 489 { 490 throw new ApplicationRuntimeException(PageloadMessages.unableToInstantiateComponent( 491 container, 492 ex), container, null, ex); 493 } 494 495 _depth--; 496 } 497 498 505 506 public IComponent createImplicitComponent(IRequestCycle cycle, IComponent container, 507 String componentId, String componentType, Location location) 508 { 509 IPage page = container.getPage(); 510 511 _componentResolver.resolve(cycle, container.getNamespace(), componentType, location); 512 513 INamespace componentNamespace = _componentResolver.getNamespace(); 514 IComponentSpecification spec = _componentResolver.getSpecification(); 515 516 IComponent result = instantiateComponent( 517 page, 518 container, 519 componentId, 520 spec, 521 _componentResolver.getType(), 522 componentNamespace, 523 location); 524 525 container.addComponent(result); 526 527 529 constructComponent(cycle, page, result, spec, componentNamespace); 530 531 return result; 532 } 533 534 540 541 private IComponent instantiateComponent(IPage page, IComponent container, String id, 542 IComponentSpecification spec, String type, INamespace namespace, Location location) 543 { 544 ComponentClassProviderContext context = new ComponentClassProviderContext(type, spec, 545 namespace); 546 String className = _componentClassProvider.provideComponentClassName(context); 547 548 550 if (HiveMind.isBlank(className)) 551 className = BaseComponent.class.getName(); 552 else 553 { 554 Class componentClass = _classResolver.findClass(className); 555 556 if (!IComponent.class.isAssignableFrom(componentClass)) 557 throw new ApplicationRuntimeException(PageloadMessages 558 .classNotComponent(componentClass), container, spec.getLocation(), null); 559 560 if (IPage.class.isAssignableFrom(componentClass)) 561 throw new ApplicationRuntimeException(PageloadMessages.pageNotAllowed(id), 562 container, spec.getLocation(), null); 563 } 564 565 ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor( 566 spec, 567 className); 568 569 IComponent result = (IComponent) cc.newInstance(); 570 571 result.setNamespace(namespace); 572 result.setPage(page); 573 result.setContainer(container); 574 result.setId(id); 575 result.setLocation(location); 576 577 _count++; 578 579 return result; 580 } 581 582 595 596 private IPage instantiatePage(String name, INamespace namespace, IComponentSpecification spec) 597 { 598 Location location = spec.getLocation(); 599 ComponentClassProviderContext context = new ComponentClassProviderContext(name, spec, 600 namespace); 601 String className = _pageClassProvider.provideComponentClassName(context); 602 603 Class pageClass = _classResolver.findClass(className); 604 605 if (!IPage.class.isAssignableFrom(pageClass)) 606 throw new ApplicationRuntimeException(PageloadMessages.classNotPage(pageClass), 607 location, null); 608 609 String pageName = namespace.constructQualifiedName(name); 610 611 ComponentConstructor cc = _componentConstructorFactory.getComponentConstructor( 612 spec, 613 className); 614 615 IPage result = (IPage) cc.newInstance(); 616 617 result.setNamespace(namespace); 618 result.setPageName(pageName); 619 result.setPage(result); 620 result.setLocale(_locale); 621 result.setLocation(location); 622 623 return result; 624 } 625 626 public IPage loadPage(String name, INamespace namespace, IRequestCycle cycle, 627 IComponentSpecification specification) 628 { 629 IPage page = null; 630 631 _count = 0; 632 _depth = 0; 633 _maxDepth = 0; 634 635 _locale = _threadLocale.getLocale(); 636 637 try 638 { 639 page = instantiatePage(name, namespace, specification); 640 641 constructComponent(cycle, page, page, specification, namespace); 642 643 _establishDefaultParameterValuesWalker.walkComponentTree(page); 646 647 establishInheritedBindings(); 648 649 _verifyRequiredParametersWalker.walkComponentTree(page); 652 } 653 finally 654 { 655 _locale = null; 656 _inheritedBindingQueue.clear(); 657 } 658 659 if (_log.isDebugEnabled()) 660 _log.debug("Loaded page " + page + " with " + _count + " components (maximum depth " 661 + _maxDepth + ")"); 662 663 return page; 664 } 665 666 667 668 public void loadTemplateForComponent(IRequestCycle cycle, ITemplateComponent component) 669 { 670 _componentTemplateLoader.loadTemplate(cycle, component); 671 } 672 673 private void establishInheritedBindings() 674 { 675 _log.debug("Establishing inherited bindings"); 676 677 int count = _inheritedBindingQueue.size(); 678 679 for (int i = 0; i < count; i++) 680 { 681 IQueuedInheritedBinding queued = (IQueuedInheritedBinding) _inheritedBindingQueue 682 .get(i); 683 684 queued.connect(); 685 } 686 } 687 688 private void addAssets(IComponent component, IComponentSpecification specification) 689 { 690 List names = specification.getAssetNames(); 691 692 if (names.isEmpty()) 693 return; 694 695 Iterator i = names.iterator(); 696 697 while (i.hasNext()) 698 { 699 String name = (String ) i.next(); 700 701 IAssetSpecification assetSpec = specification.getAsset(name); 702 703 IAsset asset = convertAsset(assetSpec); 704 705 component.addAsset(name, asset); 706 } 707 } 708 709 712 713 private IAsset convertAsset(IAssetSpecification spec) 714 { 715 String path = spec.getPath(); 717 Location location = spec.getLocation(); 718 719 return _assetSource.findAsset(location.getResource(), path, _locale, location); 720 } 721 722 723 724 public void setLog(Log log) 725 { 726 _log = log; 727 } 728 729 730 731 public void setComponentResolver(ComponentSpecificationResolver resolver) 732 { 733 _componentResolver = resolver; 734 } 735 736 737 738 public void setDefaultScriptLanguage(String string) 739 { 740 _defaultScriptLanguage = string; 741 } 742 743 744 745 public void setBindingSource(BindingSource bindingSource) 746 { 747 _bindingSource = bindingSource; 748 } 749 750 753 public void setComponentTemplateLoader(ComponentTemplateLoader componentTemplateLoader) 754 { 755 _componentTemplateLoader = componentTemplateLoader; 756 } 757 758 759 public void setEstablishDefaultParameterValuesVisitor( 760 IComponentVisitor establishDefaultParameterValuesVisitor) 761 { 762 _establishDefaultParameterValuesVisitor = establishDefaultParameterValuesVisitor; 763 } 764 765 766 public void setComponentConstructorFactory( 767 ComponentConstructorFactory componentConstructorFactory) 768 { 769 _componentConstructorFactory = componentConstructorFactory; 770 } 771 772 773 public void setValueConverter(ValueConverter valueConverter) 774 { 775 _valueConverter = valueConverter; 776 } 777 778 779 public void setAssetSource(AssetSource assetSource) 780 { 781 _assetSource = assetSource; 782 } 783 784 785 public void setManagerFactory(BSFManagerFactory managerFactory) 786 { 787 _managerFactory = managerFactory; 788 } 789 790 791 public void setPageClassProvider(ComponentClassProvider pageClassProvider) 792 { 793 _pageClassProvider = pageClassProvider; 794 } 795 796 797 public void setClassResolver(ClassResolver classResolver) 798 { 799 _classResolver = classResolver; 800 } 801 802 805 public void setComponentClassProvider(ComponentClassProvider componentClassProvider) 806 { 807 _componentClassProvider = componentClassProvider; 808 } 809 810 811 public void setThreadLocale(ThreadLocale threadLocale) 812 { 813 _threadLocale = threadLocale; 814 } 815 } | Popular Tags |