summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Gemmell <robbie@apache.org>2011-08-21 15:28:07 +0000
committerRobert Gemmell <robbie@apache.org>2011-08-21 15:28:07 +0000
commit1f5408d785d38c00051be1922b62529a4be9cae6 (patch)
tree398f995ba3c028bc8937836cfb763571ca50dccf
parent050353a4bcdc6d237f7cbcb89286e4bea24571cf (diff)
downloadqpid-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
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java49
-rw-r--r--qpid/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java89
-rw-r--r--qpid/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java118
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;
+ }
+
+}