FileDocCategorySizeDatePackage
ApplicationServer.javaAPI DocGlassfish v2 API25306Wed Jun 06 03:47:24 BST 2007com.sun.enterprise.server

ApplicationServer

public class ApplicationServer extends Object
ApplicationServer is the main entry point for iAS 7.0 J2EE server instance. This code implements the server lifecycle state transitions and it relies on various iAS 7.0 subsystems such as Web/EJB containers throught its lifecycle. com.sun.enterprise.J2EEServer is the RI counerpart of this code; the evolving iAS server implementation replaces functionality of RI J2EEServer. NOTES on services by name: Default services implementing lifecycle interface for orderly startup shutdown and hot deployment. Each service entry is of the form {name, className}. Note: Make sure LifecycleModuleService is the last subsystem in this list.

Fields Summary
protected static final Logger
_logger
server logger
private static ServerContext
context
ServerContext -- server-wide runtime environment context
private final List
services
services -- standard runtime service objects
private ClassLoader
commonClassLoader
common class loader for the server
private ClassLoader
connectorClassLoader
share class loader for the server
private static final int
CLASSNAME_IDX
Index into String[] of the classname for a ServerLifecycle.
private static final RunnableBase.HowToRun
HOW_TO_RUN
Changing to RUN_IN_SEPARATE_THREAD achieves some efficiences at startup, but leaving it as 'RUN_IN_CURRENT_THREAD' until time allows testing.
Constructors Summary
public ApplicationServer()
Default constructor.


            
      
Methods Summary
public static ServerContextgetServerContext()
Get the server runtime context; returns a valid context only after initialization; a null otherwise.

return
a server runtime context or null if not initialized

        return context;
    
protected static final com.sun.appserv.server.ServerLifecycleinstantiateOneServerLifecycle(ServerContext serverContext, java.lang.String classname)

        //final TimingDelta delta = new TimingDelta();
        
        final Class c  = Class.forName( classname );
       
        ServerLifecycle item = null;

        // call a constructor that takes a ServerContext if it exists, since
        // some services might make efficient use of it during construction.
        // otherwise use a no-argument constructor
        try {
            final Constructor constructor = c.getConstructor( ServerContext.class );
            item   = (ServerLifecycle)constructor.newInstance( serverContext );
        }
        catch( Exception e ) {
            item = (ServerLifecycle)c.newInstance();
        }

        //System.out.println( "Instantiate " + classname + ": " + delta.elapsedMillis() );
        return item;
    
protected java.util.ListinstantiateRuntimeServices(ServerContext serverContext, java.lang.String[][] servicesByName)

    
         
    
          
                 
        final List<String>  classnames  = new ArrayList<String>();
        
        for (int i=0; i < servicesByName.length; i++) {
                final String[] serviceInfo = servicesByName[i];
                final String classname = serviceInfo[ CLASSNAME_IDX ];
                classnames.add( classname );
        }
        
        return instantiateRuntimeServices( serverContext, classnames );
    
protected java.util.ListinstantiateRuntimeServices(ServerContext serverContext, java.util.List classnames)
Go through the list of built-in runtime services and instantiate them.

    
                     
         
    
          
            
          
        final Instantiator[]    instantiators = new Instantiator[ classnames.size() ];
        
        // Instantiate service objects 
        int idx = 0;
        for ( final String classname : classnames ) {
            instantiators[idx]    = new Instantiator( serverContext, classname );
            instantiators[idx].submit( );
            ++idx;
        }
        
        // collect the resulting ServerLifecycle 
        final List<ServerLifecycle> serviceList = new ArrayList<ServerLifecycle>();
        for ( int i = 0; i < instantiators.length; ++i ) {
            serviceList.add( instantiators[i].getService() );
        }

        return serviceList;
    
private voidlogCommonClassLoaderDetails()

    	Logger _log = LogDomains.getLogger(LogDomains.LOADER_LOGGER);
    	if (_log.isLoggable( Level.FINE ) ) {
            if (commonClassLoader instanceof URLClassLoader) {
            	URL[] u = ((URLClassLoader)commonClassLoader).getURLs();
                StringBuffer sbuf = new StringBuffer();
                for (int i = 0; i < u.length; i++) {
                	sbuf.append(u[i].toExternalForm() + " ,");
				}
                
            	_log.log(Level.FINE, "Common classloader contents: [ " + sbuf.toString() + " ].") ;
            }
    	}
	
public voidonInitialization(ServerContext context)
Server is initializing subsystems and setting up the runtime environment. Prepare for the beginning of active use of the public methods of this subsystem. This method is called before any of the public methods of this subsystem are utilized.

