/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

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