PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/googlecode/jmxtrans/util/SignalInterceptor.java

http://jmxtrans.googlecode.com/
Java | 90 lines | 43 code | 14 blank | 33 comment | 3 complexity | 92597a5dc0f847a8fba599c2e52ae1ec MD5 | raw file
 1package com.googlecode.jmxtrans.util;
 2
 3import sun.misc.Signal;
 4import sun.misc.SignalHandler;
 5
 6public abstract class SignalInterceptor {
 7
 8    protected SignalInterceptor() {
 9    }
10
11    /**
12     * <p>
13     * 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
14     * <code>register("TERM")</code>.
15     * </p>
16     * <p>
17     * If the registration fails for any reason, a <code>SignalInterceptorException</code> will be thrown. This is usually caused by one of the following conditions:
18     * </p>
19     * <ul>
20     * <li>The <code>sun.misc.Signal*</code> classes are not available (e.g. you are not using Sun's JVM).</li>
21     * <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>
22     * <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
23     * diagnostic output).</li>
24     * </ul>
25     */
26    protected void register(String signame) throws SignalInterceptorException {
27        try {
28            new SignalInterceptorHelper(signame, this);
29        } catch (Throwable e) {
30            throw new SignalInterceptorException(signame, e);
31        }
32    }
33
34    /**
35     * A wrapper around <code>register(String)</code> which never throws an
36     * exception. Instead, it returns <code>true</code> if registration
37     * succeeded, and <code>false</code> if it failed.
38     */
39    protected boolean registerQuietly(String signame) {
40        try {
41            register(signame);
42        } catch (Throwable e) {
43            return false;
44        }
45        return true;
46    }
47
48    /**
49     * Handle the given signal (which you had previously registered for). If
50     * this method return false, or throws an exception, subsequent handlers
51     * in the chain will <b>not</b> be called.
52     */
53    protected abstract boolean handle(String signame);
54
55    /**
56     * <p>
57     * Private helper class for <code>SignalInterceptor</code>.
58     * </p>
59     * <p>
60     * 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.
61     * </p>
62     */
63    private static class SignalInterceptorHelper implements SignalHandler {
64
65        private final SignalHandler oldHandler;
66
67        private final SignalInterceptor interceptor;
68
69        SignalInterceptorHelper(String signame, SignalInterceptor interceptor) {
70            this.interceptor = interceptor;
71            Signal signal = new Signal(signame);
72            oldHandler = Signal.handle(signal, this);
73        }
74
75        public void handle(Signal sig) {
76            if (interceptor.handle(sig.getName()) && (oldHandler != null)) {
77                oldHandler.handle(sig);
78            }
79        }
80    }
81
82    @SuppressWarnings("serial")
83	private static class SignalInterceptorException extends Exception {
84
85        SignalInterceptorException(String signal, Throwable cause) {
86            super("Unable to register for SIG" + signal, cause);
87        }
88
89    }
90}