1 17 18 package org.apache.avalon.fortress.impl; 19 20 import org.apache.avalon.excalibur.logger.LoggerManager; 21 import org.apache.avalon.fortress.Container; 22 import org.apache.avalon.fortress.MetaInfoEntry; 23 import org.apache.avalon.fortress.MetaInfoManager; 24 import org.apache.avalon.fortress.impl.extensions.InstrumentableCreator; 25 import org.apache.avalon.fortress.impl.factory.ProxyManager; 26 import org.apache.avalon.fortress.impl.handler.ComponentFactory; 27 import org.apache.avalon.fortress.impl.handler.ComponentHandler; 28 import org.apache.avalon.fortress.impl.handler.LEAwareComponentHandler; 29 import org.apache.avalon.fortress.impl.handler.PrepareHandlerCommand; 30 import org.apache.avalon.fortress.impl.lookup.FortressServiceManager; 31 import org.apache.avalon.fortress.impl.lookup.FortressServiceSelector; 32 import org.apache.avalon.fortress.util.CompositeException; 33 import org.apache.avalon.fortress.util.LifecycleExtensionManager; 34 import org.apache.avalon.fortress.util.dag.CyclicDependencyException; 35 import org.apache.avalon.fortress.util.dag.DirectedAcyclicGraphVerifier; 36 import org.apache.avalon.fortress.util.dag.Vertex; 37 import org.apache.avalon.framework.CascadingException; 38 import org.apache.avalon.framework.activity.Disposable; 39 import org.apache.avalon.framework.activity.Initializable; 40 import org.apache.avalon.framework.configuration.Configuration; 41 import org.apache.avalon.framework.container.ContainerUtil; 42 import org.apache.avalon.framework.context.Context; 43 import org.apache.avalon.framework.context.ContextException; 44 import org.apache.avalon.framework.context.Contextualizable; 45 import org.apache.avalon.framework.logger.AbstractLogEnabled; 46 import org.apache.avalon.framework.logger.Logger; 47 import org.apache.avalon.framework.service.DefaultServiceManager; 48 import org.apache.avalon.framework.service.ServiceException; 49 import org.apache.avalon.framework.service.ServiceManager; 50 import org.apache.avalon.framework.service.Serviceable; 51 import org.apache.commons.collections.BoundedFifoBuffer; 52 import org.apache.commons.collections.StaticBucketMap; 53 import org.apache.excalibur.event.Sink; 54 import org.apache.excalibur.instrument.InstrumentManager; 55 import org.apache.excalibur.instrument.Instrumentable; 56 import org.apache.excalibur.mpool.ObjectFactory; 57 import org.apache.excalibur.mpool.PoolManager; 58 59 import java.util.*; 60 61 70 public abstract class AbstractContainer 71 extends AbstractLogEnabled 72 implements Contextualizable, Serviceable, Initializable, Disposable, Container 73 { 74 75 public static final String DEFAULT_ENTRY = "*"; 76 77 public static final String SELECTOR_ENTRY = "$"; 78 79 80 protected Context m_context; 81 82 protected ServiceManager m_serviceManager; 83 84 protected LoggerManager m_loggerManager; 85 86 protected PoolManager m_poolManager; 87 88 protected Sink m_commandSink; 89 90 protected ClassLoader m_classLoader; 91 92 protected MetaInfoManager m_metaManager; 93 94 protected InstrumentManager m_instrumentManager; 95 96 protected LifecycleExtensionManager m_extManager; 97 102 protected Context m_componentContext; 103 107 protected Map m_mapper = new StaticBucketMap(); 108 109 protected List m_components = new ArrayList( 10 ); 110 111 protected List m_shutDownOrder; 112 113 private ProxyManager m_proxyManager; 114 115 120 protected void setProxyManager( ProxyManager proxyManager ) 121 { 122 if ( null == proxyManager ) throw new NullPointerException ("proxyManager"); 123 if ( null != m_proxyManager ) throw new IllegalStateException ("Can not double-assign the ProxyManager"); 124 m_proxyManager = proxyManager; 125 } 126 127 134 protected ProxyManager getProxyManager() throws Exception 135 { 136 if ( null == m_proxyManager ) 137 { 138 m_proxyManager = new ProxyManager( ProxyManager.DISCOVER ); 139 } 140 141 return m_proxyManager; 142 } 143 144 153 public void contextualize( final Context context ) 154 throws ContextException 155 { 156 m_context = context; 157 try 158 { 159 m_classLoader = (ClassLoader ) context.get( ClassLoader .class.getName() ); 160 } 161 catch ( ContextException ce ) 162 { 163 m_classLoader = Thread.currentThread().getContextClassLoader(); 164 } 165 } 166 167 182 public void service( final ServiceManager serviceManager ) 183 throws ServiceException 184 { 185 187 m_loggerManager = (LoggerManager) serviceManager.lookup( LoggerManager.ROLE ); 188 m_poolManager = (PoolManager) serviceManager.lookup( PoolManager.ROLE ); 189 m_instrumentManager = (InstrumentManager) serviceManager.lookup( InstrumentManager.ROLE ); 190 191 193 setupExtensionManager( serviceManager ); 194 195 if ( serviceManager.hasService( Sink.ROLE ) ) 196 { 197 m_commandSink = (Sink) serviceManager.lookup( Sink.ROLE ); 198 } 199 else 200 { 201 final String message = 202 "No " + Sink.ROLE + " is given, all " + 203 "management will be performed synchronously"; 204 getLogger().warn( message ); 205 } 206 207 m_metaManager = (MetaInfoManager) serviceManager.lookup( MetaInfoManager.ROLE ); 208 209 m_serviceManager = provideServiceManager( serviceManager ); 211 } 212 213 219 private void setupExtensionManager( final ServiceManager serviceManager ) throws ServiceException 220 { 221 final Logger extLogger = m_loggerManager.getLoggerForCategory( "system.extensions" ); 222 223 if ( serviceManager.hasService( LifecycleExtensionManager.ROLE ) ) 224 { 225 final LifecycleExtensionManager parent = (LifecycleExtensionManager) 226 serviceManager.lookup( LifecycleExtensionManager.ROLE ); 227 228 if ( extLogger.isDebugEnabled() ) 229 { 230 final String message = "Found the LifecycleExtensionManager, creating a copy."; 231 extLogger.debug( message ); 232 } 233 234 m_extManager = parent.writeableCopy(); 235 } 236 else 237 { 238 if ( extLogger.isDebugEnabled() ) 239 { 240 final String message = "No LifecycleExtensionManager found, creating a new one."; 241 extLogger.debug( message ); 242 } 243 244 m_extManager = new LifecycleExtensionManager(); 245 } 246 247 248 m_extManager.enableLogging( extLogger ); 249 250 if ( extLogger.isDebugEnabled() ) 251 { 252 final String message = 253 "Adding an InstrumentableCreator to support our InstrumentManager"; 254 extLogger.debug( message ); 255 } 256 257 265 m_extManager.addCreatorExtension( new InstrumentableCreator( m_instrumentManager ) ); 266 } 267 268 277 protected void addComponent( final ComponentHandlerMetaData metaData ) 278 throws IllegalArgumentException , Exception 279 { 280 final String classname = metaData.getClassname(); 282 final MetaInfoEntry metaEntry = m_metaManager.getMetaInfoForClassname( classname ); 283 if ( null == metaEntry ) 284 { 285 final String message = "No role defined for " + classname; 286 throw new IllegalArgumentException ( message ); 287 } 288 289 if ( DEFAULT_ENTRY.equals( metaData.getName() ) || 290 SELECTOR_ENTRY.equals( metaData.getName() ) ) 291 { 292 throw new IllegalArgumentException ( "Using a reserved id name" + metaData.getName() ); 293 } 294 295 Iterator it = metaEntry.getRoles(); 296 final ComponentHandler handler = 298 getComponentHandler( metaEntry, metaData ); 299 300 while ( it.hasNext() ) 301 { 302 final String role = (String ) it.next(); 303 304 if ( null != role && null != classname && null != handler ) 308 { 309 Map hintMap = (Map) m_mapper.get( role ); 310 311 if ( null == hintMap ) 313 { 314 hintMap = createHintMap(); 315 hintMap.put( DEFAULT_ENTRY, handler ); 316 hintMap.put( SELECTOR_ENTRY, 317 new FortressServiceSelector( this, role ) ); 318 m_mapper.put( role, hintMap ); 319 } 320 321 hintMap.put( metaData.getName(), handler ); 322 323 if ( metaData.getConfiguration().getAttributeAsBoolean( "default", false ) ) 324 { 325 hintMap.put( DEFAULT_ENTRY, handler ); 326 } 327 } 328 } 329 } 330 331 339 private ComponentHandler getComponentHandler( final MetaInfoEntry metaEntry, 340 final ComponentHandlerMetaData metaData ) 341 throws Exception 342 { 343 final ComponentHandler handler; 345 final String classname = metaEntry.getComponentClass().getName(); 346 final Configuration configuration = metaData.getConfiguration(); 347 348 try 349 { 350 final ObjectFactory factory = 351 createObjectFactory( classname, configuration ); 352 353 final ComponentHandler targetHandler = 355 (ComponentHandler) metaEntry.getHandlerClass().newInstance(); 356 357 ContainerUtil.enableLogging( targetHandler, getLogger() ); 359 ContainerUtil.contextualize( targetHandler, m_context ); 360 final DefaultServiceManager serviceManager = 361 new DefaultServiceManager( getServiceManager() ); 362 serviceManager.put( ObjectFactory.ROLE, factory ); 363 serviceManager.makeReadOnly(); 364 365 ContainerUtil.service( targetHandler, serviceManager ); 366 ContainerUtil.configure( targetHandler, configuration ); 367 ContainerUtil.initialize( targetHandler ); 368 369 if ( targetHandler instanceof Instrumentable ) 370 { 371 final Instrumentable instrumentable = (Instrumentable) targetHandler; 372 final String name = instrumentable.getInstrumentableName(); 373 m_instrumentManager.registerInstrumentable( instrumentable, name ); 374 } 375 376 379 handler = 380 new LEAwareComponentHandler( targetHandler, m_extManager, m_context ); 381 } 382 catch ( final Exception e ) 383 { 384 if ( getLogger().isDebugEnabled() ) 388 { 389 final String message = 390 "Could not create the handler for the '" + 391 classname + "' component."; 392 getLogger().debug( message, e ); 393 } 394 throw e; 395 } 396 397 if ( getLogger().isDebugEnabled() ) 398 { 399 final String message = 400 "Component " + classname + 401 " uses handler " + metaEntry.getHandlerClass().getName(); 402 getLogger().debug( message ); 403 } 404 405 final ComponentHandlerEntry entry = 408 new ComponentHandlerEntry( handler, metaData ); 409 m_components.add( entry ); 410 411 return handler; 412 } 413 414 422 protected ObjectFactory createObjectFactory( final String classname, 423 final Configuration configuration ) 424 throws Exception 425 { 426 if ( m_componentContext == null ) 427 { 428 m_componentContext = provideComponentContext( m_context ); 429 if ( m_componentContext == null ) 430 { 431 throw new IllegalStateException ( "provideComponentContext() has returned null" ); 432 } 433 } 434 435 final Class clazz = m_classLoader.loadClass( classname ); 436 final ComponentFactory componentFactory = 437 new ComponentFactory( clazz, configuration, 438 m_serviceManager, m_componentContext, 439 m_loggerManager, m_extManager ); 440 return getProxyManager().getWrappedObjectFactory( componentFactory ); 441 } 442 443 455 public Object get( final String role, final Object hint ) 456 throws ServiceException 457 { 458 final Map hintMap = (Map) m_mapper.get( role ); 459 Object value; 460 461 if ( null == hintMap ) 462 { 463 final String key = getRoleKey( role, hint ); 464 final String message = "Component does not exist"; 465 throw new ServiceException( key, message ); 466 } 467 468 if ( null == hint ) 469 { 470 value = hintMap.get( SELECTOR_ENTRY ); 472 473 if ( null == value ) 474 { 475 value = hintMap.get( DEFAULT_ENTRY ); 477 } 478 479 return value; 480 } 481 482 value = hintMap.get( hint ); 484 485 if ( null == value ) 486 { 487 final String key = getRoleKey( role, hint ); 488 final String message = "Component does not exist"; 489 throw new ServiceException( key, message ); 490 } 491 492 return value; 493 } 494 495 510 protected Map createHintMap() 511 { 512 return new StaticBucketMap(); 513 } 514 515 525 protected static String getRoleKey( final String role, final Object hint ) 526 { 527 return role + "/" + hint; 528 } 529 530 541 public boolean has( final String role, final Object hint ) 542 { 543 final Map hintMap = (Map) m_mapper.get( role ); 544 boolean hasComponent = false; 545 546 if ( null != hintMap ) 547 { 548 hasComponent = true; 549 } 550 551 if ( hasComponent ) 552 { 553 if ( null == hint ) 554 { 555 hasComponent = hintMap.containsKey( SELECTOR_ENTRY ); 557 558 if ( !hasComponent ) 559 { 560 hasComponent = hintMap.containsKey( DEFAULT_ENTRY ); 562 } 563 } 564 else 565 { 566 hasComponent = hintMap.containsKey( hint ); 568 } 569 } 570 571 return hasComponent; 572 } 573 574 582 public void initialize() 583 throws CompositeException, Exception 584 { 585 final Iterator i = m_components.iterator(); 587 final BoundedFifoBuffer buffer = new BoundedFifoBuffer( Math.max( m_components.size(), 1 ) ); 588 589 m_extManager.makeReadOnly(); 591 592 verifyComponents(); 593 594 ComponentHandlerEntry entry; 595 while ( i.hasNext() ) 596 { 597 entry = (ComponentHandlerEntry) i.next(); 598 try 599 { 600 final ComponentHandler handler = entry.getHandler(); 601 602 int activation = entry.getMetaData().getActivation(); 606 if ( activation == ComponentHandlerMetaData.ACTIVATION_BACKGROUND ) 607 { 608 if ( null == m_commandSink ) 610 { 611 activation = ComponentHandlerMetaData.ACTIVATION_INLINE; 612 } 613 } 614 615 switch ( activation ) 617 { 618 case ComponentHandlerMetaData.ACTIVATION_BACKGROUND: 619 final PrepareHandlerCommand element = 623 new PrepareHandlerCommand( handler, getLogger() ); 624 m_commandSink.enqueue( element ); 625 break; 626 627 case ComponentHandlerMetaData.ACTIVATION_INLINE: 628 handler.prepareHandler(); 630 break; 631 632 default: if ( getLogger().isDebugEnabled() ) 634 { 635 final String message = "ComponentHandler (" + handler + 636 ") has specified a lazy activation policy, " + 637 "initialization deferred until first use"; 638 getLogger().debug( message ); 639 } 640 break; 641 } 642 } 643 catch ( final CascadingException e ) 644 { 645 final String cName = entry.getMetaData().getName(); 646 647 if ( getLogger().isWarnEnabled() ) 648 { 649 final String message = "Could not initialize component " + cName; 650 getLogger().warn( message, e ); 651 652 final String cause = "Cause for exception"; 653 getLogger().warn( cause, e.getCause() ); 654 } 655 buffer.add( e ); 656 } 657 catch ( final Exception e ) 658 { 659 final String cName = entry.getMetaData().getName(); 660 661 if ( getLogger().isWarnEnabled() ) 662 { 663 final String message = "Could not initialize component " + cName; 664 getLogger().warn( message, e ); 665 } 666 buffer.add( e ); 667 } 668 catch ( final LinkageError le ) 669 { 670 final String cName = entry.getMetaData().getName(); 671 672 if ( getLogger().isWarnEnabled() ) 673 { 674 final String message = "Could not initialize component " + cName; 675 getLogger().warn( message, le ); 676 } 677 buffer.add( le ); 678 } 679 } 680 681 if ( buffer.size() > 0 ) 684 { 685 throw new CompositeException( (Exception []) buffer.toArray( new Exception [0] ), 686 "unable to instantiate one or more components" ); 687 } 688 } 689 690 private void verifyComponents() throws CyclicDependencyException 691 { 692 Map vertexMap = new HashMap(); 693 List vertices = new ArrayList( m_components.size() ); 694 Iterator it = m_components.iterator(); 695 696 while ( it.hasNext() ) 697 { 698 ComponentHandlerEntry entry = (ComponentHandlerEntry) it.next(); 699 ComponentHandlerMetaData metaData = entry.getMetaData(); 700 701 String name = metaData.getName(); 702 Vertex v = (Vertex) vertexMap.get( name ); 703 if ( v == null ) 704 { 705 v = new Vertex( name, entry.getHandler() ); 706 vertexMap.put( name, v ); 707 vertices.add( v ); 708 } 709 710 MetaInfoEntry meta = m_metaManager.getMetaInfoForClassname( metaData.getClassname() ); 711 712 Iterator dit = meta.getDependencies().iterator(); 713 while ( dit.hasNext() ) 714 { 715 Map deps = (Map) m_mapper.get( dit.next() ); 716 717 721 if ( null == deps ) continue; 722 723 Iterator mdit = deps.entrySet().iterator(); 724 while ( mdit.hasNext() ) 725 { 726 Map.Entry depEntry = (Map.Entry) mdit.next(); 727 728 if ( !( depEntry.getKey().equals( DEFAULT_ENTRY ) || 731 depEntry.getKey().equals( SELECTOR_ENTRY ) ) ) 732 { 733 String dName = depEntry.getKey().toString(); 734 Vertex dv = (Vertex) vertexMap.get( dName ); 735 if ( dv == null ) 736 { 737 dv = new Vertex( dName, depEntry.getValue() ); 738 vertexMap.put( dName, dv ); 739 vertices.add( dv ); 740 } 741 v.addDependency( dv ); 742 } 743 } 744 } 745 } 746 747 DirectedAcyclicGraphVerifier.topologicalSort( vertices ); 748 749 if ( getLogger().isDebugEnabled() ) 750 { 751 getLogger().debug( "Component initialization order:" ); 752 int i = 1; 753 for ( Iterator iter = vertices.iterator(); iter.hasNext(); i++ ) 754 { 755 Vertex v = (Vertex) iter.next(); 756 getLogger().debug( " #" + i + " (" + v.getOrder() + ") : " + v.getName() ); 757 } 758 } 759 760 Collections.reverse( vertices ); 761 762 m_shutDownOrder = vertices; 763 } 764 765 768 public void dispose() 769 { 770 771 if ( getLogger().isDebugEnabled() ) 772 { 773 getLogger().debug( "Component shutdown order:" ); 774 int i = 1; 775 for ( Iterator iter = m_shutDownOrder.iterator(); iter.hasNext(); i++ ) 776 { 777 Vertex v = (Vertex) iter.next(); 778 getLogger().debug( " #" + i + " (" + v.getOrder() + ") : " + v.getName() ); 779 } 780 } 781 782 final Iterator i = m_shutDownOrder.iterator(); 783 while ( i.hasNext() ) 784 { 785 final Vertex entry = (Vertex) i.next(); 786 final ComponentHandler handler = (ComponentHandler) entry.getNode(); 787 788 if ( getLogger().isDebugEnabled() ) getLogger().debug( "Shutting down: " + handler ); 789 ContainerUtil.dispose( handler ); 790 if ( getLogger().isDebugEnabled() ) getLogger().debug( "Done." ); 791 } 792 } 793 794 803 protected ServiceManager getServiceManager() 804 { 805 return m_serviceManager; 806 } 807 808 827 protected ServiceManager provideServiceManager( final ServiceManager parent ) 828 throws ServiceException 829 { 830 return new FortressServiceManager( this, parent ); 831 } 832 833 840 protected Context provideComponentContext( final Context parent ) 841 throws Exception 842 { 843 844 return parent; 845 } 846 } 847 | Popular Tags |