/*
 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.misc;
import java.util.Hashtable;

/**
 * This class provides ANSI/ISO C signal support. A Java program can register
 * signal handlers for the current process. There are two restrictions:
 * <ul>
 * <li>
 * Java code cannot register a handler for signals that are already used
 * by the Java VM implementation. The <code>Signal.handle</code>
 * function raises an <code>IllegalArgumentException</code> if such an attempt
 * is made.
 * <li>
 * When <code>Signal.handle</code> is called, the VM internally registers a
 * special C signal handler. There is no way to force the Java signal handler
 * to run synchronously before the C signal handler returns. Instead, when the
 * VM receives a signal, the special C signal handler creates a new thread
 * (at priority <code>Thread.MAX_PRIORITY</code>) to
 * run the registered Java signal handler. The C signal handler immediately
 * returns. Note that because the Java signal handler runs in a newly created
 * thread, it may not actually be executed until some time after the C signal
 * handler returns.
 * </ul>
 * <p>
 * Signal objects are created based on their names. For example:
 * <blockquote><pre>
 * new Signal("INT");
 * </blockquote></pre>
 * constructs a signal object corresponding to <code>SIGINT</code>, which is
 * typically produced when the user presses <code>Ctrl-C</code> at the command line.
 * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
 * when it is passed an unknown signal.
 * <p>
 * This is an example of how Java code handles <code>SIGINT</code>:
 * <blockquote><pre>
 * SignalHandler handler = new SignalHandler () {
 *     public void handle(Signal sig) {
 *       ... // handle SIGINT
 *     }
 * };
 * Signal.handle(new Signal("INT"), handler);
 * </blockquote></pre>
 *
 * @author   Sheng Liang
 * @author   Bill Shannon
 * @see      sun.misc.SignalHandler
 * @since    1.2
 */
public final class Signal {
    private static Hashtable<Signal,SignalHandler> handlers = new Hashtable<>(4);
    private static Hashtable<Integer,Signal> signals = new Hashtable<>(4);

    private int number;
    private String name;

    /* Returns the signal number */
    public int getNumber() {
        return number;
    }

    /**
     * Returns the signal name.
     *
     * @return the name of the signal.
     * @see sun.misc.Signal#Signal(String name)
     */
    public String getName() {
        return name;
    }

    /**
     * Compares the equality of two <code>Signal</code> objects.
     *
     * @param other the object to compare with.
     * @return whether two <code>Signal</code> objects are equal.
     */
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other == null || !(other instanceof Signal)) {
            return false;
        }
        Signal other1 = (Signal)other;
        return name.equals(other1.name) && (number == other1.number);
    }

    /**
     * Returns a hashcode for this Signal.
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        return number;
    }

    /**
     * Returns a string representation of this signal. For example, "SIGINT"
     * for an object constructed using <code>new Signal ("INT")</code>.
     *
     * @return a string representation of the signal
     */
    public String toString() {
        return "SIG" + name;
    }

    /**
     * Constructs a signal from its name.
     *
     * @param name the name of the signal.
     * @exception IllegalArgumentException unknown signal
     * @see sun.misc.Signal#getName()
     */
    public Signal(String name) {
        number = findSignal(name);
        this.name = name;
        if (number < 0) {
            throw new IllegalArgumentException("Unknown signal: " + name);
        }
    }

    /**
     * Registers a signal handler.
     *
     * @param sig a signal
     * @param handler the handler to be registered with the given signal.
     * @result the old handler
     * @exception IllegalArgumentException the signal is in use by the VM
     * @see sun.misc.Signal#raise(Signal sig)
     * @see sun.misc.SignalHandler
     * @see sun.misc.SignalHandler#SIG_DFL
     * @see sun.misc.SignalHandler#SIG_IGN
     */
    public static synchronized SignalHandler handle(Signal sig,
                                                    SignalHandler handler)
        throws IllegalArgumentException {
        long newH = (handler instanceof NativeSignalHandler) ?
                      ((NativeSignalHandler)handler).getHandler() : 2;
        long oldH = handle0(sig.number, newH);
        if (oldH == -1) {
            throw new IllegalArgumentException
                ("Signal already used by VM or OS: " + sig);
        }
        signals.put(sig.number, sig);
        synchronized (handlers) {
            SignalHandler oldHandler = handlers.get(sig);
            handlers.remove(sig);
            if (newH == 2) {
                handlers.put(sig, handler);
            }
            if (oldH == 0) {
                return SignalHandler.SIG_DFL;
            } else if (oldH == 1) {
                return SignalHandler.SIG_IGN;
            } else if (oldH == 2) {
                return oldHandler;
            } else {
                return new NativeSignalHandler(oldH);
            }
        }
    }

    /**
     * Raises a signal in the current process.
     *
     * @param sig a signal
     * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
     */
    public static void raise(Signal sig) throws IllegalArgumentException {
        if (handlers.get(sig) == null) {
            throw new IllegalArgumentException("Unhandled signal: " + sig);
        }
        raise0(sig.number);
    }

    /* Called by the VM to execute Java signal handlers. */
    private static void dispatch(final int number) {
        final Signal sig = signals.get(number);
        final SignalHandler handler = handlers.get(sig);

        Runnable runnable = new Runnable () {
            public void run() {
              // Don't bother to reset the priority. Signal handler will
              // run at maximum priority inherited from the VM signal
              // dispatch thread.
              // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
                handler.handle(sig);
            }
        };
        if (handler != null) {
            new Thread(runnable, sig + " handler").start();
        }
    }

    /* Find the signal number, given a name. Returns -1 for unknown signals. */
    private static native int findSignal(String sigName);
    /* Registers a native signal handler, and returns the old handler.
     * Handler values:
     *   0     default handler
     *   1     ignore the signal
     *   2     call back to Signal.dispatch
     *   other arbitrary native signal handlers
     */
    private static native long handle0(int sig, long nativeH);
    /* Raise a given signal number */
    private static native void raise0(int sig);
}
