// ========================================================================
// $Id: Container.java,v 1.4 2005/08/13 08:49:59 gregwilkins Exp $
// Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package net.lightbody.bmp.proxy.jetty.util;
import net.lightbody.bmp.proxy.jetty.http.HttpContext;
import net.lightbody.bmp.proxy.jetty.log.LogFactory;
import org.apache.commons.logging.Log;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EventListener;
/* ------------------------------------------------------------ */
/** Abstract Container.
* Provides base handling for LifeCycle and Component events.
*
* @version $Id: Container.java,v 1.4 2005/08/13 08:49:59 gregwilkins Exp $
* @author Greg Wilkins (gregw)
*/
public abstract class Container implements LifeCycle,EventProvider,Serializable
{
private static Log log = LogFactory.getLog(Container.class);
private Object _eventListeners;
private Object _components;
private transient boolean _started;
private transient boolean _starting;
private transient boolean _stopping;
/* ------------------------------------------------------------ */
/** Start the server.
* Generate LifeCycleEvents for starting and started either side of a call to doStart
*/
public synchronized final void start()
throws Exception
{
if (_started || _starting)
return;
_starting=true;
if (log.isDebugEnabled()) log.debug("Starting "+this);
LifeCycleEvent event = new LifeCycleEvent(this);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleStarting(event);
}
try
{
doStart();
_started=true;
log.info("Started "+this);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleStarted(event);
}
}
catch(Throwable e)
{
LifeCycleEvent failed = new LifeCycleEvent(this,e);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleFailure(event);
}
if (e instanceof Exception)
throw (Exception)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
if (e instanceof Error)
throw (Error)e;
log.warn(LogSupport.EXCEPTION, e);
}
finally
{
_starting=false;
}
}
/* ------------------------------------------------------------ */
/** Do start operations.
* This abstract method is called by start
* to perform the actual start operations.
*/
protected abstract void doStart()
throws Exception;
/* ------------------------------------------------------------ */
public synchronized boolean isStarted()
{
return _started;
}
/* ------------------------------------------------------------ */
protected synchronized boolean isStarting()
{
return _starting;
}
/* ------------------------------------------------------------ */
protected synchronized boolean isStopping()
{
return _stopping;
}
/* ------------------------------------------------------------ */
/** Stop the container.
* Generate LifeCycleEvents for stopping and stopped either side of a call to doStop
*/
public synchronized final void stop()
throws InterruptedException
{
if (!_started || _stopping)
return;
_stopping=true;
if (log.isDebugEnabled()) log.debug("Stopping "+this);
LifeCycleEvent event = new LifeCycleEvent(this);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleStopping(event);
}
try
{
doStop();
_started=false;
log.info("Stopped "+this);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleStopped(event);
}
}
catch(Throwable e)
{
event = new LifeCycleEvent(this,e);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof LifeCycleListener)
((LifeCycleListener)listener).lifeCycleFailure(event);
}
if (e instanceof InterruptedException)
throw (InterruptedException)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
if (e instanceof Error)
throw (Error)e;
log.warn(LogSupport.EXCEPTION, e);
}
finally
{
_stopping=false;
}
}
/* ------------------------------------------------------------ */
/** Do stop operations.
* This abstract method is called by stop
* to perform the actual stop operations.
*/
protected abstract void doStop()
throws Exception;
/* ------------------------------------------------------------ */
protected void addComponent(Object o)
{
if (!LazyList.contains(_components,o))
{
_components = LazyList.add(_components,o);
if(log.isDebugEnabled())log.debug("add component: "+o);
ComponentEvent event = new ComponentEvent(this,o);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof ComponentListener)
((ComponentListener)listener).addComponent(event);
}
}
}
/* ------------------------------------------------------------ */
protected void removeComponent(Object o)
{
if (LazyList.contains(_components,o))
{
_components=LazyList.remove(_components, o);
if(log.isDebugEnabled())log.debug("remove component: "+o);
ComponentEvent event = new ComponentEvent(this,o);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof ComponentListener)
((ComponentListener)listener).removeComponent(event);
}
}
}
/* ------------------------------------------------------------ */
/** Add a server event listener.
* @param listener ComponentEventListener or LifeCycleEventListener
*/
public void addEventListener(EventListener listener)
throws IllegalArgumentException
{
if (_eventListeners==null)
_eventListeners=new ArrayList();
if (listener instanceof ComponentListener ||
listener instanceof LifeCycleListener )
{
if(log.isDebugEnabled())log.debug("addEventListener: "+listener);
_eventListeners=LazyList.add(_eventListeners,listener);
}
}
/* ------------------------------------------------------------ */
public void removeEventListener(EventListener listener)
{
if(log.isDebugEnabled())log.debug("removeEventListener: "+listener);
_eventListeners=LazyList.remove(_eventListeners,listener);
}
/* ------------------------------------------------------------ */
/** Destroy a stopped server.
* Remove all components and send notifications to all event
* listeners. The HttpServer must be stopped before it can be destroyed.
*/
public void destroy()
{
if (isStarted())
throw new IllegalStateException("Started");
if (_components!=null && _eventListeners!=null)
{
for (int c=0;c<LazyList.size(_components);c++)
{
Object o=LazyList.get(_components,c);
if (o instanceof HttpContext )
((HttpContext)o).destroy();
ComponentEvent event = new ComponentEvent(this,o);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof ComponentListener)
((ComponentListener)listener).removeComponent(event);
}
}
}
_components=null;
_eventListeners=null;
}
/* ------------------------------------------------------------ */
public Collection getComponents()
{
return LazyList.getList(_eventListeners, false);
}
/* ------------------------------------------------------------ */
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
for (int c=0;c<LazyList.size(_components);c++)
{
Object o = LazyList.get(_components,c);
ComponentEvent event = new ComponentEvent(this,o);
for(int i=0;i<LazyList.size(_eventListeners);i++)
{
EventListener listener=(EventListener)LazyList.get(_eventListeners,i);
if (listener instanceof ComponentListener)
((ComponentListener)listener).addComponent(event);
}
}
}
}