1 16 package org.apache.cocoon.components; 17 18 import java.io.IOException ; 19 import java.net.MalformedURLException ; 20 import java.util.ArrayList ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Map ; 25 26 import org.apache.avalon.excalibur.component.ExcaliburComponentManager; 27 import org.apache.avalon.framework.component.Component; 28 import org.apache.avalon.framework.component.ComponentException; 29 import org.apache.avalon.framework.component.ComponentManager; 30 import org.apache.avalon.framework.component.ComponentSelector; 31 import org.apache.avalon.framework.component.Recomposable; 32 import org.apache.avalon.framework.configuration.Configuration; 33 import org.apache.avalon.framework.configuration.ConfigurationException; 34 import org.apache.avalon.framework.logger.Logger; 35 import org.apache.cocoon.ProcessingException; 36 import org.apache.cocoon.Processor; 37 import org.apache.cocoon.environment.Environment; 38 import org.apache.cocoon.xml.XMLConsumer; 39 import org.apache.excalibur.source.Source; 40 import org.apache.excalibur.source.SourceException; 41 import org.apache.excalibur.source.SourceResolver; 42 43 56 public final class CocoonComponentManager extends ExcaliburComponentManager 57 implements SourceResolver { 58 59 60 private static final String PROCESS_KEY = CocoonComponentManager.class.getName(); 61 62 63 private static final String PROCESSOR_ATTR = "CocoonComponentManager.processor"; 64 65 66 protected static final ThreadLocal environmentStack = new ThreadLocal (); 67 68 69 private SourceResolver sourceResolver; 70 71 72 private Map sitemapConfigurationHolders = new HashMap (15); 73 74 75 private ComponentManager parentManager; 76 77 79 private ArrayList parentAwareComponents = new ArrayList (); 80 81 82 private boolean wasDisposed; 83 84 85 86 public CocoonComponentManager() { 87 super(null, Thread.currentThread().getContextClassLoader()); 88 } 89 90 91 public CocoonComponentManager(final ClassLoader loader) { 92 super(null, loader); 93 } 94 95 96 public CocoonComponentManager(final ComponentManager manager, final ClassLoader loader) { 97 super(manager, loader); 98 this.parentManager = manager; 99 } 100 101 102 public CocoonComponentManager(final ComponentManager manager) { 103 super(manager); 104 this.parentManager = manager; 105 } 106 107 112 public static void enterEnvironment(Environment env, 113 ComponentManager manager, 114 Processor processor) { 115 if (null == env || null == manager || null == processor) { 116 throw new RuntimeException ("CocoonComponentManager.enterEnvironment: " + 117 "All parameters must be set: " + env + " - " + manager + " - " + processor); 118 } 119 120 EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 121 if (stack == null) { 122 stack = new EnvironmentStack(); 123 environmentStack.set(stack); 124 } 125 stack.push(new EnvironmentStack.Item(env, processor, manager, stack.getOffset())); 126 stack.setOffset(stack.size()-1); 127 128 env.setAttribute(PROCESSOR_ATTR, processor); 129 } 130 131 135 public static void leaveEnvironment() { 136 leaveEnvironment(true); 138 } 139 140 146 public static void leaveEnvironment(boolean success) { 147 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 148 final EnvironmentStack.Item objs = (EnvironmentStack.Item)stack.pop(); 149 stack.setOffset(objs.offset); 150 151 if (stack.isEmpty()) { 152 final Environment env = objs.env; 153 final Map globalComponents = (Map )env.getAttribute(GlobalRequestLifecycleComponent.class.getName()); 154 if (globalComponents != null) { 155 156 final Iterator iter = globalComponents.values().iterator(); 157 while (iter.hasNext()) { 158 final Object [] o = (Object [])iter.next(); 159 final Component c = (Component)o[0]; 160 ((CocoonComponentManager)o[1]).releaseRLComponent( c ); 161 } 162 } 163 env.removeAttribute(GlobalRequestLifecycleComponent.class.getName()); 164 165 CocoonComponentManager.environmentStack.set(null); 167 } else { 168 if (!success) { 169 getCurrentEnvironment().setAttribute(PROCESSOR_ATTR, getCurrentProcessor()); 171 } 172 } 173 } 174 175 178 public static int markEnvironment() { 179 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 181 if (stack != null) { 182 return stack.size(); 183 } 184 185 return 0; 186 } 187 188 191 public static void checkEnvironment(int depth, Logger logger) 192 throws Exception { 193 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 195 int currentDepth = stack != null? stack.size() : 0; 196 if (currentDepth != depth) { 197 logger.error("ENVIRONMENT STACK HAS NOT BEEN CLEANED PROPERLY!"); 198 throw new ProcessingException("Environment stack has not been cleaned up properly. " + 199 "Please report this (and if possible, together with a test case) " + 200 "to the Cocoon developers."); 201 } 202 } 203 204 208 public static XMLConsumer createEnvironmentAwareConsumer(XMLConsumer consumer) { 209 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 210 final EnvironmentStack.Item objs = stack.getCurrent(); 211 return stack.getEnvironmentAwareConsumerWrapper(consumer, objs.offset); 212 } 213 214 223 public static Object startProcessing(Environment env) { 224 if (null == env) { 225 throw new RuntimeException ("CocoonComponentManager.startProcessing: environment must be set."); 226 } 227 final EnvironmentDescription desc = new EnvironmentDescription(env); 228 env.getObjectModel().put(PROCESS_KEY, desc); 229 env.startingProcessing(); 230 return desc; 231 } 232 233 240 public static void endProcessing(Environment env, Object key) { 241 env.finishingProcessing(); 242 final EnvironmentDescription desc = (EnvironmentDescription)key; 243 desc.release(); 244 env.getObjectModel().remove(PROCESS_KEY); 245 } 246 247 250 public static Environment getCurrentEnvironment() { 251 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 252 if (null != stack && !stack.isEmpty()) { 253 return stack.getCurrent().env; 254 } 255 return null; 256 } 257 258 261 public static Processor getCurrentProcessor() { 262 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 263 if (null != stack && !stack.isEmpty()) { 264 return stack.getCurrent().processor; 265 } 266 return null; 267 } 268 269 272 public static Processor getActiveProcessor(Environment env) { 273 return (Processor) env.getAttribute(PROCESSOR_ATTR); 274 } 275 276 282 static public ComponentManager getSitemapComponentManager() { 283 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 284 if (null != stack && !stack.isEmpty()) { 285 EnvironmentStack.Item o = (EnvironmentStack.Item) stack.peek(); 286 return o.manager; 287 } 288 289 return null; 291 } 292 293 298 public Component lookup(final String role) 299 throws ComponentException { 300 if (null == role) { 301 final String message = 302 "ComponentLocator Attempted to retrieve component with null role."; 303 throw new ComponentException(role, message); 304 } 305 306 if (role.equals(SourceResolver.ROLE)) { 307 if (null == this.sourceResolver) { 308 if(wasDisposed) { 309 getLogger().warn("Trying to lookup SourceResolver on disposed CocoonComponentManager"); 312 } 313 this.sourceResolver = (SourceResolver) super.lookup( role ); 314 } 315 return this; 316 } 317 318 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 319 if ( null != stack && !stack.isEmpty()) { 320 final EnvironmentStack.Item objects = stack.getCurrent(); 321 final Map objectModel = objects.env.getObjectModel(); 322 EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); 323 if ( null != desc ) { 324 Component component = desc.getRequestLifecycleComponent(role); 325 if (null != component) { 326 return component; 327 } 328 component = desc.getGlobalRequestLifecycleComponent(role); 329 if (null != component) { 330 return component; 331 } 332 } 333 } 334 335 final Component component = super.lookup(role); 336 337 if (component != null && component instanceof RequestLifecycleComponent) { 338 if (stack == null || stack.isEmpty()) { 339 throw new ComponentException(role, "ComponentManager has no Environment Stack."); 340 } 341 342 final EnvironmentStack.Item objects = stack.getCurrent(); 343 final Map objectModel = objects.env.getObjectModel(); 344 EnvironmentDescription desc = (EnvironmentDescription) objectModel.get(PROCESS_KEY); 345 if (null != desc) { 346 if (!desc.containsRequestLifecycleComponent(role)) { 348 try { 349 if (component instanceof Recomposable) { 350 ((Recomposable) component).recompose(this); 351 } 352 ((RequestLifecycleComponent) component).setup((org.apache.cocoon.environment.SourceResolver)objects.env, 353 objectModel); 354 } catch (Exception local) { 355 throw new ComponentException(role, "Exception during setup of RequestLifecycleComponent.", local); 356 } 357 desc.addRequestLifecycleComponent(role, component, this); 358 } 359 } 360 } 361 362 if (component != null && component instanceof GlobalRequestLifecycleComponent) { 363 if (stack == null || stack.isEmpty()) { 364 throw new ComponentException(role, "ComponentManager has no Environment Stack."); 365 } 366 367 final EnvironmentStack.Item objects = stack.getCurrent(); 368 final Map objectModel = objects.env.getObjectModel(); 369 EnvironmentDescription desc = (EnvironmentDescription) objectModel.get(PROCESS_KEY); 370 if (null != desc) { 371 if ( !desc.containsGlobalRequestLifecycleComponent( role ) ) { 373 try { 374 if (component instanceof Recomposable) { 375 ((Recomposable) component).recompose(this); 376 } 377 ((GlobalRequestLifecycleComponent) component).setup((org.apache.cocoon.environment.SourceResolver)objects.env, 378 objectModel); 379 } catch (Exception local) { 380 throw new ComponentException(role, "Exception during setup of RequestLifecycleComponent.", local); 381 } 382 desc.addGlobalRequestLifecycleComponent(role, component, this); 383 } 384 } 385 } 386 387 if (component != null && component instanceof SitemapConfigurable) { 388 SitemapConfigurationHolder holder; 390 391 holder = (SitemapConfigurationHolder) this.sitemapConfigurationHolders.get(role); 392 if (null == holder) { 393 holder = new DefaultSitemapConfigurationHolder(role); 395 this.sitemapConfigurationHolders.put(role, holder); 396 } 397 398 try { 399 ((SitemapConfigurable)component).configure(holder); 400 } catch (ConfigurationException ce) { 401 throw new ComponentException(role, "Exception during setup of SitemapConfigurable.", ce); 402 } 403 } 404 405 return component; 406 } 407 408 412 public void release(final Component component) { 413 if (null == component) { 414 return; 415 } 416 417 if (component instanceof RequestLifecycleComponent 418 || component instanceof GlobalRequestLifecycleComponent) { 419 return; 420 } 421 422 if (component == this) { 423 return; 424 } 425 426 super.release(component); 427 } 428 429 432 protected void releaseRLComponent(final Component component) { 433 super.release(component); 434 } 435 436 439 public static void addComponentForAutomaticRelease(final ComponentSelector selector, 440 final Component component, 441 final ComponentManager manager) 442 throws ProcessingException { 443 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 444 if ( null != stack && !stack.isEmpty()) { 445 final EnvironmentStack.Item objects = (EnvironmentStack.Item)stack.get(0); 446 final Map objectModel = objects.env.getObjectModel(); 447 EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); 448 if ( null != desc ) { 449 desc.addToAutoRelease(selector, component, manager); 450 } 451 } else { 452 throw new ProcessingException("Unable to add component for automatic release: no environment available."); 453 } 454 } 455 456 459 public static void addComponentForAutomaticRelease(final ComponentManager manager, 460 final Component component) 461 throws ProcessingException { 462 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 463 if ( null != stack && !stack.isEmpty()) { 464 final EnvironmentStack.Item objects = (EnvironmentStack.Item)stack.get(0); 465 final Map objectModel = objects.env.getObjectModel(); 466 EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); 467 if ( null != desc ) { 468 desc.addToAutoRelease(manager, component); 469 } 470 } else { 471 throw new ProcessingException("Unable to add component for automatic release: no environment available."); 472 } 473 } 474 475 478 public static void removeFromAutomaticRelease(final Component component) 479 throws ProcessingException { 480 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 481 if ( null != stack && !stack.isEmpty()) { 482 final EnvironmentStack.Item objects = (EnvironmentStack.Item)stack.get(0); 483 final Map objectModel = objects.env.getObjectModel(); 484 EnvironmentDescription desc = (EnvironmentDescription)objectModel.get(PROCESS_KEY); 485 if ( null != desc ) { 486 desc.removeFromAutoRelease(component); 487 } 488 } else { 489 throw new ProcessingException("Unable to remove component from automatic release: no environment available."); 490 } 491 } 492 493 496 public void dispose() { 497 if (getLogger().isDebugEnabled()) { 498 getLogger().debug("CocoonComponentManager.dispose() called"); 499 } 500 501 if (null != this.sourceResolver) { 502 super.release(this.sourceResolver); 503 } 508 509 super.dispose(); 510 511 this.sourceResolver = null; 514 515 this.wasDisposed = true; 517 } 518 519 522 public Source resolveURI(final String location) 523 throws MalformedURLException , IOException , SourceException { 524 return this.resolveURI(location, null, null); 525 } 526 527 530 public Source resolveURI(final String location, 531 String baseURI, 532 final Map parameters) 533 throws MalformedURLException , IOException , SourceException { 534 if (baseURI == null) { 535 final EnvironmentStack stack = (EnvironmentStack)environmentStack.get(); 536 if ( null != stack && !stack.isEmpty()) { 537 final EnvironmentStack.Item objects = stack.getCurrent(); 538 baseURI = objects.env.getContext(); 539 } 540 } 541 return this.sourceResolver.resolveURI(location, baseURI, parameters); 542 } 543 544 547 public void release(final Source source) { 548 this.sourceResolver.release(source); 549 } 550 551 552 555 public void addComponent(String role, Class clazz, Configuration conf) 556 throws ComponentException { 557 super.addComponent(role, clazz, conf); 558 if (ParentAware.class.isAssignableFrom(clazz)) { 561 parentAwareComponents.add(role); 562 } 563 } 564 565 public void initialize() throws Exception { 566 super.initialize(); 567 if (parentAwareComponents == null) { 568 throw new ComponentException(null, "CocoonComponentManager already initialized"); 569 } 570 Iterator iter = parentAwareComponents.iterator(); 572 while (iter.hasNext()) { 573 String role = (String )iter.next(); 574 getLogger().debug(".. "+role); 575 if ( parentManager != null && parentManager.hasComponent( role ) ) { 576 Component component = null; 578 try { 579 component = this.lookup( role ); 580 ((ParentAware)component).setParentLocator( new ComponentLocatorImpl(this.parentManager, role )); 581 } catch (ComponentException ignore) { 582 } finally { 584 this.release( component ); 585 } 586 } 587 } 588 parentAwareComponents = null; } 590 591 598 public static abstract class AbstractCocoonRunnable implements Runnable { 599 private Object parentStack = null; 600 601 public AbstractCocoonRunnable() { 602 Object stack = CocoonComponentManager.environmentStack.get(); 605 if (stack != null) { 606 this.parentStack = ((EnvironmentStack)stack).clone(); 607 } 608 } 609 610 613 public final void run() { 614 Object oldStack = environmentStack.get(); 616 CocoonComponentManager.environmentStack.set(this.parentStack); 617 try { 618 doRun(); 619 } finally { 620 CocoonComponentManager.environmentStack.set(oldStack); 622 } 623 } 627 628 abstract protected void doRun(); 629 } 630 } 631 632 final class EnvironmentDescription { 633 634 Environment environment; 635 Map objectModel; 636 Map requestLifecycleComponents; 637 List autoreleaseComponents = new ArrayList (4); 638 639 642 EnvironmentDescription(Environment env) { 643 this.environment = env; 644 this.objectModel = env.getObjectModel(); 645 } 646 647 Map getGlobalRequestLifcecycleComponents() { 648 Map m = (Map )environment.getAttribute(GlobalRequestLifecycleComponent.class.getName()); 649 if ( m == null ) { 650 m = new HashMap (); 651 environment.setAttribute(GlobalRequestLifecycleComponent.class.getName(), m); 652 } 653 return m; 654 } 655 656 661 synchronized void release() { 662 if ( this.requestLifecycleComponents != null ) { 663 final Iterator iter = this.requestLifecycleComponents.values().iterator(); 664 while (iter.hasNext()) { 665 final Object [] o = (Object [])iter.next(); 666 final Component component = (Component)o[0]; 667 ((CocoonComponentManager)o[1]).releaseRLComponent( component ); 668 } 669 this.requestLifecycleComponents.clear(); 670 } 671 672 for (int i = 0; i < autoreleaseComponents.size(); i++) { 673 final Object [] o = (Object [])autoreleaseComponents.get(i); 674 final Component component = (Component)o[0]; 675 if (o[1] instanceof ComponentManager) { 676 ((ComponentManager)o[1]).release( component ); 677 } else { 678 ((ComponentSelector) o[1]).release(component); 679 if (o[2] != null) { 680 ((ComponentManager) o[2]).release((Component) o[1]); 681 } 682 } 683 } 684 this.autoreleaseComponents.clear(); 685 this.environment = null; 686 this.objectModel = null; 687 } 688 689 692 void addRequestLifecycleComponent(final String role, 693 final Component co, 694 final ComponentManager manager) { 695 if ( this.requestLifecycleComponents == null ) { 696 this.requestLifecycleComponents = new HashMap (); 697 } 698 this.requestLifecycleComponents.put(role, new Object [] {co, manager}); 699 } 700 701 704 void addGlobalRequestLifecycleComponent(final String role, 705 final Component co, 706 final ComponentManager manager) { 707 this.getGlobalRequestLifcecycleComponents().put(role, new Object [] {co, manager}); 708 } 709 710 713 boolean containsRequestLifecycleComponent(final String role) { 714 if ( this.requestLifecycleComponents == null ) { 715 return false; 716 } 717 return this.requestLifecycleComponents.containsKey( role ); 718 } 719 720 723 boolean containsGlobalRequestLifecycleComponent(final String role) { 724 return this.getGlobalRequestLifcecycleComponents().containsKey( role ); 725 } 726 727 730 Component getRequestLifecycleComponent(final String role) { 731 if ( this.requestLifecycleComponents == null ) { 732 return null; 733 } 734 final Object [] o = (Object [])this.requestLifecycleComponents.get(role); 735 if ( null != o ) { 736 return (Component)o[0]; 737 } 738 return null; 739 } 740 741 744 Component getGlobalRequestLifecycleComponent(final String role) { 745 final Object [] o = (Object [])this.getGlobalRequestLifcecycleComponents().get(role); 746 if ( null != o ) { 747 return (Component)o[0]; 748 } 749 return null; 750 } 751 752 755 synchronized void addToAutoRelease(final ComponentSelector selector, 756 final Component component, 757 final ComponentManager manager) { 758 this.autoreleaseComponents.add(new Object [] {component, selector, manager}); 759 } 760 761 764 synchronized void addToAutoRelease(final ComponentManager manager, 765 final Component component) { 766 this.autoreleaseComponents.add(new Object [] {component, manager}); 767 } 768 769 772 synchronized void removeFromAutoRelease(final Component component) 773 throws ProcessingException { 774 int i = 0; 775 boolean found = false; 776 while (i < this.autoreleaseComponents.size() && !found) { 777 final Object [] o = (Object [])this.autoreleaseComponents.get(i); 778 if (o[0] == component) { 779 found = true; 780 if (o[1] instanceof ComponentManager) { 781 ((ComponentManager)o[1]).release( component ); 782 } else { 783 ((ComponentSelector)o[1]).release( component ); 784 if (o[2] != null) { 785 ((ComponentManager)o[2]).release( (Component)o[1] ); 786 } 787 } 788 this.autoreleaseComponents.remove(i); 789 } else { 790 i++; 791 } 792 } 793 if (!found) { 794 throw new ProcessingException("Unable to remove component from automatic release: component not found."); 795 } 796 } 797 } 798 | Popular Tags |