/*
* JacORB - a free Java ORB
*
* Copyright (C) 1999-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package org.jacorb.imr;
/**
* 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
*
*
*/
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import org.jacorb.config.Configuration;
import org.jacorb.config.ConfigurationException;
import org.jacorb.util.threadpool.Consumer;
import org.jacorb.util.threadpool.ConsumerFactory;
import org.jacorb.util.threadpool.ThreadPool;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.slf4j.Logger;
public class ServerStartupDaemonImpl
extends org.jacorb.imr.ServerStartupDaemonPOA
{
private org.omg.CORBA.ORB orb = null;
private static final String out_prefix = ">> ";
private ThreadPool stdout_pool = null;
private ThreadPool stderr_pool = null;
private Logger logger;
/**
* The constructor. It registers this daemon at the repository.
*/
public ServerStartupDaemonImpl(org.omg.CORBA.ORB orb)
{
this.orb = orb;
}
public void configure(Configuration myConfiguration)
throws ConfigurationException
{
this.logger = ((org.jacorb.config.Configuration) myConfiguration).getLogger("org.jacorb.imr");
try
{
Registration _registration = null;
_registration =
RegistrationHelper.narrow( orb.resolve_initial_references("ImplementationRepository"));
if( _registration == null )
throw new ConfigurationException("ImR not found");
POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
poa.the_POAManager().activate();
ServerStartupDaemon ssd =
ServerStartupDaemonHelper.narrow(poa.servant_to_reference(this));
HostInfo _me = new HostInfo(InetAddress.getLocalHost().getHostName(),
ssd,
orb.object_to_string(ssd));
_registration.register_host(_me);
}
catch (Exception e)
{
throw new ConfigurationException("Caught Exception", e);
}
stdout_pool = new ThreadPool( (org.jacorb.config.Configuration)myConfiguration, null,
new OutputForwarderFactory( new InputStreamSelector(){
public InputStream getInputStream( Process p )
{
return p.getInputStream();
}
}), //max threads
100, 10 );//max idle threads
stderr_pool = new ThreadPool( (org.jacorb.config.Configuration)myConfiguration, null,
new OutputForwarderFactory( new InputStreamSelector(){
public InputStream getInputStream( Process p )
{
return p.getErrorStream();
}
}), //max threads
100, 10 );//max idle threads
}
/**
* 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 ServerStartupFailed
* Runtime.exec() failed to execute the command.
*/
public void start_server(String command)
throws ServerStartupFailed
{
try
{
if (this.logger.isDebugEnabled())
{
this.logger.debug("Starting: " + command);
}
Process _server = Runtime.getRuntime().exec( command );
stdout_pool.putJob(_server);
stderr_pool.putJob(_server);
}
catch (Exception _e)
{
this.logger.error("Server startup failed", _e);
throw new ServerStartupFailed( _e.toString() );
}
}
/**
* main method. Creates a new ServerStartupDaemonImpl instance and runs the orb.
**/
public static void main( String[] args )
{
try
{
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
ServerStartupDaemonImpl _ssd = new ServerStartupDaemonImpl(orb);
_ssd.configure(((org.jacorb.orb.ORB) orb).getConfiguration());
orb.run();
}
catch( Exception _e )
{
_e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
/**
* Inner class used to forward output of servers, since that would be
* invisible otherwise.
*/
private class OutputForwarder
implements Consumer
{
/**
* prefix to help distinguish between output of a
* started server and output of this SSD
*/
private InputStreamSelector selector = null;
public OutputForwarder( InputStreamSelector selector )
{
this.selector = selector;
}
public void doWork( Object job )
{
Process p = (Process) job;
BufferedReader _in = new BufferedReader(new InputStreamReader(selector.getInputStream( p )));
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(out_prefix + _line);
}
_in.close();
}
catch( Exception _e )
{
logger.debug("Exception while forwarding server output", _e);
}
logger.debug("A server process exited");
}
}//OutputForwarder
private interface InputStreamSelector
{
public InputStream getInputStream( Process p );
}
private class OutputForwarderFactory
implements ConsumerFactory
{
private InputStreamSelector selector = null;
public OutputForwarderFactory( InputStreamSelector selector )
{
this.selector = selector;
}
public Consumer create()
{
return new OutputForwarder( selector );
}
}
} // ServerStartupDaemonImpl