param
context ServerContext the server runtime context.
exception
IllegalStateException if this subsystem has already been started
exception
ServerLifecycleException if this subsystem detects a fatal error that prevents this subsystem from being used

        
        // sets the server context
        this.context = context;

        // NOTE: side effects of reInitializeServerLoggers invoke various MBean related code
        // that really ought not to run yet, and that code hits synchronized code being relied
        // upon (indirectly via a Logger).  The thread initializing the MBeanServer (see PEMain)
        // will try to acquire that same synchronized lock and then hang.
        // See CR6555027.
        com.sun.enterprise.util.FeatureAvailability.getInstance().waitForMBeanServer();
        
        // initialize all server loggers that were not initialized
        // Note: reInitializeServerLoggers should be called after 
        //       setting the server context and before performing any
        //       other server startup activities that needs a logger

        ServerLogManager.reInitializeServerLoggers();
        
        // print jvm info
        printStartupInfo();

        // system class loader 
        ClassLoader parentOfCommonCL = this.getClass().getClassLoader();
        //Shared CL
        //In the new CL hierarchy the parent of common classloader
        //is the shared chain.
        if(Boolean.getBoolean(com.sun.enterprise.server.PELaunch.USE_NEW_CLASSLOADER_PROPERTY))
            parentOfCommonCL = PELaunch.getSharedChain();

        final InstanceEnvironment env = this.context.getInstanceEnvironment();

        try {
            final String dir     =  env.getLibClassesPath();
            final String jarDir  = env.getLibPath();

            // constructs the common class loader. System class loader 
            // is the parent of common class loader. Common class loader 
            // includes <instance>/lib/classes dir, <instance>/lib/*.jar 
            // and <instance>/lib/*.zip
            commonClassLoader = 
                ClassLoaderUtils.getClassLoader(new File[] {new File(dir)}, 
                                                new File[] {new File(jarDir)},
                                                parentOfCommonCL
                                                );
            logCommonClassLoaderDetails();
            

            // ignore if null
            if (commonClassLoader == null) {
                commonClassLoader = parentOfCommonCL;
            }
        } catch (IOException ioe) {
            _logger.log(Level.WARNING, "server.ioexception", ioe);
            commonClassLoader = parentOfCommonCL;
        } catch (Throwable th) {
            _logger.log(Level.WARNING, "server.exception", th);
            commonClassLoader = parentOfCommonCL;
        }

        // Create the connector class loader. This will be the parent class
        // loader for all j2ee components!! Common class loader is the 
        // parent of connector class loader.
        connectorClassLoader =
            ConnectorClassLoader.getInstance(commonClassLoader);
        
        // sets the class loaders in the server context
        if (this.context instanceof ServerContextImpl) {
            final ServerContextImpl contextImpl = (ServerContextImpl) this.context;

            // set the common classloader in the server context
            contextImpl.setCommonClassLoader(commonClassLoader);

            // sets the shared class loader
            contextImpl.setSharedClassLoader(connectorClassLoader);

            // sets the life cycle parent class loader
            contextImpl.setLifecycleParentClassLoader(connectorClassLoader);
        }

        // final common class loader for the anonymous inner class
        final ClassLoader commonCL = commonClassLoader;

        // 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(commonCL);
                    return null;
                }
            }
            );

	//added the pluggable interface way of getting the list of services
	final InternalServicesList servicesList = 
		context.getPluggableFeatureFactory().getInternalServicesList();

	final String[][] servicesByName = servicesList.getServicesByName();
	if (servicesByName == null) {
	      _logger.log(Level.SEVERE, "services.null");
	      throw new ServerLifecycleException();
	}

        // security manager is set inside SecurityLifecycle

	// Instantiate the built-in runtime services
        final List<ServerLifecycle> temp = instantiateRuntimeServices( context, servicesByName );
        services.addAll( temp );
	        
        // Initialize the built-in runtime services
        for ( final ServerLifecycle service : services) {
	        try {
                service.onInitialization(context);
            } catch (ServerLifecycleException e) {		   
                _logger.log(Level.SEVERE, "service.notinit", 
                    new Object[] {service, e.toString()});
                throw e;
            }
        }

        //add listeners for security dynamic reconfiguration
        AdminEventListenerRegistry.addAuditModuleEventListener(
                new AuditModuleEventListenerImpl());
        AdminEventListenerRegistry.addAuthRealmEventListener(
                new AuthRealmEventListenerImpl());
        AdminEventListenerRegistry.addSecurityServiceEventListener(
                new SecurityServiceEventListenerImpl());
        AdminEventListenerRegistry.addUserMgmtEventListener(
                new UserMgmtEventListenerImpl());
        AdminEventListenerRegistry.addEventListener(
                MessageSecurityConfigEvent.eventType,
                new MessageSecurityConfigEventListenerImpl());

            // Call RI J2EEServer initialization code. Note that all resources
            // specified in server.xml will be loaded by the common class loader.
        try {
            J2EEServer.main(context);
        } catch (Exception e) {
            throw new ServerLifecycleException(e);
        }

        // final connector class loader for the anonymous inner class
        final ClassLoader connCL = connectorClassLoader;

        // set the connector class loader as the thread context class loader
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction() {
                public Object run() {
                    Thread.currentThread().
                        setContextClassLoader(connCL);
                        return null;
                    }
                }
        );
    
public voidonReady()
Server has complted loading the applications and is ready to serve requests.

