/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the license at * https://glassfish.dev.java.net/public/CDDLv1.0.html or * glassfish/bootstrap/legal/CDDLv1.0.txt. * See the License for the specific language governing * permissions and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at glassfish/bootstrap/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * you own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. */ package com.sun.appserv.server; import java.util.HashSet; import java.util.Set; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import com.sun.enterprise.deployment.WebBundleDescriptor; import com.sun.enterprise.deployment.Application; import com.sun.web.security.RealmAdapter; import org.apache.catalina.Context; import org.apache.catalina.core.StandardContext; import com.sun.enterprise.config.ConfigContext; import com.sun.enterprise.config.ConfigException; import com.sun.enterprise.config.serverbeans.ServerBeansFactory; import com.sun.enterprise.config.serverbeans.Server; import com.sun.enterprise.config.serverbeans.Applications; import com.sun.enterprise.config.serverbeans.ApplicationRef; import com.sun.enterprise.config.serverbeans.LifecycleModule; import com.sun.enterprise.config.serverbeans.ElementProperty; import com.sun.enterprise.server.ServerContext; import com.sun.appserv.management.util.misc.TimingDelta; import com.sun.appserv.management.util.misc.RunnableBase; import com.sun.appserv.management.helper.AMXDebugHelper; /** * Support class to assist in firing LifecycleEvent notifications to * registered LifecycleListeners. * * @author Sridatta Viswanath * @version $Id: LifecycleModuleService.java,v 1.7 2006/12/01 09:55:32 binod Exp $ */ public class LifecycleModuleService implements ServerLifecycle { private OneTimeIniter mOneTimeIniter; private OneTimeStartup mOneTimeStartup; private final AMXDebugHelper mDebug = new AMXDebugHelper( "LifecycleModuleService" ); private void debug( final Object...args ) { mDebug.println( args ); } /** * The set of registered LifecycleListeners for event notifications. */ private final List mLifecycleModules = new ArrayList(); private final class OneTimeIniter extends RunnableBase { private final ServerContext mServerContext; public OneTimeIniter( final ServerContext serverContext ) { mServerContext = serverContext; } protected void doRun() throws ConfigException, ServerLifecycleException { //ROB: config changes //Applications apps = //ServerBeansFactory.getServerBean(mServerContext.getConfigContext()).getApplications(); final Applications apps = ServerBeansFactory.getApplicationsBean(mServerContext.getConfigContext()); if (apps == null) return; final LifecycleModule[] lcms = apps.getLifecycleModule(); if(lcms == null) return; final Set listenerSet = new HashSet(); for(int i=0;i 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); } } private void initialize( final ServerContext context) throws ServerLifecycleException { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); for( final ServerLifecycleModule next : mLifecycleModules ) { next.onInitialization(context); } // set it back resetClassLoader(cl); } public LifecycleModuleService() { } public synchronized void onInitialization( final ServerContext context) throws ServerLifecycleException { mOneTimeIniter = new OneTimeIniter( context ); mOneTimeIniter.submit( RunnableBase.SUBMIT_ASYNC ); // leave it running; we'll sync up with it in start() } /** * 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 */ private boolean isEnabled(LifecycleModule lcm, ConfigContext config) { 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 void resetClassLoader(final 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; } } ); } /** Note that both the onStartup() and onReady() phases are performed (in sequence) by this thread. */ private final class OneTimeStartup extends RunnableBase { private final ServerContext mServerContext; public OneTimeStartup( final ServerContext serverContext ) { mServerContext = serverContext; } protected void doRun() throws ServerLifecycleException { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); for( final ServerLifecycleModule next : mLifecycleModules ) { // the SERVLET invocation context so J2EE invocations from // lifecycle modules get a legal ComponentInvocation. // create an invocation context that is of the type // SERVLET_INVOCATION final Context invocationContext = new StandardContext(); final WebBundleDescriptor wbd = new WebBundleDescriptor(); Application.createApplication(next.getName(), wbd.getModuleDescriptor()); invocationContext.setRealm(new RealmAdapter(wbd, false)); next.onStartup( mServerContext, invocationContext); } // set it back resetClassLoader(cl); // do the onReady() phase now instead of waiting for( final ServerLifecycleModule next : mLifecycleModules ) { next.onReady( mServerContext ); } resetClassLoader(cl); } }; public void onStartup(ServerContext context) throws ServerLifecycleException { final TimingDelta delta = new TimingDelta(); // wait for initialization to finish mOneTimeIniter.waitDoneThrow(); debug( "Millis for initer to run: ", (mOneTimeIniter.getNanosFromSubmit() / (1000*1000)), ", wait time = ", delta.elapsedMillis() ); mOneTimeIniter = null; mOneTimeStartup = new OneTimeStartup( context ); mOneTimeStartup.submit( RunnableBase.SUBMIT_ASYNC ); // we'll sync up with this thread in onReady() } public void onReady(ServerContext context) throws ServerLifecycleException { mOneTimeStartup.waitDoneThrow(); debug( "Millis for onStartup+onReady to run: ", (mOneTimeStartup.getNanosFromSubmit() / (1000*1000))); mOneTimeStartup = null; } public void onShutdown() throws ServerLifecycleException { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); for( final ServerLifecycleModule next : mLifecycleModules ) { next.onShutdown(); } // set it back resetClassLoader(cl); } public void onTermination() throws ServerLifecycleException { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); for( final ServerLifecycleModule next : mLifecycleModules ) { next.onTermination(); } // set it back resetClassLoader(cl); } }