FileDocCategorySizeDatePackage
LifecycleModuleService.javaAPI DocGlassfish v2 API19821Fri May 04 22:32:54 BST 2007com.sun.appserv.server

LifecycleModuleService

public final class LifecycleModuleService extends Object implements ServerLifecycle
Support class to assist in firing LifecycleEvent notifications to registered LifecycleListeners.

Fields Summary
private OneTimeIniter
mOneTimeIniter
private OneTimeStartup
mOneTimeStartup
private final com.sun.appserv.management.helper.AMXDebugHelper
mDebug
private static final String
SUBMIT_TYPE_SPROP
private static final String
SUBMIT_TYPE
private final List
mLifecycleModules
Not accessed concurrently, so no need to use a synchronized List.
Constructors Summary
public LifecycleModuleService()

    
Methods Summary
private voidcallAllModules(com.sun.enterprise.server.ServerContext serverContext, java.lang.String methodName)

        // save current ClassLoader
        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        
        final List<Set<ServerLifecycleModule>> sets = groupByLoadOrder( mLifecycleModules );
        
        for ( final Set<ServerLifecycleModule> itemsOfSameLoadOrder : sets ) {
            final int numModules = itemsOfSameLoadOrder.size();
            final ServerLifecycleModule[] modules = new ServerLifecycleModule[ numModules ];
            itemsOfSameLoadOrder.toArray( modules );
            
            final LifecycleModuleCaller[] callers = new LifecycleModuleCaller[ numModules ];
                
            for( int i = 0; i < numModules; ++ i ) {
                callers[ i ] = createCaller( serverContext, modules[ i ], methodName);
                
                // run the *last* one in *this* thread to save the overhead of a new thread
                // (common case might be just 1 or 2 items)
                final boolean isLast = (i + 1) == numModules;
                final HowToRun submitType = isLast ? RUN_IN_CURRENT_THREAD : getSubmitType();
                callers[ i ].submit( submitType );
            }
            
            // They're all submitted and running.  Wait until they're *all* done in order to maintain
            // the semantics of not loading any subsequent modules of a later load-order.
            for( int idx = 0; idx < callers.length; ++idx ) {
                callers[idx].waitDone();    // do not call waitDoneThrow(); we want to wait for all
                debug( "Millis for " + callers[idx].getName() + ": " + callers[idx].getNanosFromSubmit() / (1000*1000) );
            }
            // All modules have now finished
            
            // they're all done, for better or worse. Loop again, throw an exception if
            // any of them had one.
            for( int idx = 0; idx < callers.length; ++idx ) {
                callers[idx].waitDoneThrow();
            }
        }
        
        // restore ClassLoader, in case a module changed it
        resetClassLoader(cl);
    
private com.sun.appserv.server.LifecycleModuleService$LifecycleModuleCallercreateCaller(com.sun.enterprise.server.ServerContext serverContext, ServerLifecycleModule lifecycleModule, java.lang.String methodName)

        
        LifecycleModuleCaller caller = null;
        
        if ( methodName.equals( "onInitialization" ) ) {
            caller = new onInitializationCaller( serverContext, lifecycleModule );
        }
        else if ( methodName.equals( "onStartup" ) ) {
            caller = new onStartupCaller( serverContext, lifecycleModule );
        }
        else if ( methodName.equals( "onReady" ) ) {
            caller = new onReadyCaller( serverContext, lifecycleModule );
        }
        else {
            throw new IllegalArgumentException( methodName );
        }
            
        return caller;
    
private voiddebug(java.lang.Object args)

             mDebug.println( args ); 
private com.sun.appserv.management.util.misc.RunnableBase.HowToRungetSubmitType()

        HowToRun submitType = RUN_INVALID;
        
        if ( "async".equals( SUBMIT_TYPE ) ) {
            submitType = RUN_IN_SEPARATE_THREAD;
        }
        else if ( "sync".equals( SUBMIT_TYPE ) ) {
            submitType = RUN_IN_CURRENT_THREAD;
        }
        else {
            // default behavior
            // use multiple threads only if we have more than one CPU core
            submitType = isMultiCore() ? RUN_IN_SEPARATE_THREAD : RUN_IN_CURRENT_THREAD;
        }
        
        debug( "SUBMIT_TYPE: ", SUBMIT_TYPE, " => ", submitType );
        
        return submitType;
    
