/**
* The MIT License
* Copyright © 2010 JmxTrans team
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.googlecode.jmxtrans.util;
import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement;
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);
}
}
/**
* 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>
*/
@IgnoreJRERequirement
private static class SignalInterceptorHelper implements SignalHandler {
private final SignalHandler oldHandler;
private final SignalInterceptor interceptor;
@IgnoreJRERequirement
SignalInterceptorHelper(String signame, SignalInterceptor interceptor) {
this.interceptor = interceptor;
Signal signal = new Signal(signame);
oldHandler = Signal.handle(signal, this);
}
@Override @IgnoreJRERequirement
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);
}
}
}