332937 Added Destroyable interface and reworked dependent lifecycles, specially of JNDI

Also added Dumpable interface to improve and standardize the output of nested structures while debugging

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2615 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-12-21 11:27:02 +00:00
parent 7656b37934
commit e10c14c77a
43 changed files with 1018 additions and 517 deletions

View File

@ -5,6 +5,7 @@ jetty-7.3.0-SNAPSHOT
+ 332179 Fixed formatting of negative dates
+ 332703 Cleanup context scope JNDI at stop
+ 332796 Annotations inheritance does not work with jetty7
+ 332937 Added Destroyable interface and reworked dependent lifecycles, specially of JNDI
jetty-7.2.2.v20101205 5 December 2010
+ JETTY-1308 327109 (re)fixed AJP handling of empty packets

View File

@ -24,7 +24,9 @@ import static org.junit.Assert.assertNotNull;
public class TestResourceAnnotations
{
Object objA=new Integer(1000);
Object objB=new Integer(2000);
@Test
public void testResourceAnnotations ()
throws Exception
@ -38,8 +40,8 @@ public class TestResourceAnnotations
Context comp = (Context)ic.lookup("java:comp");
Context env = comp.createSubcontext("env");
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
AnnotationIntrospector parser = new AnnotationIntrospector();
ResourceAnnotationHandler handler = new ResourceAnnotationHandler(wac);
@ -56,13 +58,13 @@ public class TestResourceAnnotations
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceB/f
// java:comp/env/org.eclipse.jetty.annotations.resources.ResourceA/n
//
assertEquals(resourceB.getObjectToBind(), env.lookup("myf"));
assertEquals(resourceA.getObjectToBind(), env.lookup("mye"));
assertEquals(resourceA.getObjectToBind(), env.lookup("resA"));
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g"));
assertEquals(resourceA.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h"));
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f"));
assertEquals(resourceB.getObjectToBind(), env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n"));
assertEquals(objB, env.lookup("myf"));
assertEquals(objA, env.lookup("mye"));
assertEquals(objA, env.lookup("resA"));
assertEquals(objA, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/g"));
assertEquals(objA, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/h"));
assertEquals(objB, env.lookup("org.eclipse.jetty.annotations.resources.ResourceB/f"));
assertEquals(objB, env.lookup("org.eclipse.jetty.annotations.resources.ResourceA/n"));
//we should have Injections
assertNotNull(injections);
@ -98,22 +100,22 @@ public class TestResourceAnnotations
//check injected values
Field f = ResourceB.class.getDeclaredField ("f");
f.setAccessible(true);
assertEquals(resourceB.getObjectToBind() , f.get(binst));
assertEquals(objB , f.get(binst));
//@Resource(mappedName="resA") //test the default naming scheme but using a mapped name from the environment
f = ResourceA.class.getDeclaredField("g");
f.setAccessible(true);
assertEquals(resourceA.getObjectToBind(), f.get(binst));
assertEquals(objA, f.get(binst));
//@Resource(name="resA") //test using the given name as the name from the environment
f = ResourceA.class.getDeclaredField("j");
f.setAccessible(true);
assertEquals(resourceA.getObjectToBind(), f.get(binst));
assertEquals(objA, f.get(binst));
//@Resource(mappedName="resB") //test using the default name on an inherited field
f = ResourceA.class.getDeclaredField("n");
f.setAccessible(true);
assertEquals(resourceB.getObjectToBind(), f.get(binst));
assertEquals(objB, f.get(binst));
comp.destroySubcontext("env");
}
@ -131,8 +133,8 @@ public class TestResourceAnnotations
InitialContext ic = new InitialContext();
Context comp = (Context)ic.lookup("java:comp");
Context env = comp.createSubcontext("env");
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", new Integer(1000), false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", new Integer(2000), false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceA = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resA", objA, false);
org.eclipse.jetty.plus.jndi.EnvEntry resourceB = new org.eclipse.jetty.plus.jndi.EnvEntry(server, "resB", objB, false);
AnnotationIntrospector introspector = new AnnotationIntrospector();
ResourcesAnnotationHandler handler = new ResourcesAnnotationHandler(wac);
@ -140,7 +142,7 @@ public class TestResourceAnnotations
introspector.introspect(ResourceA.class);
introspector.introspect(ResourceB.class);
assertEquals(resourceA.getObjectToBind(), env.lookup("peach"));
assertEquals(resourceB.getObjectToBind(), env.lookup("pear"));
assertEquals(objA, env.lookup("peach"));
assertEquals(objB, env.lookup("pear"));
}
}

View File

@ -20,9 +20,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -38,6 +36,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
/**
@ -54,7 +53,7 @@ import org.eclipse.jetty.util.log.Log;
* <p>
* <img src="doc-files/DeploymentManager.png">
*/
public class DeploymentManager extends AbstractLifeCycle
public class DeploymentManager extends AggregateLifeCycle
{
/**
* Represents a single tracked app within the deployment manager.
@ -144,8 +143,10 @@ public class DeploymentManager extends AbstractLifeCycle
throw new IllegalStateException();
_providers.clear();
removeBeans();
for (AppProvider provider:providers)
_providers.add(provider);
if (_providers.add(provider))
addBean(provider);
}
public Collection<AppProvider> getAppProviders()
@ -159,6 +160,7 @@ public class DeploymentManager extends AbstractLifeCycle
throw new IllegalStateException();
_providers.add(provider);
addBean(provider);
}
public void setLifeCycleBindings(Collection<AppLifeCycle.Binding> bindings)
@ -250,18 +252,6 @@ public class DeploymentManager extends AbstractLifeCycle
}
return null;
}
/*
public App getAppByContextId(String contextId)
{
AppEntry entry = findAppByContextId(contextId);
if (entry == null)
{
return null;
}
return entry.app;
}
*/
public App getAppByOriginId(String originId)
{
@ -404,7 +394,8 @@ public class DeploymentManager extends AbstractLifeCycle
public void removeAppProvider(AppProvider provider)
{
_providers.remove(provider);
if(_providers.remove(provider))
removeBean(provider);
try
{
provider.stop();

View File

@ -53,6 +53,7 @@ public class StandardUndeployer implements AppLifeCycle.Binding
{
Log.debug("Removing handler: " + child);
coll.removeHandler(child);
((ContextHandler)child).destroy();
Log.debug(String.format("After removal: %d (originally %d)",coll.getHandlers().length,originalCount));
}
else if (child instanceof HandlerCollection)

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.jmx;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -26,8 +27,10 @@ import javax.management.ObjectName;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.component.Container.Relationship;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.ShutdownThread;
@ -36,7 +39,7 @@ import org.eclipse.jetty.util.thread.ShutdownThread;
/**
* Container class for the MBean instances
*/
public class MBeanContainer extends AbstractLifeCycle implements Container.Listener
public class MBeanContainer extends AbstractLifeCycle implements Container.Listener, Dumpable
{
private final MBeanServer _server;
private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
@ -311,4 +314,12 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
removeBean(removeObj);
}
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(toString()).append("\n");
AggregateLifeCycle.dump(out,indent,_beans.entrySet());
}
}

View File

@ -135,7 +135,7 @@ public class ContextFactory implements ObjectFactory
ctx = new NamingContext (env,
name.get(0),
nameCtx,
(NamingContext)nameCtx,
parser);
if(__log.isDebugEnabled())__log.debug("No entry for classloader: "+loader);
__contextMap.put (loader, ctx);

View File

@ -0,0 +1,43 @@
package org.eclipse.jetty.jndi;
import java.lang.reflect.Method;
import javax.sql.DataSource;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.log.Log;
/**
* Close a DataSource.
* Some {@link DataSource}'s need to be close (eg. Atomikos). This bean is a {@link Destroyable} and
* may be added to any {@link AggregateLifeCycle} so that {@link #destroy()}
* will be called. The {@link #destroy()} method calls any no-arg method called "close" on the passed DataSource.
*
*/
public class DataSourceCloser implements Destroyable
{
final DataSource _datasource;
public DataSourceCloser(DataSource datasource)
{
_datasource=datasource;
}
public void destroy()
{
if (_datasource != null)
{
try
{
Method close = _datasource.getClass().getMethod("close", new Class[]{});
close.invoke(_datasource, new Object[]{});
}
catch (Exception e)
{
Log.warn(e);
}
}
}
}

View File

@ -15,6 +15,8 @@ package org.eclipse.jetty.jndi;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@ -42,8 +44,13 @@ import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.spi.NamingManager;
import org.eclipse.jetty.jndi.local.localContextRoot;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Logger;
import com.sun.naming.internal.FactoryEnumeration;
import com.sun.naming.internal.ResourceManager;
/*------------------------------------------------*/
/** NamingContext
@ -63,7 +70,7 @@ import org.eclipse.jetty.util.log.Logger;
*
* @version 1.0
*/
public class NamingContext implements Context, Cloneable
public class NamingContext implements Context, Cloneable, Dumpable
{
private final static Logger __log=NamingUtil.__log;
private final static List<Binding> __empty = Collections.emptyList();
@ -73,11 +80,36 @@ public class NamingContext implements Context, Cloneable
protected final Hashtable<String,Object> _env = new Hashtable<String,Object>();
protected Map<String,Binding> _bindings = new HashMap<String,Binding>();
protected Context _parent = null;
protected NamingContext _parent = null;
protected String _name = null;
protected NameParser _parser = null;
private Collection<Listener> _listeners;
/*------------------------------------------------*/
/**
* Naming Context Listener.
* <p>
* If the env property {@link NamingContext#LISTENERS_PROPERTY} is set to
* a collection of Listeners, then the listener will be called as Bindings
* are added and removed from the context.
*/
public interface Listener
{
/**
* Called by {@link NamingContext#addBinding(Name, Object)} when adding
* a binding.
* @param ctx The context to add to.
* @param binding The binding to add.
* @return The binding to bind, or null if the binding should be ignored.
*/
Binding bind(NamingContext ctx, Binding binding);
/**
* @param ctx The context to unbind from
* @param binding The binding that was unbound.
*/
void unbind(NamingContext ctx, Binding binding);
}
/*------------------------------------------------*/
/** NameEnumeration
@ -207,7 +239,7 @@ public class NamingContext implements Context, Cloneable
*/
public NamingContext(Hashtable<String,Object> env,
String name,
Context parent,
NamingContext parent,
NameParser parser)
{
if (env != null)
@ -319,19 +351,15 @@ public class NamingContext implements Context, Cloneable
if (cname.size() == 1)
{
//get the object to be bound
Object objToBind = NamingManager.getStateToBind(obj, name,this, null);
Object objToBind = NamingManager.getStateToBind(obj, name,this, _env);
// Check for Referenceable
if (objToBind instanceof Referenceable)
{
objToBind = ((Referenceable)objToBind).getReference();
}
//anything else we should be able to bind directly
Binding binding = getBinding (cname);
if (binding == null)
addBinding (cname, objToBind);
else
throw new NameAlreadyBoundException (cname.toString());
//anything else we should be able to bind directly
addBinding (cname, objToBind);
}
else
{
@ -354,7 +382,6 @@ public class NamingContext implements Context, Cloneable
ctx = binding.getObject();
if (ctx instanceof Reference)
{
//deference the object
@ -973,13 +1000,15 @@ public class NamingContext implements Context, Cloneable
//if no subcontexts, just bind it
if (cname.size() == 1)
{
{
//check if it is a Referenceable
Object objToBind = NamingManager.getStateToBind(obj, name, this, null);
Object objToBind = NamingManager.getStateToBind(obj, name, this, _env);
if (objToBind instanceof Referenceable)
{
objToBind = ((Referenceable)objToBind).getReference();
}
removeBinding(cname);
addBinding (cname, objToBind);
}
else
@ -1336,7 +1365,6 @@ public class NamingContext implements Context, Cloneable
return (Hashtable)_env.clone();
}
/*------------------------------------------------*/
/**
* Add a name to object binding to this Context.
@ -1344,11 +1372,29 @@ public class NamingContext implements Context, Cloneable
* @param name a <code>Name</code> value
* @param obj an <code>Object</code> value
*/
protected void addBinding (Name name, Object obj)
protected void addBinding (Name name, Object obj) throws NameAlreadyBoundException
{
String key = name.toString();
if(__log.isDebugEnabled())__log.debug("Adding binding with key="+key+" obj="+obj+" for context="+_name);
_bindings.put (key, new Binding (key, obj));
Binding binding=new Binding (key, obj);
Collection<Listener> list = findListeners();
for (Listener listener : list)
{
binding=listener.bind(this,binding);
if (binding==null)
break;
}
if(__log.isDebugEnabled())
__log.debug("Adding binding with key="+key+" obj="+obj+" for context="+_name+" as "+binding);
if (binding!=null)
{
if (_bindings.containsKey(key))
throw new NameAlreadyBoundException(name.toString());
_bindings.put(key,binding);
}
}
/*------------------------------------------------*/
@ -1360,7 +1406,6 @@ public class NamingContext implements Context, Cloneable
*/
protected Binding getBinding (Name name)
{
if(__log.isDebugEnabled())__log.debug("Looking up binding for "+name.toString()+" for context="+_name);
return (Binding) _bindings.get(name.toString());
}
@ -1374,16 +1419,22 @@ public class NamingContext implements Context, Cloneable
*/
protected Binding getBinding (String name)
{
if(__log.isDebugEnabled())__log.debug("Looking up binding for "+name+" for context="+_name);
return (Binding) _bindings.get(name);
}
/*------------------------------------------------*/
protected void removeBinding (Name name)
{
String key = name.toString();
if (__log.isDebugEnabled()) __log.debug("Removing binding with key="+key);
_bindings.remove(key);
if (__log.isDebugEnabled())
__log.debug("Removing binding with key="+key);
Binding binding = _bindings.remove(key);
if (binding!=null)
{
Collection<Listener> list = findListeners();
for (Listener listener : list)
listener.unbind(this,binding);
}
}
/*------------------------------------------------*/
@ -1405,16 +1456,15 @@ public class NamingContext implements Context, Cloneable
if (canonicalName.get(0).equals(""))
canonicalName = canonicalName.getSuffix(1);
if (canonicalName.get(canonicalName.size()-1).equals(""))
canonicalName = canonicalName.getPrefix(canonicalName.size()-1);
canonicalName = canonicalName.getPrefix(canonicalName.size()-1);
}
}
return canonicalName;
}
/* ------------------------------------------------------------ */
private boolean isLocked()
{
if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null))
@ -1427,7 +1477,9 @@ public class NamingContext implements Context, Cloneable
return false;
return true;
}
/* ------------------------------------------------------------ */
public String dump()
{
StringBuilder buf = new StringBuilder();
@ -1444,7 +1496,7 @@ public class NamingContext implements Context, Cloneable
/* ------------------------------------------------------------ */
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
out.append(this.getClass().getSimpleName()).append("@").append(Long.toHexString(this.hashCode())).append("\n");
int size=_bindings.size();
@ -1457,13 +1509,14 @@ public class NamingContext implements Context, Cloneable
Binding binding = entry.getValue();
Object value = binding.getObject();
if ("comp".equals(entry.getKey()) && value instanceof Reference && "org.eclipse.jetty.jndi.ContextFactory".equals(((Reference)value).getFactoryClassName()))
{
ContextFactory.dump(out,indent+(last?" ":" | "));
}
else if (value instanceof NamingContext)
((NamingContext)value).dump(out,indent+(last?" ":" | "));
else if (value instanceof Dumpable)
{
((Dumpable)value).dump(out,indent+(last?" ":" | "));
}
else
{
out.append(value.getClass().getSimpleName()).append("=");
@ -1472,4 +1525,29 @@ public class NamingContext implements Context, Cloneable
}
}
}
private Collection<Listener> findListeners()
{
Collection<Listener> list = new ArrayList<Listener>();
NamingContext ctx=this;
while (ctx!=null)
{
if (ctx._listeners!=null)
list.addAll(ctx._listeners);
ctx=(NamingContext)ctx.getParent();
}
return list;
}
public void addListener(Listener listener)
{
if (_listeners==null)
_listeners=new ArrayList<Listener>();
_listeners.add(listener);
}
public boolean removeListener(Listener listener)
{
return _listeners.remove(listener);
}
}

View File

@ -17,6 +17,8 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Hashtable;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
@ -72,6 +74,37 @@ public class TestJNDI
ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
ClassLoader childLoader2 = new URLClassLoader(new URL[0], currentLoader);
/*
javaRootURLContext.getRoot().addListener(new NamingContext.Listener()
{
public void unbind(NamingContext ctx, Binding binding)
{
System.err.println("java unbind "+binding+" from "+ctx.getName());
}
public Binding bind(NamingContext ctx, Binding binding)
{
System.err.println("java bind "+binding+" to "+ctx.getName());
return binding;
}
});
localContextRoot.getRoot().addListener(new NamingContext.Listener()
{
public void unbind(NamingContext ctx, Binding binding)
{
System.err.println("local unbind "+binding+" from "+ctx.getName());
}
public Binding bind(NamingContext ctx, Binding binding)
{
System.err.println("local bind "+binding+" to "+ctx.getName());
return binding;
}
});
*/
//set the current thread's classloader
currentThread.setContextClassLoader(childLoader1);

View File

@ -35,32 +35,33 @@ import org.eclipse.jetty.util.log.Log;
*/
public class Injection
{
private Class _targetClass;
private Class<?> _targetClass;
private String _jndiName;
private String _mappingName;
private Member _target;
private Class _paramClass;
private Class _resourceClass;
private Class<?> _paramClass;
private Class<?> _resourceClass;
public Injection ()
{}
{
}
/**
* @return the _className
*/
public Class getTargetClass()
public Class<?> getTargetClass()
{
return _targetClass;
}
public Class getParamClass ()
public Class<?> getParamClass ()
{
return _paramClass;
}
public Class getResourceClass ()
public Class<?> getResourceClass ()
{
return _resourceClass;
}
@ -113,22 +114,22 @@ public class Injection
}
public void setTarget(Class clazz, Field field, Class resourceType)
public void setTarget(Class<?> clazz, Field field, Class<?> resourceType)
{
_targetClass = clazz;
_target = field;
_resourceClass = resourceType;
}
public void setTarget(Class clazz, Method method, Class arg, Class resourceType)
public void setTarget(Class<?> clazz, Method method, Class<?> arg, Class<?> resourceType)
{
_targetClass = clazz;
_target = method;
_resourceClass = resourceType;
_paramClass = arg;
}
public void setTarget (Class clazz, String target, Class resourceType)
public void setTarget (Class<?> clazz, String target, Class<?> resourceType)
{
_targetClass = clazz;
_resourceClass = resourceType;

View File

@ -33,10 +33,6 @@ public class LifeCycleCallbackCollection
private HashMap<String, List<LifeCycleCallback>> postConstructCallbacksMap = new HashMap<String, List<LifeCycleCallback>>();
private HashMap<String, List<LifeCycleCallback>> preDestroyCallbacksMap = new HashMap<String, List<LifeCycleCallback>>();
/**
* Add a Callback to the list of callbacks.
*

View File

@ -26,11 +26,11 @@ public class EnvEntry extends NamingEntry
{
private boolean overrideWebXml;
public EnvEntry (Object scope, String jndiName, Object objToBind, boolean overrideWebXml)
throws NamingException
{
super (scope, jndiName, objToBind);
super (scope, jndiName);
save(objToBind);
this.overrideWebXml = overrideWebXml;
}
@ -38,7 +38,8 @@ public class EnvEntry extends NamingEntry
public EnvEntry (String jndiName, Object objToBind, boolean overrideWebXml)
throws NamingException
{
super(jndiName, objToBind);
super(jndiName);
save(objToBind);
this.overrideWebXml = overrideWebXml;
}
@ -48,7 +49,6 @@ public class EnvEntry extends NamingEntry
this(jndiName, objToBind, false);
}
public boolean isOverrideWebXml ()
{
return this.overrideWebXml;

View File

@ -19,25 +19,31 @@ import javax.naming.NamingException;
public class Link extends NamingEntry
{
public Link(Object scope, String jndiName, Object object) throws NamingException
private final String _link;
public Link(Object scope, String jndiName, String link) throws NamingException
{
//jndiName is the name according to the web.xml
//objectToBind is the name in the environment
super(scope, jndiName, object);
super(scope, jndiName);
save(link);
_link=link;
}
public Link (String jndiName, Object object) throws NamingException
public Link (String jndiName, String link) throws NamingException
{
super(null, jndiName, object);
super(jndiName);
save(link);
_link=link;
}
public void bindToENC(String localName) throws NamingException
{
throw new UnsupportedOperationException("Method not supported for Link objects");
}
public String getLink()
{
return _link;
}
}

View File

@ -40,24 +40,23 @@ public abstract class NamingEntry
{
private static Logger __log = NamingUtil.__log;
public static final String __contextName = "__"; //all NamingEntries stored in context called "__"
protected String jndiName; //the name representing the object associated with the NamingEntry
protected Object objectToBind; //the object associated with the NamingEntry
protected String namingEntryNameString; //the name of the NamingEntry relative to the context it is stored in
protected String objectNameString; //the name of the object relative to the context it is stored in
protected final Object _scope;
protected final String _jndiName; //the name representing the object associated with the NamingEntry
protected String _namingEntryNameString; //the name of the NamingEntry relative to the context it is stored in
protected String _objectNameString; //the name of the object relative to the context it is stored in
public String toString()
{
return jndiName;
return _jndiName;
}
public NamingEntry (Object scope, String jndiName, Object object)
protected NamingEntry (Object scope, String jndiName)
throws NamingException
{
this.jndiName = jndiName;
this.objectToBind = object;
save(scope);
this._scope=scope;
this._jndiName = jndiName;
}
/**
@ -72,10 +71,10 @@ public abstract class NamingEntry
* @param object the object to be bound
* @throws NamingException
*/
public NamingEntry (String jndiName, Object object)
protected NamingEntry (String jndiName)
throws NamingException
{
this (null, jndiName, object);
this (null, jndiName);
}
@ -92,8 +91,8 @@ public abstract class NamingEntry
//TODO - check on the whole overriding/non-overriding thing
InitialContext ic = new InitialContext();
Context env = (Context)ic.lookup("java:comp/env");
__log.debug("Binding java:comp/env/"+localName+" to "+objectNameString);
NamingUtil.bind(env, localName, new LinkRef(objectNameString));
__log.debug("Binding java:comp/env/"+localName+" to "+_objectNameString);
NamingUtil.bind(env, localName, new LinkRef(_objectNameString));
}
/**
@ -122,12 +121,10 @@ public abstract class NamingEntry
try
{
InitialContext ic = new InitialContext();
ic.unbind(objectNameString);
ic.unbind(namingEntryNameString);
this.jndiName=null;
this.namingEntryNameString=null;
this.objectNameString=null;
this.objectToBind=null;
ic.unbind(_objectNameString);
ic.unbind(_namingEntryNameString);
this._namingEntryNameString=null;
this._objectNameString=null;
}
catch (NamingException e)
{
@ -142,19 +139,8 @@ public abstract class NamingEntry
*/
public String getJndiName ()
{
return this.jndiName;
return _jndiName;
}
/**
* Get the object that is to be bound
* @return the object that is to be bound
*/
public Object getObjectToBind()
throws NamingException
{
return this.objectToBind;
}
/**
* Get the name of the object, fully
@ -163,7 +149,7 @@ public abstract class NamingEntry
*/
public String getJndiNameInScope ()
{
return objectNameString;
return _objectNameString;
}
@ -187,25 +173,25 @@ public abstract class NamingEntry
*
* @throws NamingException
*/
protected void save (Object scope)
protected void save (Object object)
throws NamingException
{
__log.debug("SAVE {} in {}",this,scope);
__log.debug("SAVE {} in {}",this,_scope);
InitialContext ic = new InitialContext();
NameParser parser = ic.getNameParser("");
Name prefix = NamingEntryUtil.getNameForScope(scope);
Name prefix = NamingEntryUtil.getNameForScope(_scope);
//bind the NamingEntry into the context
Name namingEntryName = NamingEntryUtil.makeNamingEntryName(parser, getJndiName());
namingEntryName.addAll(0, prefix);
namingEntryNameString = namingEntryName.toString();
NamingUtil.bind(ic, namingEntryNameString, this);
_namingEntryNameString = namingEntryName.toString();
NamingUtil.bind(ic, _namingEntryNameString, this);
//bind the object as well
Name objectName = parser.parse(getJndiName());
objectName.addAll(0, prefix);
objectNameString = objectName.toString();
NamingUtil.bind(ic, objectNameString, objectToBind);
_objectNameString = objectName.toString();
NamingUtil.bind(ic, _objectNameString, object);
}
}