exception
ServerLifecycleException if this subsystem detects a fatal error that prevents this subsystem from being used


        try {
            // registers the resource manager as a listener for the 
            // resource deploy events
            AdminEventListenerRegistry.addResourceDeployEventListener(
                                              new ResourceManager(context));
            // registers listeners for JmsService and JmsHost changes.
            AdminEventListenerRegistry.addEventListener(JmsServiceEvent.eventType,
                                       new JmsServiceEventListener());
            AdminEventListenerRegistry.addEventListener(JmsHostEvent.eventType,
                                       new JmsHostEventListener());

            // Since onReady is called by a new thread, we have to again 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
                            (commonClassLoader);
                        return null;
                    }
                }
            );            
            
            /*
             * com.sun.enterprise.server.startupHook is an internal
             * undocumented property that can be used by iplanet developers
             * to invoke some custom code just after server startup happens.
             * Currently it is used by the ORB to easily benchmark and profile
             * the local invocation path of remote interfaces in the EJB
             * without having to deal with servlets or client/server processes
             * 
             * If the property com.sun.enterprise.server.startupHook is
             * defined then "main" in that class is executed
             * Note: This should always be the last piece of code executed
             *       in this method
             */
            String startupHook = null;

            startupHook = System.getProperty(
                              "com.sun.enterprise.server.startupHook");
            if (startupHook != null) {
                try {
                    // Call the custom startup hook specified
                    Class hookClass = Class.forName(startupHook);
                    java.lang.reflect.Method hookMethod =
                        hookClass.getMethod("main",
                                    new Class[] { ServerContext.class });
                    hookMethod.invoke(null, new Object[] { context });
                }
                catch (Exception ex) {
                    if (Debug.enabled) {
                          _logger.log(Level.FINE, "server.exception", ex);
                    }
                }
            }

        } catch (Exception ee) {
            throw new ServerLifecycleException(ee);
        }


        // notify the built-in runtime services that we are ready
        for ( final ServerLifecycle service : services) {
	        try {
                service.onReady(context);
            } catch (ServerLifecycleException e) {
              _logger.log(Level.SEVERE, "service.notready", 
                      new Object[] {service, e.toString()});
            }
        }
    
public voidonShutdown()
Server is shutting down applications

exception
ServerLifecycleException if this subsystem detects a fatal error that prevents this subsystem from being used

	
        // shutdown the built-in runtime services (in the reverse order).
        for (int i = services.size(); i > 0; i--) {
            final ServerLifecycle service = services.get(i-1);

	    _logger.log(Level.FINE,"service.shutdown", services.get(i-1));
            try {
                service.onShutdown();
            } catch (Exception e) {
            //do nothing since we want to continue shutting down other LFC
            //modules
                    _logger.log(Level.WARNING, "server.exception", e);	     
            }            
        }
    
public voidonStartup()
Server is starting up applications

param
context ServerContext the server runtime context.
exception
ServerLifecycleException if this subsystem detects a fatal error that prevents this subsystem from being used Note: Currently, with the J2EEServer code handles initialization and applications startup in one place J2EEServer.run() . XXX: This separation needs to be worked on to make it cleaner.

        // startup the built-in runtime services
        for ( final ServerLifecycle service : services) {
	        try {
                service.onStartup(context);
            } catch (ServerLifecycleException e) {		  
                _logger.log(Level.SEVERE, "service.notstarted", 
                    new Object[] {service, e.toString()});
                throw e;
            }
        }
        // _REVISIT_: Mover AlertConfigurator to configure after onReady()
        AlertConfigurator.getAlertConfigurator( ).configure( );
    
public voidonTermination()
Server is terminating the subsystems and the runtime environment. Gracefully terminate the active use of the public methods of this subsystem. This method should be the last one called on a given instance of this subsystem.

exception
ServerLifecycleException if this subsystem detects a fatal error that prevents this subsystem from being used

        //Kill all connections in the appserver's connection pools
	if (_logger.isLoggable( Level.FINE ) ) {
	    _logger.log(Level.FINE, "Killing all pools in the appserver");
	}
	try {
	    Switch.getSwitch().getPoolManager().killAllPools();
	} catch( Throwable t ) {
	    if (_logger.isLoggable( Level.FINE ) ) {
	        _logger.log(Level.FINE, "exception : " +t);
	    }
	}
 // terminate the built-in runtime services (in the reverse order)
        for (int i = services.size(); i > 0; i--) {
            final ServerLifecycle service = services.get(i-1);

	    _logger.log(Level.FINE,"service.shutdown",
					services.get(i-1));
	    try {
            service.onTermination();
	    } catch (Exception e) {
		//do nothing since we want to continue shutting down other LFC
		//modules
                _logger.log(Level.WARNING, "server.exception", e);	
	    }
        }

        services.clear();
    
private voidprintStartupInfo()

        _logger.log(Level.INFO, "j2eerunner.printstartinfo", 	
                        new Object[] {
                           System.getProperty("java.vm.name"), 
                           System.getProperty("java.version"), 
                           System.getProperty("java.vm.vendor") });
    
protected voidsetServerContext(ServerContext context)

        this.context = context;