/* * 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