View File

@ -29,7 +29,8 @@ public class Resource extends NamingEntry
public Resource (Object scope, String jndiName, Object objToBind)
throws NamingException
{
super(scope, jndiName, objToBind);
super(scope, jndiName);
save(objToBind);
}
/**
@ -39,7 +40,8 @@ public class Resource extends NamingEntry
public Resource (String jndiName, Object objToBind)
throws NamingException
{
super(jndiName, objToBind);
super(jndiName);
save(objToBind);
}
}

View File

@ -48,13 +48,12 @@ public class Transaction extends NamingEntry
throw new NameNotFoundException( USER_TRANSACTION + " not found" );
}
}
public Transaction (UserTransaction userTransaction)
throws NamingException
{
super (USER_TRANSACTION, userTransaction);
super (USER_TRANSACTION);
save(userTransaction);
}
@ -69,8 +68,8 @@ public class Transaction extends NamingEntry
{
InitialContext ic = new InitialContext();
Context env = (Context)ic.lookup("java:comp/env");
__log.debug("Binding java:comp/env"+getJndiName()+" to "+objectNameString);
NamingUtil.bind(env, localName, new LinkRef(objectNameString));
__log.debug("Binding java:comp/env"+getJndiName()+" to "+_objectNameString);
NamingUtil.bind(env, localName, new LinkRef(_objectNameString));
}
/**
@ -83,8 +82,8 @@ public class Transaction extends NamingEntry
//ignore the name, it is always bound to java:comp
InitialContext ic = new InitialContext();
Context env = (Context)ic.lookup("java:comp");
__log.debug("Binding java:comp/"+getJndiName()+" to "+objectNameString);
NamingUtil.bind(env, getJndiName(), new LinkRef(objectNameString));
__log.debug("Binding java:comp/"+getJndiName()+" to "+_objectNameString);
NamingUtil.bind(env, getJndiName(), new LinkRef(_objectNameString));
}
/**

View File

@ -14,9 +14,12 @@
package org.eclipse.jetty.plus.webapp;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
@ -25,6 +28,7 @@ import javax.naming.NamingException;
import org.eclipse.jetty.jndi.NamingContext;
import org.eclipse.jetty.jndi.NamingUtil;
import org.eclipse.jetty.jndi.java.javaRootURLContext;
import org.eclipse.jetty.jndi.local.localContextRoot;
import org.eclipse.jetty.plus.jndi.EnvEntry;
import org.eclipse.jetty.plus.jndi.NamingEntry;
@ -43,17 +47,13 @@ import org.eclipse.jetty.xml.XmlConfiguration;
*/
public class EnvConfiguration extends AbstractConfiguration
{
private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration";
private URL jettyEnvXmlUrl;
public void setJettyEnvXml (URL url)
{
this.jettyEnvXmlUrl = url;
}
/**
* @see Configuration#configure(WebAppContext)
@ -79,7 +79,6 @@ public class EnvConfiguration extends AbstractConfiguration
//look in WEB-INF/jetty-env.xml
if (jettyEnvXmlUrl == null)
{
//look for a file called WEB-INF/jetty-env.xml
//and process it if it exists
org.eclipse.jetty.util.resource.Resource web_inf = context.getWebInf();
@ -93,20 +92,46 @@ public class EnvConfiguration extends AbstractConfiguration
}
}
//apply the jetty-env.xml file
if (jettyEnvXmlUrl != null)
{
XmlConfiguration configuration = new XmlConfiguration(jettyEnvXmlUrl);
configuration.configure(context);
synchronized (localContextRoot.getRoot())
{
// create list and listener to remember the bindings we make.
final List<Bound> bindings = new ArrayList<Bound>();
NamingContext.Listener listener = new NamingContext.Listener()
{
public void unbind(NamingContext ctx, Binding binding)
{
}
public Binding bind(NamingContext ctx, Binding binding)
{
bindings.add(new Bound(ctx,binding.getName()));
return binding;
}
};
try
{
localContextRoot.getRoot().addListener(listener);
XmlConfiguration configuration = new XmlConfiguration(jettyEnvXmlUrl);
configuration.configure(context);
}
finally
{
localContextRoot.getRoot().removeListener(listener);
context.setAttribute(JETTY_ENV_BINDINGS,bindings);
}
}
}
//add java:comp/env entries for any EnvEntries that have been defined so far
bindEnvEntries(context);
}
/**
* Remove all jndi setup
* Remove jndi setup from start
* @see Configuration#deconfigure(WebAppContext)
* @throws Exception
*/
@ -121,15 +146,39 @@ public class EnvConfiguration extends AbstractConfiguration
Context ic = new InitialContext();
Context compCtx = (Context)ic.lookup ("java:comp");
compCtx.destroySubcontext("env");
//unbind any NamingEntries that were configured in this webapp's name space
List<Bound> bindings = (List<Bound>)context.getAttribute(JETTY_ENV_BINDINGS);
context.setAttribute(JETTY_ENV_BINDINGS,null);
if (bindings!=null)
{
Collections.reverse(bindings);
for (Bound b:bindings)
b._context.destroySubcontext(b._name);
}
}
catch (NameNotFoundException e)
{
Log.warn(e);
}
//unbind any NamingEntries that were configured in this webapp's name space
try
finally
{
Thread.currentThread().setContextClassLoader(oldLoader);
}
}
/**
* Remove all jndi setup
* @see Configuration#deconfigure(WebAppContext)
* @throws Exception
*/
@Override
public void destroy (WebAppContext context) throws Exception
{
try
{
//unbind any NamingEntries that were configured in this webapp's name space
NamingContext scopeContext = (NamingContext)NamingEntryUtil.getContextForScope(context);
scopeContext.getParent().destroySubcontext(scopeContext.getName());
}
@ -138,7 +187,6 @@ public class EnvConfiguration extends AbstractConfiguration
Log.ignore(e);
Log.debug("No naming entries configured in environment for webapp "+context);
}
Thread.currentThread().setContextClassLoader(oldLoader);
}
/**
@ -207,4 +255,15 @@ public class EnvConfiguration extends AbstractConfiguration
Thread.currentThread().setContextClassLoader(old_loader);
}
}
private static class Bound
{
final NamingContext _context;
final String _name;
Bound(NamingContext context, String name)
{
_context=context;
_name=name;
}
}
}

View File

@ -72,6 +72,8 @@ public class PlusConfiguration extends AbstractConfiguration
{
unlockCompEnv(context);
_key = null;
context.setAttribute(InjectionCollection.INJECTION_COLLECTION,null);
context.setAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION,null);
}
public void bindUserTransaction (WebAppContext context)

View File

@ -855,7 +855,7 @@ public class PlusDescriptorProcessor extends IterativeDescriptorProcessor
if (ne!=null && (ne instanceof Link))
{
//if we found a mapping, get out name it is mapped to in the environment
nameInEnvironment = (String)((Link)ne).getObjectToBind();
nameInEnvironment = ((Link)ne).getLink();
Link l = (Link)ne;
}

View File

@ -34,7 +34,8 @@ public class TestNamingEntryUtil
public MyNamingEntry(Object scope, String name, Object value)
throws NamingException
{
super(scope, name, value);
super(scope, name);
save(value);
}
}

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.security;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -34,6 +35,7 @@ import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.StringMap;
import org.eclipse.jetty.util.TypeUtil;
/* ------------------------------------------------------------ */
/**
@ -419,19 +421,12 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
return false;
}
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
out.append(indent).append(" +-").append(String.valueOf(_roles)).append('\n');
for (Object path : _constraintMap.keySet())
{
Object constraint = _constraintMap.get(path);
out.append(indent).append(" +-").append(String.valueOf(path)).append('=').append(String.valueOf(constraint)).append('\n');
}
dumpHandlers(out,indent);
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),Collections.singleton(_roles),_constraintMap.entrySet());
}
}

View File

@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.component.LifeCycle;
/* ------------------------------------------------------------ */
@ -39,7 +40,7 @@ import org.eclipse.jetty.util.component.LifeCycle;
* before passing it to the next stage of handling.
*
*/
public interface Handler extends LifeCycle
public interface Handler extends LifeCycle, Destroyable
{
/* ------------------------------------------------------------ */
/** Handle a request.

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
@ -33,8 +34,10 @@ import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -62,7 +65,6 @@ public class Server extends HandlerWrapper implements Attributes
}
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
private final List<Object> _dependentBeans=new ArrayList<Object>();
private ThreadPool _threadPool;
private Connector[] _connectors;
private SessionIdManager _sessionIdManager;
@ -195,8 +197,12 @@ public class Server extends HandlerWrapper implements Attributes
*/
public void setThreadPool(ThreadPool threadPool)
{
_container.update(this,_threadPool,threadPool, "threadpool",true);
if (_threadPool!=null)
removeBean(_threadPool);
_container.update(this, _threadPool, threadPool, "threadpool",false);
_threadPool = threadPool;
if (_threadPool!=null)
addBean(_threadPool);
}
/* ------------------------------------------------------------ */
@ -209,34 +215,9 @@ public class Server extends HandlerWrapper implements Attributes
Log.info("jetty-"+_version);
HttpGenerator.setServerVersion(_version);
MultiException mex=new MultiException();
if (_threadPool==null)
{
QueuedThreadPool tp=new QueuedThreadPool();
setThreadPool(tp);
}
Iterator<Object> itor = _dependentBeans.iterator();
while (itor.hasNext())
{
try
{
Object o=itor.next();
if (o instanceof LifeCycle)
((LifeCycle)o).start();
}
catch (Throwable e) {mex.add(e);}
}
if (_sessionIdManager!=null)
_sessionIdManager.start();
try
{
if (_threadPool instanceof LifeCycle)
((LifeCycle)_threadPool).start();
}
catch(Throwable e) { mex.add(e);}
setThreadPool(new QueuedThreadPool());
try
{
@ -298,31 +279,6 @@ public class Server extends HandlerWrapper implements Attributes
}
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
if (_sessionIdManager!=null)
_sessionIdManager.stop();
try
{
if (_threadPool instanceof LifeCycle)
((LifeCycle)_threadPool).stop();
}
catch(Throwable e){mex.add(e);}
if (!_dependentBeans.isEmpty())
{
ListIterator<Object> itor = _dependentBeans.listIterator(_dependentBeans.size());
while (itor.hasPrevious())
{
try
{
Object o =itor.previous();
if (o instanceof LifeCycle)
((LifeCycle)o).stop();
}
catch (Throwable e) {mex.add(e);}
}
}
mex.ifExceptionThrow();
@ -399,7 +355,6 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
public void join() throws InterruptedException
{
@ -423,8 +378,12 @@ public class Server extends HandlerWrapper implements Attributes
*/
public void setSessionIdManager(SessionIdManager sessionIdManager)
{
_container.update(this,_sessionIdManager,sessionIdManager, "sessionIdManager",true);
if (_sessionIdManager!=null)
removeBean(_sessionIdManager);
_container.update(this, _sessionIdManager, sessionIdManager, "sessionIdManager",false);
_sessionIdManager = sessionIdManager;
if (_sessionIdManager!=null)
addBean(_sessionIdManager);
}
/* ------------------------------------------------------------ */
@ -490,78 +449,21 @@ public class Server extends HandlerWrapper implements Attributes
* Add an associated bean.
* The bean will be added to the servers {@link Container}
* and if it is a {@link LifeCycle} instance, it will be
* started/stopped along with the Server.
* started/stopped along with the Server. Any beans that are also
* {@link Destroyable}, will be destroyed with the server.
* @param o the bean object to add
*/
public void addBean(Object o)
@Override
public boolean addBean(Object o)
{
if (o == null)
return;
if (!_dependentBeans.contains(o))
if (super.addBean(o))
{
_dependentBeans.add(o);
_container.addBean(o);
return true;
}
try
{
if (isStarted() && o instanceof LifeCycle)
((LifeCycle)o).start();
}
catch (Exception e)
{
throw new RuntimeException (e);
}
return false;
}
/* ------------------------------------------------------------ */
/** Get dependent beans of a specific class
* @see #addBean(Object)
* @param clazz
* @return List of beans.
*/
public <T> List<T> getBeans(Class<T> clazz)
{
ArrayList<T> beans = new ArrayList<T>();
Iterator<?> iter = _dependentBeans.iterator();
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
beans.add((T)o);
}
return beans;
}
/* ------------------------------------------------------------ */
/** Get dependent bean of a specific class.
* If more than one bean of the type exist, the first is returned.
* @see #addBean(Object)
* @param clazz
* @return bean or null
*/
public <T> T getBean(Class<T> clazz)
{
Iterator<?> iter = _dependentBeans.iterator();
T t=null;
int count=0;
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
{
count++;
if (t==null)
t=(T)o;
}
}
if (count>1)
Log.debug("getBean({}) 1 of {}",clazz.getName(),count);
return t;
}
/**
* Remove a LifeCycle object to be started/stopped
* along with the Server
@ -572,16 +474,20 @@ public class Server extends HandlerWrapper implements Attributes
{
removeBean(c);
}
/* ------------------------------------------------------------ */
/**
* Remove an associated bean.
*/
public void removeBean (Object o)
@Override
public boolean removeBean (Object o)
{
if (o == null)
return;
_dependentBeans.remove(o);
_container.removeBean(o);
if (super.removeBean(o))
{
_container.removeBean(o);
return true;
}
return false;
}
/* ------------------------------------------------------------ */
@ -652,7 +558,7 @@ public class Server extends HandlerWrapper implements Attributes
{
_graceful=timeoutMS;
}
/* ------------------------------------------------------------ */
@Override
public String toString()
@ -660,18 +566,12 @@ public class Server extends HandlerWrapper implements Attributes
return this.getClass().getName()+"@"+Integer.toHexString(hashCode());
}
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
if (_connectors != null)
for (Connector c : _connectors)
out.append(" +-").append(String.valueOf(c)).append('\n');
if (_threadPool != null)
out.append(" +-").append(String.valueOf(_threadPool)).append('\n');
dumpHandlers(out,indent);
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors));
}