private java.util.ListgroupByLoadOrder(java.util.List lifecycleModules)
Return a List of Set where each item in the same Set has the same load order. The modules are assumed to be already sorted.

        final List<Set<ServerLifecycleModule>>  sets    = new ArrayList<Set<ServerLifecycleModule>>();
        int curOrder = Integer.MIN_VALUE;
        
        Set<ServerLifecycleModule> curSet = null;
        for( final ServerLifecycleModule next : lifecycleModules ) {
            final int order = next.getLoadOrder();
            // debug( "Load order for " + next.getName() + ": " + order );
            if ( order < curOrder ) {
                throw new IllegalStateException();
            }
            
            if ( curSet == null || curOrder != order )
            {
                curSet  =  new HashSet<ServerLifecycleModule>();
                sets.add( curSet );
            }
            curSet.add( next );
            curOrder = order;
        }
        
        return sets;
    
private voidinitialize(com.sun.enterprise.server.ServerContext serverContext)

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        
        callAllModules( serverContext, "onInitialization" );

        // set it back
        resetClassLoader(cl);
    
private booleanisEnabled(com.sun.enterprise.config.serverbeans.LifecycleModule lcm, com.sun.enterprise.config.ConfigContext config)
Returns true if life cycle module is enabled in the application level and in the application ref level.

param
lcm life cycle module
param
config config context
return
true if life cycle module is enabled

        try {
            // return false if arguments are null
            if (lcm == null || config == null) {
                return false;
            }

            // find the ref to the life cycle module
            final Server server = ServerBeansFactory.getServerBean(config);
            final ApplicationRef appRef=server.getApplicationRefByRef(lcm.getName());

            // true if enabled in both lifecyle module and in the ref
            return ((lcm.isEnabled()) && 
                        (appRef != null && appRef.isEnabled()));

        } catch (ConfigException e) {
            return false;
        }
    
private static booleanisMultiCore()

    
          
    
    
        // the javadoc advises checking this periodically
        return Runtime.getRuntime().availableProcessors() >= 2;
    
public voidonInitialization(com.sun.enterprise.server.ServerContext context)

        mOneTimeIniter = new OneTimeIniter( context );
                                        
        mOneTimeIniter.submit( getSubmitType() );
        // leave it running; we'll sync up with it in start()
    
public voidonReady(com.sun.enterprise.server.ServerContext serverContext)

        mOneTimeStartup.waitDoneThrow();
        mOneTimeStartup = null;
        // onReady() not yet done, do it now
        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        
        callAllModules( serverContext, "onReady" );
        
        resetClassLoader(cl);
        assert( mOneTimeStartup == null );
    
public voidonShutdown()

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for( final ServerLifecycleModule next : mLifecycleModules ) {
            next.onShutdown();
        }
        // set it back
        resetClassLoader(cl);
    
public voidonStartup(com.sun.enterprise.server.ServerContext context)

        //final TimingDelta delta    = new TimingDelta();
        
        // wait for initialization to finish
        mOneTimeIniter.waitDoneThrow();
        //debug( "Millis for OneTimeIniter to run: ", (mOneTimeIniter.getNanosFromSubmit() / (1000*1000)), ", wait time = ", delta.elapsedMillis() );
        mOneTimeIniter  = null;
        
        mOneTimeStartup = new OneTimeStartup( context );
        mOneTimeStartup.submit( getSubmitType() );
        // we'll sync up with this thread in onReady()
    
public voidonTermination()

        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        for( final ServerLifecycleModule next : mLifecycleModules ) {
            next.onTermination();
        }
        // set it back
        resetClassLoader(cl);
    
private voidresetClassLoader(java.lang.ClassLoader c)

         // set the common class loader as the thread context class loader
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction() {
                public Object run() {
                    Thread.currentThread().setContextClassLoader(c);
                    return null;
                }
            }
        );
    
private voidsortModules(java.util.Set listenerSet)

        // FIXME: use a better sorting algorithm, this one is O( N^2 )
        for( final ServerLifecycleModule next : listenerSet ) {
            final int order = next.getLoadOrder();
            
            int i = 0;
            for( ; i < this.mLifecycleModules.size(); i++) {
                if( mLifecycleModules.get(i).getLoadOrder() > order) {
                    break;
                }
            }
            
            mLifecycleModules.add(i,next);
        }