package jacorb.imr;

import jacorb.imr.ServerStartupDaemonPackage.ServerStartupFailed;
import jacorb.orb.ORB;
import java.lang.*;
import java.net.*;
import java.io.*;
import org.omg.PortableServer.*;

/**
 * This class is used to start servers on (from the view of the repository)
 * remote hosts. It has a thread for forwarding output of started servers.
 *
 * @author Nicolas Noffke
 * 
 * $Id: ServerStartupDaemonImpl.java,v 1.14 2000/03/10 13:13:25 brose Exp $
 *
 */

public class ServerStartupDaemonImpl extends jacorb.imr.ServerStartupDaemonPOA {
    private static ORB m_orb;

    /** prefix to help distinguish between output of a 
	started server and output of this SSD */
    private static final String m_out_prefix = ">> ";
  
    /**
     * The constructor. It registers this daemon at the repository.
     *
     * @exception Exception any exception that is thrown inside is propagated upwards.
     **/
    public ServerStartupDaemonImpl() 
	throws Exception
    {
	Registration _registration = null;

	_registration = RegistrationHelper.narrow(ImplementationRepositoryImpl.getImR(m_orb));
	if( _registration == null )
	    throw new java.lang.Error("ImR not found");

	_this_object( m_orb );

	HostInfo _me = new HostInfo(InetAddress.getLocalHost().getHostName(),_this(),
				    m_orb.object_to_string(_this()));

	_registration.register_host(_me);
    }

    /**
     * NOT IMPLEMENTED, but currently used for "pinging" purposes.
     * @return 0 always
     */
    public int get_system_load() {
	// Dummy method, not supported yet.
	return 0;
    }
    
    /**
     * This method starts a server on this host as specified by 'command'.
     *
     * @param command The server startup command, i.e. the servers class name and
     * parameters for its main method. The interpreter is inserted automatically.
     *
     * @exception jacorb.imr.ServerStartupDaemonPackage.ServerStartupFailed Runtime.exec 
     * failed to execute the command.
     */
    public void start_server(String command) throws ServerStartupFailed {
	try{
	    jacorb.util.Debug.output(2, "Starting: " + command );
	    Process _server = (Runtime.getRuntime()).exec(command);
	    new OutputForwarder(_server);
	}catch (Exception _e){
	    jacorb.util.Debug.output(2, _e);
	    throw new ServerStartupFailed();
	}
    }

    /**
     * main method. Creates a new ServerStartupDaemonImpl instance and runs the orb.
     **/  
    public static void main (String[] args)
    {
	try
	{
	    m_orb = (jacorb.orb.ORB) ORB.init(args,null);	
	    POA poa = POAHelper.narrow(m_orb.resolve_initial_references("RootPOA"));

	    poa.the_POAManager().activate();

	    ServerStartupDaemonImpl _ssd = new ServerStartupDaemonImpl();
	    
	    m_orb.run();
	}catch (Exception _e){
	    _e.printStackTrace();
	}

	System.exit(0);
    } 
    
    /**
     * Inner class used to forward output of servers, since that would be 
     * invisible otherwise.
     **/
    private class OutputForwarder extends Thread{
	private Process m_process = null;
       
	public OutputForwarder (Process proc){
	    m_process = proc;
	    start();
	}

	public void run(){
	    BufferedReader _in = new BufferedReader(new InputStreamReader(m_process.getInputStream()));
	    String _line = null;
	                           
	    try{
		// If we get null from readLine() we assume that the process has exited.
		// Unfortunately there is no exception thrown when trying to read from
		// a dead processes output stream.
		while((_line = _in.readLine()) != null)
		    System.out.println(m_out_prefix + _line);

		 _in.close();
	    }catch (Exception _e){
		_e.printStackTrace();
	    }
	    
	    jacorb.util.Debug.output(2, "A server process exited");
	}
    }//OutputForwarder

} // ServerStartupDaemonImpl