View File

@ -18,7 +18,9 @@ import java.io.IOException;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
@ -27,7 +29,7 @@ import org.eclipse.jetty.util.log.Log;
*
*
*/
public abstract class AbstractHandler extends AbstractLifeCycle implements Handler
public abstract class AbstractHandler extends AggregateLifeCycle implements Handler
{
private Server _server;
@ -47,6 +49,7 @@ public abstract class AbstractHandler extends AbstractLifeCycle implements Handl
protected void doStart() throws Exception
{
Log.debug("starting {}",this);
super.doStart();
}
/* ------------------------------------------------------------ */
@ -57,6 +60,7 @@ public abstract class AbstractHandler extends AbstractLifeCycle implements Handl
protected void doStop() throws Exception
{
Log.debug("stopping {}",this);
super.doStop();
}
/* ------------------------------------------------------------ */
@ -76,42 +80,20 @@ public abstract class AbstractHandler extends AbstractLifeCycle implements Handl
return _server;
}
/* ------------------------------------------------------------ */
public void destroy()
{
if (!isStopped())
throw new IllegalStateException("!STOPPED");
super.destroy();
if (_server!=null)
_server.getContainer().removeBean(this);
}
/* ------------------------------------------------------------ */
public String dump()
{
StringBuilder b = new StringBuilder();
try
{
dump(b,"");
}
catch (IOException e)
{
Log.warn(e);
}
return b.toString();
}
/* ------------------------------------------------------------ */
public void dump(Appendable out) throws IOException
{
dump(out,"");
}
/* ------------------------------------------------------------ */
protected void dump(Appendable out,String indent) throws IOException
public void dumpThis(Appendable out) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
}
}

