296765 JMX Connector Server and ShutdownThread
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1140 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
9825a4282b
commit
3fea82d8a4
|
@ -1,6 +1,7 @@
|
|||
jetty-7.0.2-SNAPSHOT
|
||||
+ JSON parses NaN as null
|
||||
+ 290765 Reset input for HttpExchange retry.
|
||||
+ 296765 JMX Connector Server and ShutdownThread
|
||||
+ 297421 Hide server/system classes from WebAppClassLoader.getResources
|
||||
|
||||
jetty-7.0.1.v20091125 25 November 2009
|
||||
|
|
|
@ -9,51 +9,62 @@
|
|||
<!-- =============================================================== -->
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Initialize an mbean server -->
|
||||
<!-- =========================================================== -->
|
||||
<Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/>
|
||||
<!-- =========================================================== -->
|
||||
<!-- Initialize an mbean server -->
|
||||
<!-- =========================================================== -->
|
||||
<Call id="MBeanServer" class="java.lang.management.ManagementFactory"
|
||||
name="getPlatformMBeanServer" />
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Initialize the Jetty MBean container -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="MBeanContainer" class="org.eclipse.jetty.jmx.MBeanContainer">
|
||||
<Arg><Ref id="MBeanServer"/></Arg>
|
||||
</New>
|
||||
<!-- =========================================================== -->
|
||||
<!-- Initialize the Jetty MBean container -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="MBeanContainer" class="org.eclipse.jetty.jmx.MBeanContainer">
|
||||
<Arg>
|
||||
<Ref id="MBeanServer" />
|
||||
</Arg>
|
||||
</New>
|
||||
|
||||
<!-- Add to the Server to listen for object events -->
|
||||
<Get id="Container" name="container">
|
||||
<Call name="addEventListener">
|
||||
<Arg><Ref id="MBeanContainer"/></Arg>
|
||||
</Call>
|
||||
</Get>
|
||||
|
||||
<!-- Add to the Server as a lifecycle -->
|
||||
<!-- Only do this if you know you will only have a single jetty server -->
|
||||
<Call name="addBean">
|
||||
<Arg><Ref id="MBeanContainer"/></Arg>
|
||||
</Call>
|
||||
|
||||
<!-- Add the static log -->
|
||||
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log"/>
|
||||
<Ref id="MBeanContainer">
|
||||
<Call name="addBean">
|
||||
<Arg><Ref id="Logger"/></Arg>
|
||||
</Call>
|
||||
</Ref>
|
||||
|
||||
<!-- optionally add a remote JMX connector
|
||||
<Call id="jmxConnector" class="javax.management.remote.JMXConnectorServerFactory" name="newJMXConnectorServer">
|
||||
<!-- Add to the Server to listen for object events -->
|
||||
<Get id="Container" name="container">
|
||||
<Call name="addEventListener">
|
||||
<Arg>
|
||||
<New class="javax.management.remote.JMXServiceURL">
|
||||
<Arg>service:jmx:rmi:///jndi/rmi:///jettymbeanserver</Arg>
|
||||
</New>
|
||||
<Ref id="MBeanContainer" />
|
||||
</Arg>
|
||||
<Arg/>
|
||||
<Arg><Ref id="MBeanServer"/></Arg>
|
||||
<Call name="start"/>
|
||||
</Call>
|
||||
-->
|
||||
</Get>
|
||||
|
||||
<!-- Add to the Server as a lifecycle -->
|
||||
<!-- Only do this if you know you will only have a single jetty server -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<Ref id="MBeanContainer" />
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- Add the static log -->
|
||||
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" />
|
||||
<Ref id="MBeanContainer">
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<Ref id="Logger" />
|
||||
</Arg>
|
||||
</Call>
|
||||
</Ref>
|
||||
|
||||
<!-- optionally add a remote JMX connector
|
||||
<New id="ConnectorServer" class="org.eclipse.jetty.jmx.ConnectorServer">
|
||||
<Arg>
|
||||
<New class="javax.management.remote.JMXServiceURL">
|
||||
<Arg type="java.lang.String">rmi</Arg>
|
||||
<Arg type="java.lang.String" />
|
||||
<Arg type="java.lang.Integer">0</Arg>
|
||||
<Arg type="java.lang.String">/jndi/rmi://localhost:1099/jettyjmx</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
<Arg>org.eclipse.jetty:name=rmiconnectorserver</Arg>
|
||||
<Call name="start" />
|
||||
</New>
|
||||
-->
|
||||
|
||||
</Configure>
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.jmx;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.thread.ShutdownThread;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* AbstractLifeCycle wrapper for JMXConnector Server
|
||||
*/
|
||||
public class ConnectorServer extends AbstractLifeCycle
|
||||
{
|
||||
JMXConnectorServer _connectorServer;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Constructs connector server
|
||||
*
|
||||
* @param serviceURL the address of the new connector server.
|
||||
* The actual address of the new connector server, as returned
|
||||
* by its getAddress method, will not necessarily be exactly the same.
|
||||
* @param name object name string to be assigned to connector server bean
|
||||
* @throws Exception
|
||||
*/
|
||||
public ConnectorServer(JMXServiceURL serviceURL, String name)
|
||||
throws Exception
|
||||
{
|
||||
this(serviceURL, null, name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Constructs connector server
|
||||
*
|
||||
* @param serviceURL the address of the new connector server.
|
||||
* The actual address of the new connector server, as returned
|
||||
* by its getAddress method, will not necessarily be exactly the same.
|
||||
* @param environment a set of attributes to control the new connector
|
||||
* server's behavior. This parameter can be null. Keys in this map must
|
||||
* be Strings. The appropriate type of each associated value depends on
|
||||
* the attribute. The contents of environment are not changed by this call.
|
||||
* @param name object name string to be assigned to connector server bean
|
||||
* @throws Exception
|
||||
*/
|
||||
public ConnectorServer(JMXServiceURL serviceURL, Map<String,?> environment, String name)
|
||||
throws Exception
|
||||
{
|
||||
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
_connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceURL, environment, mbeanServer);
|
||||
mbeanServer.registerMBean(_connectorServer,new ObjectName(name));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
@Override
|
||||
public void doStart()
|
||||
throws Exception
|
||||
{
|
||||
_connectorServer.start();
|
||||
ShutdownThread.register(0, this);
|
||||
|
||||
Log.info("JMX Remote URL: {}", _connectorServer.getAddress().toString());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
|
||||
*/
|
||||
@Override
|
||||
public void doStop()
|
||||
throws Exception
|
||||
{
|
||||
ShutdownThread.deregister(this);
|
||||
_connectorServer.stop();
|
||||
}
|
||||
}
|
|
@ -15,9 +15,10 @@ package org.eclipse.jetty.jmx;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
|
@ -30,27 +31,45 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|||
import org.eclipse.jetty.util.component.Container;
|
||||
import org.eclipse.jetty.util.component.Container.Relationship;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.thread.ShutdownThread;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Container class for the MBean instances
|
||||
*/
|
||||
public class MBeanContainer extends AbstractLifeCycle implements Container.Listener
|
||||
{
|
||||
private final MBeanServer _server;
|
||||
private final WeakHashMap _beans = new WeakHashMap();
|
||||
private final HashMap _unique = new HashMap();
|
||||
private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
|
||||
private final HashMap<String, Integer> _unique = new HashMap<String, Integer>();
|
||||
private final MultiMap<ObjectName> _relations = new MultiMap<ObjectName>();
|
||||
private String _domain = null;
|
||||
private MultiMap _relations = new MultiMap();
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Lookup an object name by instance
|
||||
*
|
||||
* @param object instance for which object name is looked up
|
||||
* @return object name associated with specified instance, or null if not found
|
||||
*/
|
||||
public synchronized ObjectName findMBean(Object object)
|
||||
{
|
||||
ObjectName bean = (ObjectName)_beans.get(object);
|
||||
return bean==null?null:bean;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Lookup an instance by object name
|
||||
*
|
||||
* @param oname object name of instance
|
||||
* @return instance associated with specified object name, or null if not found
|
||||
*/
|
||||
public synchronized Object findBean(ObjectName oname)
|
||||
{
|
||||
for (Iterator iter = _beans.entrySet().iterator(); iter.hasNext();)
|
||||
for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
|
||||
{
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
ObjectName bean = (ObjectName)entry.getValue();
|
||||
if (bean.equals(oname))
|
||||
return entry.getKey();
|
||||
|
@ -58,30 +77,65 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Constructs MBeanContainer
|
||||
*
|
||||
* @param server instance of MBeanServer for use by container
|
||||
*/
|
||||
public MBeanContainer(MBeanServer server)
|
||||
{
|
||||
this._server = server;
|
||||
_server = server;
|
||||
|
||||
try
|
||||
{
|
||||
start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.ignore(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Retrieve instance of MBeanServer used by container
|
||||
*
|
||||
* @return instance of MBeanServer
|
||||
*/
|
||||
public MBeanServer getMBeanServer()
|
||||
{
|
||||
return _server;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set domain to be used to add MBeans
|
||||
*
|
||||
* @param domain domain name
|
||||
*/
|
||||
public void setDomain (String domain)
|
||||
{
|
||||
_domain =domain;
|
||||
_domain = domain;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Retrieve domain name used to add MBeans
|
||||
*
|
||||
* @return domain name
|
||||
*/
|
||||
public String getDomain()
|
||||
{
|
||||
return _domain;
|
||||
}
|
||||
|
||||
public void doStart()
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Implementation of Container.Listener interface
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.Container.Listener#add(org.eclipse.jetty.util.component.Container.Relationship)
|
||||
*/
|
||||
public synchronized void add(Relationship relationship)
|
||||
{
|
||||
ObjectName parent=(ObjectName)_beans.get(relationship.getParent());
|
||||
|
@ -100,10 +154,14 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
|
||||
if (parent!=null && child!=null)
|
||||
_relations.add(parent,relationship);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Implementation of Container.Listener interface
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.Container.Listener#remove(org.eclipse.jetty.util.component.Container.Relationship)
|
||||
*/
|
||||
public synchronized void remove(Relationship relationship)
|
||||
{
|
||||
ObjectName parent=(ObjectName)_beans.get(relationship.getParent());
|
||||
|
@ -112,21 +170,26 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
_relations.removeValue(parent,relationship);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Implementation of Container.Listener interface
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.Container.Listener#removeBean(java.lang.Object)
|
||||
*/
|
||||
public synchronized void removeBean(Object obj)
|
||||
{
|
||||
ObjectName bean=(ObjectName)_beans.remove(obj);
|
||||
|
||||
if (bean!=null)
|
||||
{
|
||||
List r=_relations.getValues(bean);
|
||||
if (r!=null && r.size()>0)
|
||||
List<Relationship> beanRelations = _relations.getValues(bean);
|
||||
if (beanRelations!=null && beanRelations.size()>0)
|
||||
{
|
||||
Log.debug("Unregister {}", r);
|
||||
Iterator iter = new ArrayList(r).iterator();
|
||||
while (iter.hasNext())
|
||||
Log.debug("Unregister {}", beanRelations);
|
||||
List<Relationship> removeList = new ArrayList<Relationship>(beanRelations);
|
||||
for (Relationship relation : removeList)
|
||||
{
|
||||
Relationship rel = (Relationship)iter.next();
|
||||
rel.getContainer().update(rel.getParent(),rel.getChild(),null,rel.getRelationship(),true);
|
||||
relation.getContainer().update(relation.getParent(),relation.getChild(),null,relation.getRelationship(),true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,6 +209,12 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Implementation of Container.Listener interface
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.Container.Listener#addBean(java.lang.Object)
|
||||
*/
|
||||
public synchronized void addBean(Object obj)
|
||||
{
|
||||
try
|
||||
|
@ -218,57 +287,29 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Perform actions needed to start lifecycle
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
public void doStart()
|
||||
{
|
||||
ShutdownThread.register(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Perform actions needed to stop lifecycle
|
||||
*
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
|
||||
*/
|
||||
public void doStop()
|
||||
{
|
||||
while (_beans.size()>0)
|
||||
removeBean(_beans.keySet().iterator().next());
|
||||
}
|
||||
|
||||
private class ShutdownHook extends Thread
|
||||
{
|
||||
private final ObjectName mletName;
|
||||
private final ObjectName adaptorName;
|
||||
private final ObjectName processorName;
|
||||
|
||||
public ShutdownHook(ObjectName mletName, ObjectName adaptorName, ObjectName processorName)
|
||||
Set<Object> removeSet = new HashSet<Object>(_beans.keySet());
|
||||
for (Object removeObj : removeSet)
|
||||
{
|
||||
this.mletName = mletName;
|
||||
this.adaptorName = adaptorName;
|
||||
this.processorName = processorName;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
halt();
|
||||
unregister(processorName);
|
||||
unregister(adaptorName);
|
||||
unregister(mletName);
|
||||
}
|
||||
|
||||
private void halt()
|
||||
{
|
||||
try
|
||||
{
|
||||
_server.invoke(adaptorName, "stop", null, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregister(ObjectName objectName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_server.unregisterMBean(objectName);
|
||||
Log.debug("Unregistered " + objectName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
removeBean(removeObj);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.jetty.util.component.Container;
|
|||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ShutdownThread;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -54,7 +55,6 @@ import org.eclipse.jetty.util.thread.ThreadPool;
|
|||
*/
|
||||
public class Server extends HandlerWrapper implements Attributes
|
||||
{
|
||||
private static final ShutdownHookThread hookThread = new ShutdownHookThread();
|
||||
private static final String _version;
|
||||
static
|
||||
{
|
||||
|
@ -120,7 +120,9 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
{
|
||||
_stopAtShutdown=stop;
|
||||
if (stop)
|
||||
hookThread.add(this);
|
||||
ShutdownThread.register(this);
|
||||
else
|
||||
ShutdownThread.deregister(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -189,7 +191,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
if (getStopAtShutdown())
|
||||
hookThread.add(this);
|
||||
ShutdownThread.register(this);
|
||||
|
||||
Log.info("jetty-"+_version);
|
||||
HttpGenerator.setServerVersion(_version);
|
||||
|
@ -309,7 +311,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
}
|
||||
|
||||
mex.ifExceptionThrow();
|
||||
hookThread.remove(this);
|
||||
ShutdownThread.deregister(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -518,119 +520,6 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
_container.removeBean(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* ShutdownHook thread for stopping all servers.
|
||||
*
|
||||
* Thread is hooked first time list of servers is changed.
|
||||
*/
|
||||
private static class ShutdownHookThread extends Thread
|
||||
{
|
||||
private boolean _hooked = false;
|
||||
private final Set<Server> _servers = new CopyOnWriteArraySet<Server>();
|
||||
|
||||
/**
|
||||
* Hooks this thread for shutdown.
|
||||
*
|
||||
* @see java.lang.Runtime#addShutdownHook(java.lang.Thread)
|
||||
*/
|
||||
private void createShutdownHook()
|
||||
{
|
||||
if (!_hooked)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook", Thread.class);
|
||||
shutdownHook.invoke(Runtime.getRuntime(), this);
|
||||
_hooked = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (Log.isDebugEnabled())
|
||||
Log.debug("No shutdown hook in JVM ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Server to servers list.
|
||||
*/
|
||||
public void add(Server server)
|
||||
{
|
||||
_servers.add(server);
|
||||
if (server.getStopAtShutdown())
|
||||
createShutdownHook();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains Server in servers list?
|
||||
*/
|
||||
public boolean contains(Server server)
|
||||
{
|
||||
return _servers.contains(server);
|
||||
}
|
||||
|
||||
public Iterable<Server> getServers()
|
||||
{
|
||||
return _servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear list of Servers.
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
_servers.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Server from list.
|
||||
*/
|
||||
public boolean remove(Server server)
|
||||
{
|
||||
createShutdownHook();
|
||||
return _servers.remove(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all Servers in list.
|
||||
*/
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setName("Shutdown");
|
||||
Log.info("Shutdown hook executing");
|
||||
for (Server svr : _servers)
|
||||
{
|
||||
if (svr == null || !svr.getStopAtShutdown() || !svr.isRunning())
|
||||
continue;
|
||||
try
|
||||
{
|
||||
svr.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
Log.info("Shutdown hook complete");
|
||||
|
||||
// Try to avoid JVM crash
|
||||
try
|
||||
{
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.util.AttributesMap#clearAttributes()
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.util.thread;
|
||||
|
||||
import java.io.ObjectStreamException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* ShutdownThread is a shutdown hook thread implemented as
|
||||
* singleton that maintains a list of lifecycle instances
|
||||
* that are registered with it and provides ability to stop
|
||||
* these lifecycles upon shutdown of the Java Virtual Machine
|
||||
*/
|
||||
public class ShutdownThread extends Thread
|
||||
{
|
||||
private static final ShutdownThread _thread = new ShutdownThread();
|
||||
|
||||
private final List<LifeCycle> _lifeCycles = new CopyOnWriteArrayList<LifeCycle>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Default constructor for the singleton
|
||||
*
|
||||
* Registers the instance as shutdown hook with the Java Runtime
|
||||
*/
|
||||
private ShutdownThread()
|
||||
{
|
||||
Runtime.getRuntime().addShutdownHook(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Returns the instance of the singleton
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ShutdownThread getInstance()
|
||||
{
|
||||
return _thread;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static synchronized void register(LifeCycle... lifeCycles)
|
||||
{
|
||||
_thread._lifeCycles.addAll(Arrays.asList(lifeCycles));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static synchronized void register(int index, LifeCycle... lifeCycles)
|
||||
{
|
||||
_thread._lifeCycles.addAll(index,Arrays.asList(lifeCycles));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static synchronized void deregister(LifeCycle lifeCycle)
|
||||
{
|
||||
_thread._lifeCycles.remove(lifeCycle);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void run()
|
||||
{
|
||||
for (LifeCycle lifeCycle : _thread._lifeCycles)
|
||||
{
|
||||
try
|
||||
{
|
||||
lifeCycle.stop();
|
||||
Log.debug("Stopped " + lifeCycle);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.debug(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected Object readResolve()
|
||||
throws ObjectStreamException
|
||||
{
|
||||
return _thread;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue