Author: markt
Date: Mon May  3 21:40:52 2010
New Revision: 940634

URL: http://svn.apache.org/viewvc?rev=940634&view=rev
Log:
With the benefit of some sleep, refactor the MBean support for Lifecycle (still 
some components to convert)
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49134
Thanks to Marc Guillemot whose test case for 49134 provided the basis of 
o.a.c.mbeans.TestRegistration

Added:
    tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java   (with 
props)
    tomcat/trunk/test/org/apache/catalina/mbeans/TestRegistration.java
      - copied, changed from r940487, 
tomcat/trunk/test/org/apache/catalina/mbeans/RegistrationTest.java
Removed:
    tomcat/trunk/java/org/apache/catalina/LifecycleMBeanRegistration.java
    tomcat/trunk/test/org/apache/catalina/mbeans/RegistrationTest.java
Modified:
    tomcat/trunk/java/org/apache/catalina/connector/Connector.java
    tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
    tomcat/trunk/java/org/apache/catalina/core/StandardServer.java
    tomcat/trunk/java/org/apache/catalina/core/StandardService.java
    tomcat/trunk/java/org/apache/catalina/core/StandardThreadExecutor.java
    tomcat/trunk/java/org/apache/catalina/loader/WebappLoader.java
    tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java
    tomcat/trunk/java/org/apache/catalina/mbeans/MBeanUtils.java
    tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
    tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java
    tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties
    tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
    tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java

Modified: tomcat/trunk/java/org/apache/catalina/connector/Connector.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Connector.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/connector/Connector.java (original)
+++ tomcat/trunk/java/org/apache/catalina/connector/Connector.java Mon May  3 
21:40:52 2010
@@ -20,16 +20,14 @@ package org.apache.catalina.connector;
 
 import java.util.HashMap;
 
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Service;
 import org.apache.catalina.core.AprLifecycleListener;
-import org.apache.catalina.util.LifecycleBase;
+import org.apache.catalina.mbeans.MBeanUtils;
+import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.coyote.Adapter;
 import org.apache.coyote.ProtocolHandler;
@@ -37,7 +35,6 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.IntrospectionUtils;
 import org.apache.tomcat.util.http.mapper.Mapper;
-import org.apache.tomcat.util.modeler.Registry;
 
 
 /**
@@ -49,7 +46,7 @@ import org.apache.tomcat.util.modeler.Re
  */
 
 
-public class Connector extends LifecycleBase implements MBeanRegistration {
+public class Connector extends LifecycleMBeanBase  {
 
     private static final Log log = LogFactory.getLog(Connector.class);
 
@@ -796,12 +793,11 @@ public class Connector extends Lifecycle
     }
 
 
-    protected ObjectName createObjectName(String domain, String type)
-            throws MalformedObjectNameException {
+    protected String createObjectNameKeyProperties(String type) {
+        
         Object addressObj = getProperty("address");
 
-        StringBuilder sb = new StringBuilder(domain);
-        sb.append(":type=");
+        StringBuilder sb = new StringBuilder("type=");
         sb.append(type);
         sb.append(",port=");
         sb.append(getPort());
@@ -812,8 +808,7 @@ public class Connector extends Lifecycle
                 sb.append(ObjectName.quote(address));
             }
         }
-        ObjectName _oname = new ObjectName(sb.toString());
-        return _oname;
+        return sb.toString();
     }
 
 
@@ -843,6 +838,37 @@ public class Connector extends Lifecycle
     }
 
 