View File

@ -15,10 +15,14 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.TypeUtil;
/* ------------------------------------------------------------ */
@ -83,36 +87,11 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
return list;
}
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
super.dump(out,indent);
dumpHandlers(out,indent);
}
/* ------------------------------------------------------------ */
protected void dumpHandlers(Appendable out,String indent) throws IOException
{
Handler[] handlers = getHandlers();
if (handlers!=null)
{
int last=handlers.length-1;
for (int h=0;h<=last;h++)
{
if (handlers[h]==null)
continue;
out.append(indent);
out.append(" +-");
if (handlers[h] instanceof AbstractHandler)
((AbstractHandler)handlers[h]).dump(out,indent+((h==last)?" ":" | "));
else
{
out.append(String.valueOf(handlers[h]));
out.append("\n");
}
}
}
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans());
}
}

View File

@ -59,6 +59,7 @@ import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -187,15 +188,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
if (Log.isDebugEnabled())
{
out.append(indent).append(" +-").append(String.valueOf(_attributes)).append('\n');
out.append(indent).append(" +-").append(String.valueOf(_contextAttributes)).append('\n');
}
dumpHandlers(out,indent);
dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),_initParams.entrySet(), _attributes.getAttributeEntrySet(),_contextAttributes.getAttributeEntrySet());
}
/* ------------------------------------------------------------ */
@ -645,6 +641,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
}
Log.info("started {}",this);
}
/* ------------------------------------------------------------ */
@ -695,6 +692,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
finally
{
Log.info("stopped {}",this);
__context.set(old_context);
// reset the classloader
if (_classLoader!=null)

View File

@ -57,6 +57,8 @@ public class HandlerWrapper extends AbstractHandlerContainer
*/
public Handler[] getHandlers()
{
if (_handler==null)
return new Handler[0];
return new Handler[] {_handler};
}

View File

@ -25,6 +25,7 @@ import javax.servlet.FilterConfig;
import org.eclipse.jetty.servlet.api.FilterRegistration;
import javax.servlet.ServletException;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
/* --------------------------------------------------------------------- */
@ -219,8 +220,7 @@ public class FilterHolder extends Holder<Filter>
if (mapping.getFilterHolder()!=FilterHolder.this)
continue;
String[] specs=mapping.getPathSpecs();
if (specs!=null && specs.length>0)
patterns.addAll(Arrays.asList(specs));
patterns.addAll(TypeUtil.asList(specs));
}
return patterns;
}

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.Arrays;
import java.util.EnumSet;
@ -20,9 +21,12 @@ import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
public class FilterMapping
public class FilterMapping implements Dumpable
{
/** Dispatch types */
public static final int DEFAULT=0;
@ -251,10 +255,16 @@ public class FilterMapping
public String toString()
{
return
(_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+"/"+
(_servletNames==null?"[]":Arrays.asList(_servletNames).toString())+"=="+
TypeUtil.asList(_pathSpecs)+"/"+
TypeUtil.asList(_servletNames)+"=="+
_dispatches+"=>"+
_filterName;
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
}
}

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@ -27,6 +28,8 @@ import javax.servlet.UnavailableException;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
@ -34,7 +37,7 @@ import org.eclipse.jetty.util.log.Log;
/**
*
*/
public class Holder<T> extends AbstractLifeCycle
public class Holder<T> extends AbstractLifeCycle implements Dumpable
{
protected transient Class<? extends T> _class;
protected final Map<String,String> _initParams=new HashMap<String,String>(3);
@ -250,6 +253,13 @@ public class Holder<T> extends AbstractLifeCycle
}
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(_name).append("==").append(_className).append("\n");
AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */

View File

@ -141,6 +141,7 @@ public class ServletContextHandler extends ContextHandler
protected void doStop() throws Exception
{
super.doStop();
_decorators.clear();
}
/* ------------------------------------------------------------ */

View File

@ -58,6 +58,7 @@ import org.eclipse.jetty.server.handler.ScopedHandler;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@ -1472,56 +1473,17 @@ public class ServletHandler extends ScopedHandler
_contextHandler.destroyFilter(filter);
}
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
public void dump(Appendable out,String indent) throws IOException
{
super.dump(out,indent);
if (getFilterMappings()!=null)
{
for (FilterMapping f : getFilterMappings())
{
out.append(indent);
out.append(" +-");
out.append(String.valueOf(f.toString()));
if (Log.isDebugEnabled())
out.append(String.valueOf(f.getFilterHolder().getInitParameters()));
out.append('\n');
}
}
HashSet<String> servlets = new HashSet<String>();
if (getServletMappings()!=null)
{
for (ServletMapping m : getServletMappings())
{
servlets.add(m.getServletName());
out.append(indent);
out.append(" +-");
out.append(String.valueOf(m));
ServletHolder h = getServlet(m.getServletName());
if (h!=null && Log.isDebugEnabled())
out.append(String.valueOf(h.getInitParameters()));
out.append('\n');
}
}
if (getServlets()!=null)
{
for (ServletHolder h : getServlets())
{
if (servlets.contains(h.getName()))
continue;
out.append(indent);
out.append(" +-[]==>");
out.append(h.getName());
if (Log.isDebugEnabled())
out.append(String.valueOf(h.getInitParameters()));
out.append('\n');
}
}
super.dumpThis(out);
dump(out,indent,
TypeUtil.asList(getHandlers()),
getBeans(),
TypeUtil.asList(getFilterMappings()),
TypeUtil.asList(getFilters()),
TypeUtil.asList(getServletMappings()),
TypeUtil.asList(getServlets()));
}
}

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.Arrays;
@ -77,4 +78,10 @@ public class ServletMapping
{
return (_pathSpecs==null?"[]":Arrays.asList(_pathSpecs).toString())+"=>"+_servletName;
}
/* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
}
}

View File

@ -94,7 +94,13 @@ public class AttributesMap implements Attributes
{
return _map.keySet();
}
/* ------------------------------------------------------------ */
public Set<Map.Entry<String, Object>> getAttributeEntrySet()
{
return _map.entrySet();
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.util.Attributes#getAttributeNames()

View File

@ -19,7 +19,11 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import org.eclipse.jetty.util.log.Log;
@ -156,6 +160,19 @@ public class TypeUtil
}
}
/* ------------------------------------------------------------ */
/** Array to List.
* <p>
* Works like {@link Arrays#asList(Object...)}, but handles null arrays.
* @return a list backed by the array.
*/
public static <T> List<T> asList(T[] a)
{
if (a==null)
return Collections.emptyList();
return Arrays.asList(a);
}
/* ------------------------------------------------------------ */
/** Class from a canonical name for a type.
* @param name A class or type name.

View File

@ -0,0 +1,250 @@
package org.eclipse.jetty.util.component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.naming.Binding;
import javax.naming.Reference;
import org.eclipse.jetty.util.log.Log;
/**
* An AggregateLifeCycle is an AbstractLifeCycle with a collection of dependent beans.
* <p>
* Dependent beans are started and stopped with the {@link LifeCycle} and if they are destroyed if they are also {@link Destroyable}.
*
*/
public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable, Dumpable
{
private final Queue<Object> _dependentBeans=new ConcurrentLinkedQueue<Object>();
public void destroy()
{
for (Object o : _dependentBeans)
{
if (o instanceof Destroyable)
{
((Destroyable)o).destroy();
}
}
_dependentBeans.clear();
}
@Override
protected void doStart() throws Exception
{
for (Object o:_dependentBeans)
{
if (o instanceof LifeCycle)
((LifeCycle)o).start();
}
super.doStart();
}
@Override
protected void doStop() throws Exception
{
super.doStop();
for (Object o:_dependentBeans)
{
if (o instanceof LifeCycle)
((LifeCycle)o).stop();
}
}
/* ------------------------------------------------------------ */
/**
* Add an associated bean.
* The bean will be added to this LifeCycle and if it is also a
* {@link LifeCycle} instance, it will be
* started/stopped. Any beans that are also
* {@link Destroyable}, will be destroyed with the server.
* @param o the bean object to add
*/
public boolean addBean(Object o)
{
if (o == null)
return false;
boolean added=false;
if (!_dependentBeans.contains(o))
{
_dependentBeans.add(o);
added=true;
}
try
{
if (isStarted() && o instanceof LifeCycle)
((LifeCycle)o).start();
}
catch (Exception e)
{
throw new RuntimeException (e);
}
return added;
}
/* ------------------------------------------------------------ */
/** Get dependent beans
* @return List of beans.
*/
public Collection<Object> getBeans()
{
return _dependentBeans;
}
/* ------------------------------------------------------------ */
/** Get dependent beans of a specific class
* @see #addBean(Object)
* @param clazz
* @return List of beans.
*/
public <T> List<T> getBeans(Class<T> clazz)
{
ArrayList<T> beans = new ArrayList<T>();
Iterator<?> iter = _dependentBeans.iterator();
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
beans.add((T)o);
}
return beans;
}
/* ------------------------------------------------------------ */
/** Get dependent bean of a specific class.
* If more than one bean of the type exist, the first is returned.
* @see #addBean(Object)
* @param clazz
* @return bean or null
*/
public <T> T getBean(Class<T> clazz)
{
Iterator<?> iter = _dependentBeans.iterator();
T t=null;
int count=0;
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
{
count++;
if (t==null)
t=(T)o;
}
}
if (count>1)
Log.debug("getBean({}) 1 of {}",clazz.getName(),count);
return t;
}
/* ------------------------------------------------------------ */
/**
* Remove all associated bean.
*/
public void removeBeans ()
{
_dependentBeans.clear();
}
/* ------------------------------------------------------------ */
/**
* Remove an associated bean.
*/
public boolean removeBean (Object o)
{
if (o == null)
return false;
return _dependentBeans.remove(o);
}
/* ------------------------------------------------------------ */
public void dumpStdErr()
{
try
{
dump(System.err,"");
}
catch (IOException e)
{
Log.warn(e);
}
}
/* ------------------------------------------------------------ */
public String dump()
{
StringBuilder b = new StringBuilder();
try
{
dump(b,"");
}
catch (IOException e)
{
Log.warn(e);
}
return b.toString();
}
/* ------------------------------------------------------------ */
public void dump(Appendable out) throws IOException
{
dump(out,"");
}
/* ------------------------------------------------------------ */
protected void dumpThis(Appendable out) throws IOException
{
out.append(String.valueOf(this)).append("\n");
}
/* ------------------------------------------------------------ */
public void dump(Appendable out,String indent) throws IOException
{
dumpThis(out);
dump(out,indent,_dependentBeans);
}
/* ------------------------------------------------------------ */
public static void dump(Appendable out,String indent,Collection<?>... collections) throws IOException
{
if (collections.length==0)
return;
int size=0;
for (Collection<?> c : collections)
size+=c.size();
if (size==0)
return;
int i=0;
for (Collection<?> c : collections)
{
for (Object o : c)
{
i++;
out.append(indent).append(" +- ");
if (o instanceof Dumpable)
((Dumpable)o).dump(out,indent+(i==size?" ":" | "));
else
out.append(String.valueOf(o)).append("\n");
}
if (i!=size)
out.append(indent).append(" |\n");
}
}
}

