/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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
 *
 *      https://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.
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.Properties;

import org.apache.commons.daemon.Daemon;
import org.apache.commons.daemon.DaemonContext;

public class ServiceDaemon implements Daemon {

    private Properties prop;
    private Process[] proc = null;
    private ServiceDaemonReadThread[] readout = null;
    private ServiceDaemonReadThread[] readerr = null;

    public ServiceDaemon() {
        super();
        System.err.println("ServiceDaemon: instance "+this.hashCode()+
                           " created");
    }

    @Override
    protected void finalize() {
        System.err.println("ServiceDaemon: instance "+this.hashCode()+
                           " garbage collected");
    }

    /**
     * init and destroy were added in jakarta-tomcat-daemon.
     */
    @Override
    public void init(DaemonContext context)
    throws Exception {
        // Set the err
        System.setErr(new PrintStream(new FileOutputStream(new File("ServiceDaemon.err")), true));
        System.err.println("ServiceDaemon: instance "+this.hashCode()+
                           " init");

        // read the properties file
        prop = new Properties();
        try {
            prop.load(new FileInputStream("startfile"));
        }
        catch (Exception e) {
            // Cannot find startfile.properties.
            // TODO: Should we print something?
        }
        // create an array to store the processes
        int processCount = prop.size();
        System.err.println("ServiceDaemon: init for " + processCount + " processes");
        proc = new Process[processCount];
        readout = new ServiceDaemonReadThread[processCount];
        readerr = new ServiceDaemonReadThread[processCount];
        for (int i = 0 ; i < processCount; i++) {
            proc[i] = null;
            readout[i] = null;
            readerr[i] = null;
        }

        System.err.println("ServiceDaemon: init done ");
    }

    @Override
    public void start() {
        // Dump a message
        System.err.println("ServiceDaemon: starting");

        // Start
        int i=0;
        for (Enumeration<Object> e = prop.keys(); e.hasMoreElements() ;) {
            String name = (String) e.nextElement();
            System.err.println("ServiceDaemon: starting: " + name + " : " + prop.getProperty(name));
            try {
                proc[i] = Runtime.getRuntime().exec(new String[] {prop.getProperty(name)});
            } catch (Exception ex) {
               System.err.println("Exception: " + ex);
           }
           // Start threads to read from Error and Out streams
           readerr[i] =
               new ServiceDaemonReadThread(proc[i].getErrorStream());
           readout[i] =
               new ServiceDaemonReadThread(proc[i].getInputStream());
           readerr[i].start();
           readout[i].start();
           i++;
        }
    }

    @Override
    public void stop()
    throws IOException, InterruptedException {
        // Dump a message
        System.err.println("ServiceDaemon: stopping");

        for (int i=0;i<proc.length;i++) {
            if ( proc[i]==null)
               continue;
            proc[i].destroy();
            try {
                proc[i].waitFor();
            } catch (InterruptedException ex) {
                System.err.println("ServiceDaemon: exception while stopping:" +
                                    ex);
            }
        }

        System.err.println("ServiceDaemon: stopped");
    }

    @Override
    public void destroy() {
        System.err.println("ServiceDaemon: instance "+this.hashCode()+
                           " destroy");
    }

}
