001/*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020package org.crsh.util;
021
022import java.lang.reflect.Constructor;
023import java.lang.reflect.InvocationHandler;
024import java.lang.reflect.Method;
025import java.lang.reflect.Proxy;
026import java.util.logging.Level;
027import java.util.logging.Logger;
028
029public class InterruptHandler {
030
031  /** . */
032  private final Runnable runnable;
033
034  /** . */
035  private final Logger log = Logger.getLogger(InterruptHandler.class.getName());
036
037  private final InvocationHandler handler = new InvocationHandler() {
038    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
039      Class<?>[] parameterTypes = method.getParameterTypes();
040      if (method.getName().equals("hashCode") && parameterTypes.length == 0) {
041        return System.identityHashCode(runnable);
042      } else if (method.getName().equals("equals") && parameterTypes.length == 1 && parameterTypes[0] == Object.class) {
043        return runnable.equals(args[0]);
044      } else if (method.getName().equals("toString") && parameterTypes.length == 0) {
045        return runnable.toString();
046      } else if (method.getName().equals("handle")) {
047        runnable.run();
048        return null;
049      } else {
050        throw new UnsupportedOperationException("Method " + method + " not implemented");
051      }
052    }
053  };
054
055  public InterruptHandler(Runnable runnable) {
056    this.runnable = runnable;
057  }
058
059  public void install() {
060    ClassLoader cl = Thread.currentThread().getContextClassLoader();
061    Class<?> signalHandlerClass;
062    Class<?> signalClass;
063    Method handle;
064    Object INT;
065    try {
066      signalHandlerClass = cl.loadClass("sun.misc.SignalHandler");
067      signalClass = cl.loadClass("sun.misc.Signal");
068      handle = signalClass.getDeclaredMethod("handle", signalClass, signalHandlerClass);
069      Constructor ctor = signalClass.getConstructor(String.class);
070      INT = ctor.newInstance("INT");
071    }
072    catch (Exception e) {
073      return;
074    }
075
076    //
077    Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{signalHandlerClass}, handler);
078
079    //
080    try {
081      handle.invoke(null, INT, proxy);
082    }
083    catch (Exception e) {
084      log.log(Level.SEVERE, "Could not install signal handler", e);
085    }
086  }
087}