View File

@ -0,0 +1,15 @@
package org.eclipse.jetty.util.component;
/**
* A Destroyable is an object which can be detroyed.
* <p>
* Typically a Destroyable is a {@link LifeCycle} component that can hold onto
* resources over multiple start/stop cycles. A call to destroy will release all
* resources and will prevent any further start/stop cycles from being successful.
*/
public interface Destroyable
{
void destroy();
}

View File

@ -0,0 +1,8 @@
package org.eclipse.jetty.util.component;
import java.io.IOException;
public interface Dumpable
{
void dump(Appendable out,String indent) throws IOException;
}

View File

@ -0,0 +1,164 @@
package org.eclipse.jetty.util.component;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import junit.framework.Assert;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.Test;
public class AggregateLifeCycleTest
{
@Test
public void testStartStopDestroy() throws Exception
{
final AtomicInteger destroyed=new AtomicInteger();
final AtomicInteger started=new AtomicInteger();
final AtomicInteger stopped=new AtomicInteger();
AggregateLifeCycle a0=new AggregateLifeCycle();
AggregateLifeCycle a1=new AggregateLifeCycle()
{
@Override
protected void doStart() throws Exception
{
started.incrementAndGet();
super.doStart();
}
@Override
protected void doStop() throws Exception
{
stopped.incrementAndGet();
super.doStop();
}
@Override
public void destroy()
{
destroyed.incrementAndGet();
super.destroy();
}
};
a0.addBean(a1);
a0.start();
Assert.assertEquals(1,started.get());
Assert.assertEquals(0,stopped.get());
Assert.assertEquals(0,destroyed.get());
a0.start();
Assert.assertEquals(1,started.get());
Assert.assertEquals(0,stopped.get());
Assert.assertEquals(0,destroyed.get());
a0.stop();
Assert.assertEquals(1,started.get());
Assert.assertEquals(1,stopped.get());
Assert.assertEquals(0,destroyed.get());
a0.start();
Assert.assertEquals(2,started.get());
Assert.assertEquals(1,stopped.get());
Assert.assertEquals(0,destroyed.get());
a0.stop();
Assert.assertEquals(2,started.get());
Assert.assertEquals(2,stopped.get());
Assert.assertEquals(0,destroyed.get());
a0.destroy();
Assert.assertEquals(2,started.get());
Assert.assertEquals(2,stopped.get());
Assert.assertEquals(1,destroyed.get());
a0.start();
Assert.assertEquals(2,started.get());
Assert.assertEquals(2,stopped.get());
Assert.assertEquals(1,destroyed.get());
a0.addBean(a1);
a0.start();
Assert.assertEquals(3,started.get());
Assert.assertEquals(2,stopped.get());
Assert.assertEquals(1,destroyed.get());
a0.removeBean(a1);
a0.stop();
a0.destroy();
Assert.assertEquals(3,started.get());
Assert.assertEquals(2,stopped.get());
Assert.assertEquals(1,destroyed.get());
a1.stop();
Assert.assertEquals(3,started.get());
Assert.assertEquals(3,stopped.get());
Assert.assertEquals(1,destroyed.get());
a1.destroy();
Assert.assertEquals(3,started.get());
Assert.assertEquals(3,stopped.get());
Assert.assertEquals(2,destroyed.get());
}
@Test
public void testDumpable()
{
AggregateLifeCycle a0 = new AggregateLifeCycle();
a0.dumpStdErr();
System.err.println("--");
AggregateLifeCycle aa0 = new AggregateLifeCycle();
a0.addBean(aa0);
a0.dumpStdErr();
System.err.println("--");
AggregateLifeCycle aa1 = new AggregateLifeCycle();
a0.addBean(aa1);
a0.dumpStdErr();
System.err.println("--");
AggregateLifeCycle aaa0 = new AggregateLifeCycle();
aa0.addBean(aaa0);
a0.dumpStdErr();
System.err.println("--");
AggregateLifeCycle aa10 = new AggregateLifeCycle();
aa1.addBean(aa10);
a0.dumpStdErr();
System.err.println("--");
final AggregateLifeCycle a1 = new AggregateLifeCycle();
final AggregateLifeCycle a2 = new AggregateLifeCycle();
final AggregateLifeCycle a3 = new AggregateLifeCycle();
final AggregateLifeCycle a4 = new AggregateLifeCycle();
AggregateLifeCycle aa = new AggregateLifeCycle()
{
@Override
public void dump(Appendable out, String indent) throws IOException
{
out.append(this.toString()).append("\n");
dump(out,indent,TypeUtil.asList(new Object[]{a1,a2}),TypeUtil.asList(new Object[]{a3,a4}));
}
};
a0.addBean(aa);
a0.dumpStdErr();
System.err.println("--");
a2.addBean(aa0);
a0.dumpStdErr();
}
}

