/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/src/util/org/apache/slide/util/os/Killer.java,v 1.1 2004/03/25 16:18:12 juergen Exp $
 * $Revision: 1.1 $
 * $Date: 2004/03/25 16:18:12 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.slide.util.os;

import java.util.ArrayList;
import java.util.List;

/**
 ** Destroys processes upon jvm termination (including abnormal termination).
 ** A singleton which is registered as a shutdownHook. The Killer is necessary because killing
 ** (e.g. Ctrl-C) a JVM in JDK 1.4 no longer kills all child processes. In JDK 1.3, a killer
 ** is not necessary because all child processes are killed automatically. This class is thread-save.
 **
 ** @version   $Revision: 1.1 $
 **/
public class Killer extends Thread {
    private static Killer singleton = null;

    /**
     ** Returns the Killer singleton.
     **
     ** @return Killer
     **/
    public static synchronized Killer get() {
        if (singleton == null) {
            singleton = new Killer();
            Runtime.getRuntime().addShutdownHook(singleton);
        }
        return singleton;
    }
    
    /**
     ** Processes that have been started and have not been destroyed.
     **/
    private List processes;

    /**
     ** Creates a new killer. Private, use get() instead.
     **/
    private Killer() {
        processes = new ArrayList();
    }

    /**
     ** Adds a processes that has been started.
     **
     ** @param p  Process
     **/
    public synchronized void add(Process p) {
        processes.add(p);
    }

    /**
     ** Destroys a process.
     **
     ** @param p Process to be destroyed.
     **/
    public synchronized void remove(Process p) {
        processes.remove(p);
    }

    /**
     ** Runs method called in the shutdownHook. Destroys all processed.
     **/
    public void run() {
        int i;
        int max;
        Process p;

        synchronized (this) {
            max = processes.size();
            for (i = 0; i < max; i++) {
                p = (Process) processes.get(i);
                System.err.println("destroying " + p);
                p.destroy();
            }
        }
        System.err.flush();
    }
}