+    @Override
+    protected void initInternal() throws LifecycleException {
+
+        super.initInternal();
+        
+        // Initialize adapter
+        adapter = new CoyoteAdapter(this);
+        protocolHandler.setAdapter(adapter);
+
+        IntrospectionUtils.setProperty(protocolHandler, "jkHome",
+                                       System.getProperty("catalina.base"));
+
+        try {
+            protocolHandler.init();
+        } catch (Exception e) {
+            throw new LifecycleException
+                (sm.getString
+                 ("coyoteConnector.protocolHandlerInitializationFailed", e));
+        }
+
+        onameProtocolHandler = register(protocolHandler,
+                createObjectNameKeyProperties("ProtocolHandler"));
+        
+        mapperListener.setDomain(getDomain());
+        mapperListener.init();
+
+        onameMapper = register(mapperListener,
+                createObjectNameKeyProperties("Mapper"));
+    }
+
+
     /**
      * Begin processing requests via this Connector.
      *
@@ -853,23 +879,6 @@ public class Connector extends Lifecycle
 
         setState(LifecycleState.STARTING);
 
-        // We can't register earlier - the JMX registration of this happens
-        // in Server.start callback
-        if ( this.oname != null ) {
-            // We are registred - register the adapter as well.
-            try {
-                Registry.getRegistry(null, null).registerComponent
-                    (protocolHandler, 
createObjectName(this.domain,"ProtocolHandler"), null);
-            } catch (Exception ex) {
-                log.error(sm.getString
-                          ("coyoteConnector.protocolRegistrationFailed"), ex);
-            }
-        } else {
-            if(log.isInfoEnabled())
-                log.info(sm.getString
-                     ("coyoteConnector.cannotRegisterProtocol"));
-        }
-
         try {
             protocolHandler.start();
         } catch (Exception e) {
@@ -882,23 +891,6 @@ public class Connector extends Lifecycle
                 (errPrefix + " " + sm.getString
                  ("coyoteConnector.protocolHandlerStartFailed", e));
         }
-
-        if( this.domain != null ) {
-            mapperListener.setDomain( domain );
-            //mapperListener.setEngine( service.getContainer().getName() );
-            mapperListener.init();
-            try {
-                ObjectName mapperOname = 
createObjectName(this.domain,"Mapper");
-                if (log.isDebugEnabled())
-                    log.debug(sm.getString(
-                            "coyoteConnector.MapperRegistration", 
mapperOname));
-                Registry.getRegistry(null, null).registerComponent
-                    (mapper, mapperOname, "Mapper");
-            } catch (Exception ex) {
-                log.error(sm.getString
-                        ("coyoteConnector.protocolRegistrationFailed"), ex);
-            }
-        }
     }
 
 
@@ -912,16 +904,15 @@ public class Connector extends Lifecycle
 
         setState(LifecycleState.STOPPING);
 
-        try {
-            mapperListener.destroy();
-            Registry.getRegistry(null, null).unregisterComponent
-                (createObjectName(this.domain,"Mapper"));
-            Registry.getRegistry(null, null).unregisterComponent
-                (createObjectName(this.domain,"ProtocolHandler"));
-        } catch (MalformedObjectNameException e) {
-            log.error( sm.getString
-                    ("coyoteConnector.protocolUnregistrationFailed"), e);
-        }
+    }
+
+
+    @Override
+    protected void destroyInternal() throws LifecycleException {
+        mapperListener.destroy();
+        unregister(onameMapper);
+        unregister(onameProtocolHandler);
+        
         try {
             protocolHandler.destroy();
         } catch (Exception e) {
@@ -930,6 +921,11 @@ public class Connector extends Lifecycle
                  ("coyoteConnector.protocolHandlerDestroyFailed", e));
         }
 
+        if (getService() != null) {
+            getService().removeConnector(this);
+        }
+        
+        super.destroyInternal();
     }
 
 
@@ -948,92 +944,19 @@ public class Connector extends Lifecycle
         return sb.toString();
     }
 
-
     // -------------------- JMX registration  --------------------
-    protected String domain;
-    protected ObjectName oname;
-    protected MBeanServer mserver;
-
-    public ObjectName getObjectName() {
-        return oname;
-    }
-
-    public String getDomain() {
-        return domain;
-    }
-
-    public ObjectName preRegister(MBeanServer server,
-                                  ObjectName name) throws Exception {
-        oname=name;
-        mserver=server;
-        domain=name.getDomain();
-        return name;
-    }
-
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
-
-    public void preDeregister() throws Exception {
-        // NOOP
-    }
-
-    public void postDeregister() {
-        try {
-            if(getState().isAvailable()) {
-                stop();
-            }
-        } catch( Throwable t ) {
-            log.error( "Unregistering - can't stop", t);
-        }
-    }
-
 
+    private ObjectName onameProtocolHandler;
+    private ObjectName onameMapper;
+    
     @Override
-    protected void initInternal() throws LifecycleException {
-
-        if (oname == null) {
-            try {
-                // we are loaded directly, via API - and no name was given to 
us
-                // Engine name is used as domain name for MBeans
-                oname = createObjectName(
-                        getService().getContainer().getName(), "Connector");
-                Registry.getRegistry(null, null)
-                    .registerComponent(this, oname, null);
-            } catch (Exception e) {
-                log.error( "Error registering connector ", e);
-            }
-            if(log.isDebugEnabled())
-                log.debug("Creating name for connector " + oname);
-        }
-
-        // Initializa adapter
-        adapter = new CoyoteAdapter(this);
-        protocolHandler.setAdapter(adapter);
-
-        IntrospectionUtils.setProperty(protocolHandler, "jkHome",
-                                       System.getProperty("catalina.base"));
-
-        try {
-            protocolHandler.init();
-        } catch (Exception e) {
-            throw new LifecycleException
-                (sm.getString
-                 ("coyoteConnector.protocolHandlerInitializationFailed", e));
-        }
-
+    protected String getDomainInternal() {
+        return MBeanUtils.getDomain(getService());
     }
 
     @Override
-    protected void destroyInternal() {
-        if (oname!=null) {
-            if(log.isDebugEnabled())
-                 log.debug("Unregister itself " + oname );
-            Registry.getRegistry(null, null).unregisterComponent(oname);
-        }
-        if( getService() == null)
-            return;
-        getService().removeConnector(this);
+    protected String getObjectNameKeyProperties() {
+        return createObjectNameKeyProperties("Connector");
     }
 
 }

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Mon May  3 
21:40:52 2010
@@ -5014,6 +5014,23 @@ public class StandardContext
      */ 
     @Override
     protected void destroyInternal() throws LifecycleException {
+        
+        if ((manager != null) && (manager instanceof Lifecycle)) {
+            ((Lifecycle) manager).destroy();
+        }
+        if ((realm != null) && (realm instanceof Lifecycle)) {
+            ((Lifecycle) realm).destroy();
+        }
+        if ((cluster != null) && (cluster instanceof Lifecycle)) {
+            ((Lifecycle) cluster).destroy();
+        }
+        if ((logger != null) && (logger instanceof Lifecycle)) {
+            ((Lifecycle) logger).destroy();
+        }
+        if ((loader != null) && (loader instanceof Lifecycle)) {
+            ((Lifecycle) loader).destroy();
+        }
+
         if( oname != null ) { 
             // Send j2ee.object.deleted notification 
             Notification notification = 
@@ -5029,7 +5046,6 @@ public class StandardContext
         synchronized (instanceListenersLock) {
             instanceListeners = new String[0];
         }
-
     }
     
     private void resetContext() throws Exception {

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardServer.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardServer.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardServer.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardServer.java Mon May  3 
21:40:52 2010
@@ -29,27 +29,24 @@ import java.net.Socket;
 import java.security.AccessControlException;
 import java.util.Random;
 
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
-import org.apache.catalina.Globals;
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleMBeanRegistration;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Server;
 import org.apache.catalina.Service;
 import org.apache.catalina.deploy.NamingResources;
 import org.apache.catalina.mbeans.MBeanFactory;
+import org.apache.catalina.mbeans.MBeanUtils;
 import org.apache.catalina.util.LifecycleBase;
+import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.catalina.util.ServerInfo;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.buf.StringCache;
-import org.apache.tomcat.util.modeler.Registry;
 
 
 /**
@@ -59,8 +56,8 @@ import org.apache.tomcat.util.modeler.Re
  * @author Craig R. McClanahan
  * @version $Id$
  */
-public final class StandardServer extends LifecycleBase
-        implements Server, LifecycleMBeanRegistration {
+public final class StandardServer extends LifecycleMBeanBase
+        implements Server {
 
     private static final Log log = LogFactory.getLog(StandardServer.class);
    
@@ -684,29 +681,17 @@ public final class StandardServer extend
      */
     @Override
     protected void initInternal() throws LifecycleException {
+        
+        super.initInternal();
 
         // Register global String cache
         // Note although the cache is global, if there are multiple Servers
         // present in the JVM (may happen when embedding) then the same cache
         // will be registered under multiple names
-        try {
-            onameStringCache = 
-                new ObjectName(oname.getDomain() + ":type=StringCache");
-            Registry.getRegistry(null, null)
-                .registerComponent(new StringCache(), onameStringCache, null);
-        } catch (Exception e) {
-            log.error("Error registering ",e);
-        }
+        onameStringCache = register(new StringCache(), "type=StringCache");
 
         // Register the MBeanFactory
-        try {
-            onameMBeanFactory = 
-                new ObjectName(oname.getDomain() + ":type=MBeanFactory");
-            Registry.getRegistry(null, null)
-                .registerComponent(new MBeanFactory(), onameMBeanFactory, 
null);
-        } catch (Exception e) {
-            log.error("Error registering ",e);
-        }
+        onameMBeanFactory = register(new MBeanFactory(), "type=MBeanFactory");
         
         // Initialize our defined Services
         for (int i = 0; i < services.length; i++) {
@@ -716,24 +701,18 @@ public final class StandardServer extend
     
     @Override
     protected void destroyInternal() throws LifecycleException {
-        Registry registry = Registry.getRegistry(null, null);
-        
-        if (onameStringCache != null) {
-            registry.unregisterComponent(onameStringCache);
-        }
-        if (onameMBeanFactory != null) {
-            registry.unregisterComponent(onameMBeanFactory);
-        }
-        
         // Destroy our defined Services
         for (int i = 0; i < services.length; i++) {
             services[i].destroy();
         }
+
+        unregister(onameMBeanFactory);
+        
+        unregister(onameStringCache);
+        
+        super.destroyInternal();
     }
 
-    protected volatile String domain;
-    protected volatile ObjectName oname;
-    protected MBeanServer mserver;
     private ObjectName onameStringCache;
     private ObjectName onameMBeanFactory;
     
@@ -743,72 +722,27 @@ public final class StandardServer extend
      * <ol>
      * <li>Name of first {...@link Engine}.</li>
      * <li>Name of first {...@link Service}.</li>
-     * <li>Global default defined by {...@link 
Globals#DEFAULT_MBEAN_DOMAIN}</li>
      * </ol>
      */
-    public String getDomain() {
-        if (domain == null) {
-            Service[] services = findServices();
-            if (services.length > 0) {
-                Service service = services[0];
-                if (service != null) {
-                    Container container = service.getContainer();
-                    if (container != null) {
-                        domain = container.getName();
-                    } else {
-                        domain = service.getName();
-                    }
-                }
-            }
-            if (domain == null) {
-                domain = Globals.DEFAULT_MBEAN_DOMAIN;
+    @Override
+    protected String getDomainInternal() {
+        
+        String domain = null;
+        
+        Service[] services = findServices();
+        if (services.length > 0) {
+            Service service = services[0];
+            if (service != null) {
+                domain = MBeanUtils.getDomain(service);
             }
         }
         return domain;
     }
 
     
-    public void setDomain(String domain) {
-        this.domain = domain;
-    }
-    
-    
-    public ObjectName getObjectName() {
-        if (oname == null) {
-            StringBuilder name = new StringBuilder(getDomain());
-            name.append(":type=Server");
-            
-            try {
-                oname = new ObjectName(name.toString());
-            } catch (MalformedObjectNameException e) {
-                log.warn(sm.getString("standardServer.onameFail", name), e);
-            } catch (NullPointerException e) {
-                // Never going to happen
-            }
-        }
-        
-        return oname;
-    }
-
-
-    public ObjectName preRegister(MBeanServer server,
-                                  ObjectName name) throws Exception {
-        oname = name;
-        mserver = server;
-        domain = name.getDomain();
-        return name;
-    }
-
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
-
-    public void preDeregister() throws Exception {
-        // NOOP
+    @Override
+    protected final String getObjectNameKeyProperties() {
+        return "type=Server";
     }
 
-    public void postDeregister() {
-        // NOOP
-    }
-    
 }

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardService.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardService.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardService.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardService.java Mon May  3 
21:40:52 2010
@@ -21,24 +21,21 @@ package org.apache.catalina.core;
 
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 import org.apache.catalina.Container;
 import org.apache.catalina.Engine;
-import org.apache.catalina.Globals;
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleMBeanRegistration;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Server;
 import org.apache.catalina.Service;
 import org.apache.catalina.connector.Connector;
+import org.apache.catalina.mbeans.MBeanUtils;
 import org.apache.catalina.util.LifecycleBase;
+import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.modeler.Registry;
 import java.util.ArrayList;
 import org.apache.catalina.Executor;
 
@@ -51,8 +48,7 @@ import org.apache.catalina.Executor;
  * @author Craig R. McClanahan
  */
 
-public class StandardService extends LifecycleBase
-        implements Service, LifecycleMBeanRegistration {
+public class StandardService extends LifecycleMBeanBase implements Service {
 
     private static final Log log = LogFactory.getLog(StandardService.class);
    
@@ -509,14 +505,16 @@ public class StandardService extends Lif
     @Override
     protected void initInternal() throws LifecycleException {
 
+        super.initInternal();
+        
         if (container != null) {
             container.init();
         }
 
         // Initialize any Executors
         for (Executor executor : findExecutors()) {
-            if (executor instanceof LifecycleMBeanRegistration) {
-                ((LifecycleMBeanRegistration) executor).setDomain(getDomain());
+            if (executor instanceof LifecycleMBeanBase) {
+                ((LifecycleMBeanBase) executor).setDomain(getDomain());
             }
             executor.init();
         }
@@ -537,8 +535,6 @@ public class StandardService extends Lif
     
     @Override
     protected void destroyInternal() throws LifecycleException {
-        Registry.getRegistry(null, null).unregisterComponent(oname);
-        
         // Destroy our defined Connectors
         synchronized (connectors) {
             for (Connector connector : connectors) {
@@ -561,72 +557,17 @@ public class StandardService extends Lif
             container.destroy();
         }
 
+        super.destroyInternal();
     }
 
-    protected volatile String domain;
-    protected volatile ObjectName oname;
-
-    /**
-     * Obtain the MBean domain for this server. The domain is obtained using
-     * the following search order:
-     * <ol>
-     * <li>Name of the {...@link Engine}.</li>
-     * <li>Name of the {...@link Service}.</li>
-     * <li>Global default defined by {...@link 
Globals#DEFAULT_MBEAN_DOMAIN}</li>
-     * </ol>
-     */
-    public String getDomain() {
-        if (domain == null) {
-            Container container = getContainer();
-            if (container != null) {
-                domain = container.getName();
-            } else {
-                domain = getName();
-            }
-            if (domain == null) {
-                domain = Globals.DEFAULT_MBEAN_DOMAIN;
-            }
-        }
-        return domain;
-    }
-
-    public void setDomain(String domain) {
-        this.domain = domain;
-    }
-    
-    public ObjectName getObjectName() {
-        if (oname == null) {
-            StringBuilder name = new StringBuilder(getDomain());
-            name.append(":type=Service");
-            
-            try {
-                oname = new ObjectName(name.toString());
-            } catch (MalformedObjectNameException e) {
-                log.warn(sm.getString("standardService.onameFail", name), e);
-            } catch (NullPointerException e) {
-                // Never going to happen
-            }
-        }
+    @Override
+    protected String getDomainInternal() {
         
-        return oname;
-    }
-    public ObjectName preRegister(MBeanServer server,
-                                  ObjectName name) throws Exception {
-        oname=name;
-        domain=name.getDomain();
-        return name;
+        return MBeanUtils.getDomain(this);
     }
 
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
-
-    public void preDeregister() throws Exception {
-        // NOOP
-    }
-
-    public void postDeregister() {
-        // NOOP
+    @Override
+    public final String getObjectNameKeyProperties() {
+        return "type=Service";
     }
-
 }

Modified: tomcat/trunk/java/org/apache/catalina/core/StandardThreadExecutor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardThreadExecutor.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/StandardThreadExecutor.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/core/StandardThreadExecutor.java Mon 
May  3 21:40:52 2010
@@ -20,35 +20,19 @@ package org.apache.catalina.core;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
 
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-
 import org.apache.catalina.Executor;
 import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleMBeanRegistration;
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.util.LifecycleBase;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.res.StringManager;
+import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.tomcat.util.threads.ResizableExecutor;
 import org.apache.tomcat.util.threads.TaskQueue;
 import org.apache.tomcat.util.threads.TaskThreadFactory;
 import org.apache.tomcat.util.threads.ThreadPoolExecutor;
 
-public class StandardThreadExecutor extends LifecycleBase
-        implements Executor, ResizableExecutor, LifecycleMBeanRegistration {
-    
-    private static final Log log =
-        LogFactory.getLog(StandardThreadExecutor.class);
+public class StandardThreadExecutor extends LifecycleMBeanBase
+        implements Executor, ResizableExecutor {
     
-    /**
-     * The string manager for this package.
-     */
-    private static final StringManager sm =
-        StringManager.getManager(Constants.Package);
-
     // ---------------------------------------------- Properties
     /**
      * Default thread priority
@@ -308,57 +292,16 @@ public class StandardThreadExecutor exte
     }
     
 
-    protected volatile String domain;
-    protected volatile ObjectName oname;
-
-    /**
-     * Obtain the MBean domain for this server. The domain is set by the
-     * containing Service.
-     */
-    public String getDomain() {
-        return domain;
-    }
-
-    public void setDomain(String domain) {
-        this.domain = domain;
-    }
-    
-    public ObjectName getObjectName() {
-        if (oname == null) {
-            StringBuilder name = new StringBuilder(getDomain());
-            name.append(":type=Executor,name=");
-            name.append(getName());
-            
-            try {
-                oname = new ObjectName(name.toString());
-            } catch (MalformedObjectNameException e) {
-                log.warn(sm.getString(
-                        "standardThreadExecutor.onameFail", name), e);
-            } catch (NullPointerException e) {
-                // Never going to happen
-            }
-        }
-        
-        return oname;
-    }
-    
-    public ObjectName preRegister(MBeanServer server,
-                                  ObjectName name) throws Exception {
-        oname=name;
-        domain=name.getDomain();
-        return name;
-    }
-
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
-
-    public void preDeregister() throws Exception {
-        // NOOP
+    @Override
+    protected String getDomainInternal() {
+        // No way to navigate to Engine. Needs to have domain set.
+        return null;
     }
 
-    public void postDeregister() {
-        // NOOP
+    @Override
+    protected String getObjectNameKeyProperties() {
+        StringBuilder name = new StringBuilder("type=Executor,name=");
+        name.append(getName());
+        return name.toString();
     }
-    
 }

Modified: tomcat/trunk/java/org/apache/catalina/loader/WebappLoader.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/loader/WebappLoader.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/loader/WebappLoader.java (original)
+++ tomcat/trunk/java/org/apache/catalina/loader/WebappLoader.java Mon May  3 
21:40:52 2010
@@ -37,8 +37,6 @@ import java.net.URLStreamHandlerFactory;
 import java.util.ArrayList;
 import java.util.jar.JarFile;
 
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
 import javax.management.ObjectName;
 import javax.naming.NameClassPair;
 import javax.naming.NamingEnumeration;
@@ -54,7 +52,9 @@ import org.apache.catalina.LifecycleExce
 import org.apache.catalina.LifecycleState;
 import org.apache.catalina.Loader;
 import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.mbeans.MBeanUtils;
 import org.apache.catalina.util.LifecycleBase;
+import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.naming.resources.DirContextURLStreamHandler;
 import org.apache.naming.resources.DirContextURLStreamHandlerFactory;
@@ -80,8 +80,8 @@ import org.apache.tomcat.util.modeler.Re
  * @version $Id$
  */
 
-public class WebappLoader extends LifecycleBase
-    implements Loader, PropertyChangeListener, MBeanRegistration  {
+public class WebappLoader extends LifecycleMBeanBase
+    implements Loader, PropertyChangeListener {
 
     // ----------------------------------------------------------- Constructors
 
@@ -526,41 +526,6 @@ public class WebappLoader extends Lifecy
     }
 
 
-    @Override
-    protected void initInternal() {
-
-        if( oname==null ) {
-            // not registered yet - standalone or API
-            if( container instanceof StandardContext) {
-                // Register ourself. The container must be a webapp
-                try {
-                    StandardContext ctx=(StandardContext)container;
-                    String path = ctx.getPath();
-                    if (path.equals("")) {
-                        path = "/";
-                    }   
-                    oname=new ObjectName(ctx.getEngineName() + 
":type=Loader,path=" +
-                                path + ",host=" + ctx.getParent().getName());
-                    Registry.getRegistry(null, null).registerComponent(this, 
oname, null);
-                } catch (Exception e) {
-                    log.error("Error registering loader", e );
-                }
-            }
-        }
-
-        if( container == null ) {
-            // JMX created the loader
-            // TODO
-
-        }
-    }
-
-    @Override
-    protected void destroyInternal() {
-        Registry.getRegistry(null, null).unregisterComponent(oname);
-        oname = null;
-    }
-
     /**
      * Start associated {...@link ClassLoader} and implement the requirements
      * of {...@link LifecycleBase#startInternal()}.
@@ -1188,23 +1153,37 @@ public class WebappLoader extends Lifecy
     private static final org.apache.juli.logging.Log log=
         org.apache.juli.logging.LogFactory.getLog( WebappLoader.class );
 
-    private ObjectName oname;
 
-    public ObjectName preRegister(MBeanServer server,
-                                  ObjectName name) throws Exception {
-        oname=name;
-        return name;
+    @Override
+    protected String getDomainInternal() {
+        return MBeanUtils.getDomain(container);
     }
 
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
 
-    public void preDeregister() throws Exception {
-        // NOOP
+    @Override
+    protected String getObjectNameKeyProperties() {
+        
+        StringBuilder name = new StringBuilder("type=Loader");
+        
+        if (container instanceof Context) {
+            name.append(",path=");
+            Context context = (Context) container;
+            
+            String path = context.getPath();
+            if (path.equals("")) {
+                path = "/";
+            }   
+            name.append(path);
+            
+            name.append(",host=");
+            name.append(context.getParent().getName());
+        } else {
+            // Unlikely / impossible? Handle it to be safe
+            name.append(",container=");
+            name.append(container.getName());
+        }
+        
+        return name.toString();
     }
 
-    public void postDeregister() {
-        // NOOP
-    }
 }

Modified: tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java (original)
+++ tomcat/trunk/java/org/apache/catalina/mbeans/MBeanFactory.java Mon May  3 
21:40:52 2010
@@ -83,11 +83,10 @@ public class MBeanFactory {
      * @exception RuntimeOperationsException if an IllegalArgumentException
      *  occurs
      */
-    public MBeanFactory()
-        throws MBeanException, RuntimeOperationsException {
+    public MBeanFactory() {
 
         super();
-
+        
     }
 
 

Modified: tomcat/trunk/java/org/apache/catalina/mbeans/MBeanUtils.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/MBeanUtils.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mbeans/MBeanUtils.java (original)
+++ tomcat/trunk/java/org/apache/catalina/mbeans/MBeanUtils.java Mon May  3 
21:40:52 2010
@@ -1616,4 +1616,62 @@ public class MBeanUtils {
 
     }
 
+    
+    /**
+     * Determine the name of the domain to register MBeans for from a given
+     * Service.
+     * 
+     * @param service 
+     * @return
+     */
+    public static String getDomain(Service service) {
+        
+        // Null service -> return null
+        if (service == null) {
+            return null;
+        }
+        
+        String domain = null;
+        
+        Container engine = service.getContainer();
+        
+        // Use the engine name first
+        if (engine != null) {
+            domain = engine.getName();
+        }
+        
+        // No engine or no engine name, use the service name 
+        if (domain == null) {
+            domain = service.getName();
+        }
+        
+        // No service name, use null
+        return domain;
+    }
+    
+
+    /**
+     * Determine the name of the domain to register MBeans for from a given
+     * Container.
+     * 
+     * @param container 
+     * @return
+     */
+    public static String getDomain(Container container) {
+        
+        String domain = null;
+        
+        Container c = container;
+        
+        while (!(c instanceof Engine)) {
+            c = c.getParent();
+        }
+        
+        if (c instanceof Engine) {
+            domain = c.getName();
+        }
+        
+        return domain;
+    }
+
 }

Modified: tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java Mon May  3 
21:40:52 2010
@@ -320,7 +320,7 @@ public class Tomcat {
     public void destroy() throws LifecycleException {
         getServer();
         server.destroy();
-        // Could null out obejcts here
+        // Could null out objects here
     }
     
     /** 

Modified: tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java (original)
+++ tomcat/trunk/java/org/apache/catalina/util/LifecycleBase.java Mon May  3 
21:40:52 2010
@@ -17,16 +17,12 @@
 
 package org.apache.catalina.util;
 
-import javax.management.ObjectName;
-
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleException;
 import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.LifecycleMBeanRegistration;
 import org.apache.catalina.LifecycleState;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.modeler.Registry;
 import org.apache.tomcat.util.res.StringManager;
 
 
@@ -99,20 +95,6 @@ public abstract class LifecycleBase impl
             invalidTransition(Lifecycle.INIT_EVENT);
         }
 
-        // Register MBean if required
-        if (this instanceof LifecycleMBeanRegistration) {
-            ObjectName oname =
-                ((LifecycleMBeanRegistration) this).getObjectName();
-            
-            try {
-                Registry.getRegistry(null, null).registerComponent(
-                        this, oname, null);
-            } catch (Exception e) {
-                log.warn(sm.getString("lifecycleBase.initMBeanFail", 
toString(),
-                        oname), e);
-            }
-        }
-        
         initInternal();
         
         setState(LifecycleState.INITIALIZED);
@@ -279,13 +261,6 @@ public abstract class LifecycleBase impl
 
         destroyInternal();
         
-        // De-register MBean if required
-        if (this instanceof LifecycleMBeanRegistration) {
-            ObjectName oname =
-                ((LifecycleMBeanRegistration) this).getObjectName();
-            Registry.getRegistry(null, null).unregisterComponent(oname);
-        }
-
         setState(LifecycleState.DESTROYED);
     }
     

Added: tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java?rev=940634&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java (added)
+++ tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java Mon May  
3 21:40:52 2010
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.catalina.util;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.catalina.Globals;
+import org.apache.catalina.LifecycleException;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.modeler.Registry;
+import org.apache.tomcat.util.res.StringManager;
+
+public abstract class LifecycleMBeanBase extends LifecycleBase
+        implements MBeanRegistration {
+
+    private static Log log = LogFactory.getLog(LifecycleMBeanBase.class);
+    
+    private static StringManager sm =
+        StringManager.getManager("org.apache.catalina.util");
+
+    
+    /* Cache components of the MBean registration. */
+    private String domain = null;
+    private ObjectName oname = null;
+    protected MBeanServer mserver = null;
+    
+    /**
+     * Sub-classes wishing to perform additional initialization should override
+     * this method, ensuring that super.initInternal() is the first call in the
+     * overriding method.
+     */
+    @Override
+    protected void initInternal() throws LifecycleException {
+        
+        // If oname is not null then registration has already happened via
+        // preRegister().
+        if (oname == null) {
+            mserver = Registry.getRegistry(null, null).getMBeanServer();
+            
+            oname = register(this, getObjectNameKeyProperties());
+        }
+    }
+
+    
+    /**
+     * Sub-classes wishing to perform additional clean-up should override this
+     * method, ensuring that super.destroyInternal() is the last call in the
+     * overriding method.
+     */
+    @Override
+    protected void destroyInternal() throws LifecycleException {
+        unregister(oname);
+    }
+
+    
+    /**
+     * Specify the domain under which this component should be registered. Used
+     * with components that cannot (easily) navigate the component hierarchy to
+     * determine the correct domain to use. 
+     */
+    public final void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    
+    /**
+     * Obtain the domain under which this component will be / has been
+     * registered.
+     */
+    public String getDomain() {
+        if (domain == null) {
+            domain = getDomainInternal();
+        }
+
+        if (domain == null) {
+            domain = Globals.DEFAULT_MBEAN_DOMAIN;
+        }
+        
+        return domain;
+    }
+
+    
+    /**
+     * Method implemented by sub-classes to identify the domain in which MBeans
+     * should be registered.
+     * 
+     * @return  The name of the domain to use to register MBeans.
+     */
+    protected abstract String getDomainInternal();
+
+    
+    /**
+     * Obtain the name under which this component has been registered with JMX.
+     */
+    public final ObjectName getObjectName() {
+        return oname;
+    }
+
+
+    /**
+     * Allow sub-classes to specify the key properties component of the
+     * {...@link ObjectName} that will be used to register this component.
+     * 
+     * @return  The string representation of the key properties component of 
the
+     *          desired {...@link ObjectName}
+     */
+    protected abstract String getObjectNameKeyProperties();
+    
+    
+    /**
+     * Utility method to enable sub-classes to easily register additional
+     * components that don't implement {...@link LifecycleMBeanRegistration} 
with
+     * an MBean server.<br/>
+     * Note: This method can only be used once {...@link #initInternal()} has 
been
+     * called. 
+     * 
+     * @param obj                       The object the register
+     * @param objectNameKeyProperties   The key properties component of the
+     *                                  object name to use to register the
+     *                                  object
+     *
+     * @return  The name used to register the object
+     */
+    protected final ObjectName register(Object obj,
+            String objectNameKeyProperties) {
+        
+        // Construct an object name with the right domain
+        StringBuilder name = new StringBuilder(getDomain());
+        name.append(':');
+        name.append(objectNameKeyProperties);
+
+        ObjectName on = null;
+
+        try {
+            on = new ObjectName(name.toString());
+            
+            Registry.getRegistry(null, null).registerComponent(obj, on, null);
+        } catch (MalformedObjectNameException e) {
+            log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, 
name),
+                    e);
+        } catch (Exception e) {
+            log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, 
name),
+                    e);
+        }
+
+        return on;
+    }
+    
+    
+    /**
+     * Utility method to enable sub-classes to easily unregister additional
+     * components that don't implement {...@link LifecycleMBeanRegistration} 
with
+     * an MBean server.
+     * @param on    The name of the component to unregister
+     */
+    protected final void unregister(ObjectName on) {
+        
+        // If null ObjectName, just return without complaint
+        if (on == null) {
+            return;
+        }
+        
+        // If the MBeanServer is null, log a warning & return
+        if (mserver == null) {
+            log.warn(sm.getString("lifecycleMBeanBase.unregisterNoServer", 
on));
+            return;
+        }
+        
+        try {
+            mserver.unregisterMBean(on);
+        } catch (MBeanRegistrationException e) {
+            log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e);
+        } catch (InstanceNotFoundException e) {
+            log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e);
+        }
+
+    }
+    
+    
+    /**
+     * Not used - NOOP.
+     */
+    @Override
+    public final void postDeregister() {
+        // NOOP
+    }
+
+    
+    /**
+     * Not used - NOOP.
+     */
+    @Override
+    public final void postRegister(Boolean registrationDone) {
+        // NOOP
+    }
+
+    
+    /**
+     * Not used - NOOP.
+     */
+    @Override
+    public final void preDeregister() throws Exception {
+        // NOOP
+    }
+
+
+    /**
+     * Allows the object to be registered with an alternative
+     * {...@link MBeanServer} and/or {...@link ObjectName}.
+     */
+    @Override
+    public final ObjectName preRegister(MBeanServer server, ObjectName name)
+            throws Exception {
+        
+        this.mserver = server;
+        this.oname = name;
+        this.domain = name.getDomain();
+
+        return oname;
+    }
+
+}

Propchange: tomcat/trunk/java/org/apache/catalina/util/LifecycleMBeanBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/util/LocalStrings.properties Mon May  
3 21:40:52 2010
@@ -27,6 +27,9 @@ lifecycleBase.alreadyStarted=The start()
 lifecycleBase.alreadyStopped=The stop() method was called on component [{0}] 
after stop() had already been called. The second call will be ignored.
 lifecycleBase.alreadyDestroyed=The destroy() method was called on component 
[{0}] after destroy() had already been called. The second call will be ignored.
 lifecycleBase.invalidTransition=An invalid Lifecycle transition was attempted 
([{0}]) for component [{1}] in state [{2}]
+lifecycleMBeanBase.registerFail=Failed to register object [{0}] with name 
[{0}] during component initialisation
+lifecycleMBeanBase.unregisterFail=Failed to unregister MBean with name [{0}] 
during component destruction
+lifecycleMBeanBase.unregisterNoServer=No MBean server was available to 
unregister the MBean [{0}]
 requestUtil.convertHexDigit.notHex=[{0}] is not a hexadecimal digit
 requestUtil.parseParameters.uee=Unable to parse the parameters since the 
encoding [{0}] is not supported.
 requestUtil.urlDecode.missingDigit=The % character must be followed by two 
hexademical digits

Modified: tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Protocol.java Mon May  3 
21:40:52 2010
@@ -160,6 +160,11 @@ public class Http11Protocol extends Abst
     }
 
 
+    @Override
+    public void destroy() throws Exception {
+        cHandler.recycledProcessors.clear();
+        super.destroy();
+    }
     // ------------------------------------------------------------- Properties
 
     

Copied: tomcat/trunk/test/org/apache/catalina/mbeans/TestRegistration.java 
(from r940487, 
tomcat/trunk/test/org/apache/catalina/mbeans/RegistrationTest.java)
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/mbeans/TestRegistration.java?p2=tomcat/trunk/test/org/apache/catalina/mbeans/TestRegistration.java&p1=tomcat/trunk/test/org/apache/catalina/mbeans/RegistrationTest.java&r1=940487&r2=940634&rev=940634&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/mbeans/RegistrationTest.java 
(original)
+++ tomcat/trunk/test/org/apache/catalina/mbeans/TestRegistration.java Mon May  
3 21:40:52 2010
@@ -32,7 +32,7 @@ import org.apache.tomcat.util.modeler.Re
  * don't necessarily apply to one specific Tomcat class.
  *
  */
-public class RegistrationTest extends TomcatBaseTest {
+public class TestRegistration extends TomcatBaseTest {
 
     /**
      * Test verifying that Tomcat correctly de-registers the MBeans it has

Modified: tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java?rev=940634&r1=940633&r2=940634&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java (original)
+++ tomcat/trunk/test/org/apache/catalina/startup/TomcatBaseTest.java Mon May  
3 21:40:52 2010
@@ -33,6 +33,8 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleState;
 import org.apache.tomcat.util.buf.ByteChunk;
 
 import junit.framework.TestCase;
@@ -103,7 +105,12 @@ public abstract class TomcatBaseTest ext
     
     @Override
     public void tearDown() throws Exception {
-        tomcat.stop();
+        // Some tests may call tomcat.destroy(). In which case, don't
+        // call stop()
+        if (tomcat.server != null &&
+                tomcat.server.getState() != LifecycleState.DESTROYED) {
+            tomcat.stop();
+        }
         ExpandWar.delete(tempDir);
     }
     



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to