View File

@ -18,6 +18,10 @@ public class AbstractConfiguration implements Configuration
{
}
public void destroy(WebAppContext context) throws Exception
{
}
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
{
}

View File

@ -58,6 +58,15 @@ public interface Configuration
* @throws Exception
*/
public void deconfigure (WebAppContext context) throws Exception;
/* ------------------------------------------------------------------------------- */
/** Destroy WebApp.
* This method is called to destroy a webappcontext. It is typically called when a context
* is removed from a server handler hierarchy by the deployer.
* @param context The context to configure
* @throws Exception
*/
public void destroy (WebAppContext context) throws Exception;
/* ------------------------------------------------------------------------------- */

View File

@ -431,6 +431,6 @@ public class WebAppClassLoader extends URLClassLoader
/* ------------------------------------------------------------ */
public String toString()
{
return "WebAppClassLoader@" + _name;
return "WebAppClassLoader=" + _name+"@"+Long.toHexString(hashCode());
}
}

View File

@ -43,6 +43,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@ -142,7 +143,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
private boolean _allowDuplicateFragmentNames = false;
private MetaData _metadata;
private MetaData _metadata=new MetaData();
public static WebAppContext getCurrentWebAppContext()
{
@ -161,20 +162,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
super(SESSIONS|SECURITY);
_scontext=new Context();
setErrorHandler(new ErrorPageErrorHandler());
//Make a new MetaData to hold descriptor and annotation metadata
_metadata = new MetaData();
}
/* ------------------------------------------------------------ */
public WebAppContext(WebAppContext template) throws IOException
{
super(SESSIONS|SECURITY);
if (template.isStarted())
throw new IllegalArgumentException("template is started");
_scontext=new Context();
setErrorHandler(new ErrorPageErrorHandler());
setTemplate(template);
setErrorHandler(new ErrorPageErrorHandler());
}
/* ------------------------------------------------------------ */
@ -188,9 +176,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_scontext=new Context();
setContextPath(contextPath);
setWar(webApp);
setErrorHandler(new ErrorPageErrorHandler());
//Make a new MetaData to hold descriptor and annotation metadata
_metadata = new MetaData();
setErrorHandler(new ErrorPageErrorHandler());
}
/* ------------------------------------------------------------ */
@ -204,9 +190,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super(parent,contextPath,SESSIONS|SECURITY);
_scontext=new Context();
setWar(webApp);
setErrorHandler(new ErrorPageErrorHandler());
//Make a new MetaData to hold descriptor and annotation metadata
_metadata = new MetaData();
setErrorHandler(new ErrorPageErrorHandler());
}
/* ------------------------------------------------------------ */
@ -223,48 +207,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super(null, sessionHandler, securityHandler, servletHandler, errorHandler);
_scontext = new Context();
setErrorHandler(errorHandler != null ? errorHandler : new ErrorPageErrorHandler());
//Make a new MetaData to hold descriptor and annotation metadata
_metadata = new MetaData();
}
/* ------------------------------------------------------------ */
/**
* Configure this WebAppContext from a shared WebAppContext as template.
* <p>The MetaData is reused from the template.
* @param template The template to base this webappcontext on
*/
public void setTemplate(WebAppContext template)
{
if (template==null)
throw new IllegalStateException("null template");
if (isRunning() || template.isRunning())
throw new IllegalStateException("Running");
//Make a new MetaData to hold descriptor and annotation metadata
_metadata = template.getMetaData();
_configurations = new Configuration[]{new CloneConfiguration(template)};
// TODO we need some better way to work out what attributes should be copied at this stage.
setAllowDuplicateFragmentNames(template.isAllowDuplicateFragmentNames());
setAliases(template.isAliases());
setBaseResource(template.getBaseResource());
setClassLoader(template.getClassLoader());
setContextPath(template.getContextPath());
setCompactPath(template.isCompactPath());
setDisplayName(template.getDisplayName());
setLogger(template.getLogger()); // TODO maybe not shared ???
setMaxFormContentSize(template.getMaxFormContentSize());
Enumeration<?> names=template.getAttributeNames();
while(names.hasMoreElements())
{
String name = (String)names.nextElement();
Object val = template.getAttribute(name);
if (!name.startsWith("javax.servlet."))
setAttribute(name,val);
}
}
/* ------------------------------------------------------------ */
@ -490,8 +432,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
try
{
if (_metadata != null)
_metadata.setAllowDuplicateFragmentNames(isAllowDuplicateFragmentNames());
_metadata.setAllowDuplicateFragmentNames(isAllowDuplicateFragmentNames());
preConfigure();
super.doStart();
postConfigure();
@ -507,25 +448,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
setAvailable(false);
}
}
/* ------------------------------------------------------------ */
/*
* Dumps the current web app name and URL to the log
*/
public void dumpUrl()
{
Connector[] connectors = getServer().getConnectors();
for (int i=0;i<connectors.length;i++)
{
String connectorName = connectors[i].getName();
String displayName = getDisplayName();
if (displayName == null)
displayName = "WebApp@"+connectors.hashCode();
Log.info(displayName + " at http://" + connectorName + getContextPath());
}
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
@ -540,9 +463,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
for (int i=_configurations.length;i-->0;)
_configurations[i].deconfigure(this);
_configurations=null;
if (_metadata != null)
_metadata.clear();
_metadata=new MetaData();
}
finally
@ -555,6 +478,50 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
}
/* ------------------------------------------------------------ */
@Override
public void destroy()
{
// Prepare for configuration
MultiException mx=new MultiException();
if (_configurations!=null)
{
for (int i=_configurations.length;i-->0;)
{
try
{
_configurations[i].destroy(this);
}
catch(Exception e)
{
mx.add(e);
}
}
}
_configurations=null;
super.destroy();
mx.ifExceptionThrowRuntime();
}
/* ------------------------------------------------------------ */
/*
* Dumps the current web app name and URL to the log
*/
private void dumpUrl()
{
Connector[] connectors = getServer().getConnectors();
for (int i=0;i<connectors.length;i++)
{
String connectorName = connectors[i].getName();
String displayName = getDisplayName();
if (displayName == null)
displayName = "WebApp@"+connectors.hashCode();
Log.info(displayName + " at http://" + connectorName + getContextPath());
}
}
/* ------------------------------------------------------------ */
/**
* @return Returns the configurations.
@ -833,9 +800,6 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
{
return super.toString()+(_war==null?"":(","+_war));
}
/* ------------------------------------------------------------ */
/**
@ -844,8 +808,11 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
*/
public void setConfigurationClasses(String[] configurations)
{
if (isRunning())
throw new IllegalStateException();
_configurationClasses = configurations==null?null:(String[])configurations.clone();
_configurationClassesSet = true;
_configurations=null;
}
/* ------------------------------------------------------------ */
@ -854,6 +821,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
*/
public void setConfigurations(Configuration[] configurations)
{
if (isRunning())
throw new IllegalStateException();
_configurations = configurations==null?null:(Configuration[])configurations.clone();
_configurationsSet = true;
}