001    package org.crsh.util;
002    
003    import org.slf4j.Logger;
004    import org.slf4j.LoggerFactory;
005    
006    import java.lang.reflect.Constructor;
007    import java.lang.reflect.InvocationHandler;
008    import java.lang.reflect.Method;
009    import java.lang.reflect.Proxy;
010    
011    /**
012     * Use sun.misc.Handler proprietary API for handling INT signal. This class use reflection and does not
013     * import sun.misc.* package.
014     *
015     * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
016     */
017    public class InterruptHandler {
018    
019      /** . */
020      private final Runnable runnable;
021    
022      /** . */
023      private final Logger log = LoggerFactory.getLogger(InterruptHandler.class);
024    
025      private final InvocationHandler handler = new InvocationHandler() {
026        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
027          Class<?>[] parameterTypes = method.getParameterTypes();
028          if (method.getName().equals("hashCode") && parameterTypes.length == 0) {
029            return System.identityHashCode(runnable);
030          } else if (method.getName().equals("equals") && parameterTypes.length == 1 && parameterTypes[0] == Object.class) {
031            return runnable.equals(args[0]);
032          } else if (method.getName().equals("toString") && parameterTypes.length == 0) {
033            return runnable.toString();
034          } else if (method.getName().equals("handle")) {
035            runnable.run();
036            return null;
037          } else {
038            throw new UnsupportedOperationException("Method " + method + " not implemented");
039          }
040        }
041      };
042    
043      public InterruptHandler(Runnable runnable) {
044        this.runnable = runnable;
045      }
046    
047      public void install() {
048        ClassLoader cl = Thread.currentThread().getContextClassLoader();
049        Class<?> signalHandlerClass;
050        Class<?> signalClass;
051        Method handle;
052        Object INT;
053        try {
054          signalHandlerClass = cl.loadClass("sun.misc.SignalHandler");
055          signalClass = cl.loadClass("sun.misc.Signal");
056          handle = signalClass.getDeclaredMethod("handle", signalClass, signalHandlerClass);
057          Constructor ctor = signalClass.getConstructor(String.class);
058          INT = ctor.newInstance("INT");
059        }
060        catch (Exception e) {
061          return;
062        }
063    
064        //
065        Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{signalHandlerClass}, handler);
066    
067        //
068        try {
069          handle.invoke(null, INT, proxy);
070        }
071        catch (Exception e) {
072          log.error("Could not install signal handler", e);
073        }
074      }
075    }