package com.googlecode.jmxtrans.util;
import sun.misc.Signal;
import sun.misc.SignalHandler;
public abstract class SignalInterceptor {
protected SignalInterceptor() {
}
/**
* <p>
* Register for the given signal. Note that the signal name should
* <b>not</b> begin with <b>SIG</b>. For example, if you are interested in
* <b>SIGTERM</b>, you should call <code>register("TERM")</code>.
* </p>
* <p>
* If the registration fails for any reason, a
* <code>SignalInterceptorException</code> will be thrown. This is usually
* caused by one of the following conditions:
* </p>
* <ul>
* <li>The <code>sun.misc.Signal*</code> classes are not available (e.g. you
* are not using Sun's JVM).</li>
* <li><code>signame</code> is not a valid trappable signal name on this OS
* (e.g. <b>KILL</b> can't be trapped, <b>HUP</b> does not exist on Windows)
* </li>
* <li>The JVM refuses to let you trap <code>signame</code> because it is
* already being used for some other important purpose (e.g. <b>QUIT</b>
* and/or <b>BREAK</b> cause the JVM to print diagnostic output).</li>
* </ul>
*/
protected void register(String signame) throws SignalInterceptorException {
try {
new SignalInterceptorHelper(signame, this);
} catch (Throwable e) {
throw new SignalInterceptorException(signame, e);
}
}
/**
* A wrapper around <code>register(String)</code> which never throws an
* exception. Instead, it returns <code>true</code> if registration
* succeeded, and <code>false</code> if it failed.
*/
protected boolean registerQuietly(String signame) {
try {
register(signame);
} catch (Throwable e) {
return false;
}
return true;
}
/**
* Handle the given signal (which you had previously registered for). If
* this method return false, or throws an exception, subsequent handlers in
* the chain will <b>not</b> be called.
*/
protected abstract boolean handle(String signame);
/**
* <p>
* Private helper class for <code>SignalInterceptor</code>.
* </p>
* <p>
* This class exists separately from <code>SignalInterceptor</code> to
* permit graceful handling of LinkageErrors when the
* <code>sun.misc.Signal*</code> classes don't exist.
* </p>
*/
private static class SignalInterceptorHelper implements SignalHandler {
private final SignalHandler oldHandler;
private final SignalInterceptor interceptor;
SignalInterceptorHelper(String signame, SignalInterceptor interceptor) {
this.interceptor = interceptor;
Signal signal = new Signal(signame);
oldHandler = Signal.handle(signal, this);
}
public void handle(Signal sig) {
if (interceptor.handle(sig.getName()) && (oldHandler != null)) {
oldHandler.handle(sig);
}
}
}
@SuppressWarnings("serial")
private static class SignalInterceptorException extends Exception {
SignalInterceptorException(String signal, Throwable cause) {
super("Unable to register for SIG" + signal, cause);
}
}
}