diff options
author | Robert Gemmell <robbie@apache.org> | 2011-08-21 15:28:07 +0000 |
---|---|---|
committer | Robert Gemmell <robbie@apache.org> | 2011-08-21 15:28:07 +0000 |
commit | 1f5408d785d38c00051be1922b62529a4be9cae6 (patch) | |
tree | 398f995ba3c028bc8937836cfb763571ca50dccf | |
parent | 050353a4bcdc6d237f7cbcb89286e4bea24571cf (diff) | |
download | qpid-python-1f5408d785d38c00051be1922b62529a4be9cae6.tar.gz |
QPID-3439: add intermediate task class for Signal handling using reflection to access/implement the Signal handling classes/interfaces, removing dependency on the com.sun heirarchy from ServerConfiguration and thus the associated compiler warnings
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1159997 13f79535-47bb-0310-9956-ffa450edef68
3 files changed, 227 insertions, 29 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index 95c02c60a7..02f8a346cf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -39,17 +39,13 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.SystemConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean; import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.signal.SignalHandlerTask; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.transport.NetworkTransportConfiguration; -import sun.misc.Signal; -import sun.misc.SignalHandler; - -public class ServerConfiguration extends ConfigurationPlugin implements SignalHandler +public class ServerConfiguration extends ConfigurationPlugin { protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class); @@ -75,10 +71,6 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa private File _configFile; private File _vhostsFile; - private Logger _log = Logger.getLogger(this.getClass()); - - private ConfigurationManagementMBean _mbean; - // Map of environment variables to config items private static final Map<String, String> envVarMap = new HashMap<String, String>(); @@ -137,15 +129,26 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa { this(parseConfig(configurationURL)); _configFile = configurationURL; - try + + SignalHandlerTask hupReparseTask = new SignalHandlerTask() { - Signal sig = new sun.misc.Signal("HUP"); - sun.misc.Signal.handle(sig, this); - } - catch (Exception e) + public void handle() + { + try + { + reparseConfigFileSecuritySections(); + } + catch (ConfigurationException e) + { + _logger.error("Could not reload configuration file security sections", e); + } + } + }; + + if(!hupReparseTask.register("HUP")) { - _logger.info("Signal HUP not supported for OS: " + System.getProperty("os.name")); - // We're on something that doesn't handle SIGHUP, how sad, Windows. + _logger.info("Unable to register Signal HUP handler to reload security configuration."); + _logger.info("Signal HUP not supported for this OS / JVM combination - " + SignalHandlerTask.getPlatformDescription()); } } @@ -416,18 +419,6 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa return _configFile == null ? "" : _configFile.getAbsolutePath(); } - public void handle(Signal arg0) - { - try - { - reparseConfigFileSecuritySections(); - } - catch (ConfigurationException e) - { - _logger.error("Could not reload configuration file security sections", e); - } - } - public void reparseConfigFileSecuritySections() throws ConfigurationException { if (_configFile != null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java new file mode 100644 index 0000000000..4e3fae1dbd --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java @@ -0,0 +1,89 @@ +/* + * + * 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.qpid.server.signal; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.apache.log4j.Logger; + +public abstract class SignalHandlerTask +{ + private static final Logger LOGGER = Logger.getLogger(SignalHandlerTask.class); + + private static final String HANDLE_METHOD = "handle"; + private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal"; + private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler"; + + public boolean register(final String signalName) + { + try + { + //try to load the signal handling classes + Class<?> signalClazz = Class.forName(SUN_MISC_SIGNAL_CLASS); + Class<?> handlerClazz = Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS); + + //create an InvocationHandler that just executes the SignalHandlerTask + InvocationHandler invoker = new InvocationHandler() + { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable + { + handle(); + + return null; + } + }; + + //create a dynamic proxy implementing SignalHandler + Object handler = Proxy.newProxyInstance(handlerClazz.getClassLoader(), new Class[]{handlerClazz}, invoker); + + //create the Signal to handle + Constructor<?> signalConstructor = signalClazz.getConstructor(String.class); + Object signal = signalConstructor.newInstance(signalName); + + //invoke the Signal.handle(signal, handler) method + Method handleMethod = signalClazz.getMethod(HANDLE_METHOD, signalClazz, handlerClazz); + handleMethod.invoke(null, signal, handler); + } + catch (Exception e) + { + LOGGER.debug("Unable to register handler for Signal " + signalName + " due to exception: " + e, e); + return false; + } + + return true; + } + + public abstract void handle(); + + public static String getPlatformDescription() + { + String name = System.getProperty("os.name"); + String osVer = System.getProperty("os.version"); + String jvmVendor = System.getProperty("java.vm.vendor"); + String jvmName = System.getProperty("java.vm.name"); + String javaRuntimeVer = System.getProperty("java.runtime.version"); + + return "OS: " + name + " " + osVer + ", JVM:" + jvmVendor + " " + jvmName + " " + javaRuntimeVer; + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java new file mode 100644 index 0000000000..886cb080aa --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java @@ -0,0 +1,118 @@ +/* + * + * 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.qpid.server.signal; + +import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; +import org.apache.qpid.test.utils.QpidTestCase; + +public class SignalHandlerTaskTest extends QpidTestCase +{ + private static final Logger LOGGER = Logger.getLogger(SignalHandlerTaskTest.class); + private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal"; + private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler"; + + protected void setUp() throws Exception + { + super.setUp(); + } + + public void testSignalHandlerTask() throws Exception + { + final boolean expectedResult = classifyExpectedRegistrationResult(); + final int pid = getPID(); + final CountDownLatch latch = new CountDownLatch(1); + + SignalHandlerTask hupReparseTask = new SignalHandlerTask() + { + public void handle() + { + latch.countDown(); + LOGGER.info("Signal handled, latch decremented"); + } + }; + + assertEquals("Unexpected result trying to register Signal handler", + expectedResult, hupReparseTask.register("HUP")); + LOGGER.info("Signal handler was registered"); + + assertEquals("unexpected count for the latch", 1, latch.getCount()); + + if(expectedResult) + { + //registration succeeded as expected, so now + //send SIGHUP and verify the handler was run + String cmd = "/bin/kill -SIGHUP " + pid; + + LOGGER.info("Sending SIGHUP"); + Runtime.getRuntime().exec(cmd); + + assertTrue("HUP Signal was not handled in the allowed timeframe", + latch.await(5, TimeUnit.SECONDS)); + } + } + + public void testGetPlatformDescription() throws Exception + { + assertNotNull(SignalHandlerTask.getPlatformDescription()); + } + + private boolean classifyExpectedRegistrationResult() + { + String os = System.getProperty("os.name"); + if(String.valueOf(os).toLowerCase().contains("windows")) + { + //Windows does not support SIGHUP so registration will fail + LOGGER.info("Running on windows, so we expect SIGHUP handler registration to fail"); + return false; + } + + //otherwise, if the signal handler classes are present we would expect + //registration to succeed + boolean classesPresent = true; + try + { + Class.forName(SUN_MISC_SIGNAL_CLASS); + Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS); + LOGGER.info("Signal handling classes were present so we expect SIGHUP handler registration to succeed"); + } + catch (ClassNotFoundException cnfe) + { + classesPresent = false; + } + + return classesPresent; + } + + private int getPID() + { + String processName = ManagementFactory.getRuntimeMXBean().getName(); + + int pid = Integer.parseInt(processName.substring(0,processName.indexOf('@'))); + LOGGER.info("PID was determined to be " + pid); + + return pid; + } + +} |