| /* |
| * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code 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 General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package com.sun.corba.se.impl.activation; |
| |
| /** |
| * |
| * @author Anita Jindal |
| * @since JDK1.2 |
| */ |
| |
| import org.omg.CORBA.CompletionStatus; |
| |
| import com.sun.corba.se.spi.activation.Server; |
| import com.sun.corba.se.spi.activation.EndPointInfo; |
| import com.sun.corba.se.spi.activation.ORBAlreadyRegistered; |
| import com.sun.corba.se.spi.activation.ORBPortInfo; |
| import com.sun.corba.se.spi.activation.InvalidORBid; |
| import com.sun.corba.se.spi.activation.ServerHeldDown; |
| import com.sun.corba.se.spi.activation.RepositoryPackage.ServerDef; |
| import com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT; |
| import com.sun.corba.se.spi.orb.ORB ; |
| |
| import com.sun.corba.se.impl.orbutil.ORBConstants; |
| import com.sun.corba.se.impl.logging.ActivationSystemException ; |
| |
| import java.io.File; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| |
| public class ServerTableEntry |
| { |
| |
| private final static int DE_ACTIVATED = 0; |
| private final static int ACTIVATING = 1; |
| private final static int ACTIVATED = 2; |
| private final static int RUNNING = 3; |
| private final static int HELD_DOWN = 4; |
| |
| |
| private String printState() |
| { |
| String str = "UNKNOWN"; |
| |
| switch (state) { |
| case (DE_ACTIVATED) : str = "DE_ACTIVATED"; break; |
| case (ACTIVATING ) : str = "ACTIVATING "; break; |
| case (ACTIVATED ) : str = "ACTIVATED "; break; |
| case (RUNNING ) : str = "RUNNING "; break; |
| case (HELD_DOWN ) : str = "HELD_DOWN "; break; |
| default: break; |
| } |
| |
| return str; |
| } |
| |
| private final static long waitTime = 2000; |
| private static final int ActivationRetryMax = 5; |
| |
| // state of each entry |
| private int state; |
| private int serverId; |
| private HashMap orbAndPortInfo; |
| private Server serverObj; |
| private ServerDef serverDef; |
| private Process process; |
| private int activateRetryCount=0; |
| private String activationCmd; |
| private ActivationSystemException wrapper ; |
| public String toString() |
| { |
| return "ServerTableEntry[" + "state=" + printState() + |
| " serverId=" + serverId + |
| " activateRetryCount=" + activateRetryCount + "]" ; |
| } |
| |
| // get the string needed to make the activation command |
| private static String javaHome, classPath, fileSep, pathSep; |
| |
| static { |
| javaHome = System.getProperty("java.home"); |
| classPath = System.getProperty("java.class.path"); |
| fileSep = System.getProperty("file.separator"); |
| pathSep = System.getProperty("path.separator"); |
| } |
| |
| ServerTableEntry( ActivationSystemException wrapper, |
| int serverId, ServerDef serverDef, int initialPort, |
| String dbDirName, boolean verify, boolean debug ) |
| { |
| this.wrapper = wrapper ; |
| this.serverId = serverId; |
| this.serverDef = serverDef; |
| this.debug = debug ; |
| // create a HashMap with capacity 255 |
| // Since all methods are synchronized, we don't need any |
| // additional synchronization mechanisms |
| orbAndPortInfo = new HashMap(255); |
| |
| activateRetryCount = 0; |
| state = ACTIVATING; |
| |
| // compute the activation command |
| activationCmd = |
| |
| // add path to the java vm |
| javaHome + fileSep + "bin" + fileSep + "java " + |
| |
| // add any arguments to the server Java VM |
| serverDef.serverVmArgs + " " + |
| |
| // add ORB properties |
| "-Dioser=" + System.getProperty( "ioser" ) + " " + |
| "-D" + ORBConstants.INITIAL_PORT_PROPERTY + "=" + initialPort + " " + |
| "-D" + ORBConstants.DB_DIR_PROPERTY + "=" + dbDirName + " " + |
| "-D" + ORBConstants.ACTIVATED_PROPERTY + "=true " + |
| "-D" + ORBConstants.SERVER_ID_PROPERTY + "=" + serverId + " " + |
| "-D" + ORBConstants.SERVER_NAME_PROPERTY + "=" + serverDef.serverName + " " + |
| // we need to pass in the verify flag, so that the server is not |
| // launched, when we try to validate its definition during registration |
| // into the RepositoryImpl |
| |
| (verify ? "-D" + ORBConstants.SERVER_DEF_VERIFY_PROPERTY + "=true ": "") + |
| |
| // add classpath to the server |
| "-classpath " + classPath + |
| (serverDef.serverClassPath.equals("") == true ? "" : pathSep) + |
| serverDef.serverClassPath + |
| |
| // add server class name and arguments |
| " com.sun.corba.se.impl.activation.ServerMain " + serverDef.serverArgs |
| |
| // Add the debug flag, if any |
| + (debug ? " -debug" : "") ; |
| |
| if (debug) System.out.println( |
| "ServerTableEntry constructed with activation command " + |
| activationCmd); |
| } |
| |
| /** |
| * Verify whether the server definition is valid. |
| */ |
| public int verify() |
| { |
| try { |
| |
| if (debug) |
| System.out.println("Server being verified w/" + activationCmd); |
| |
| process = Runtime.getRuntime().exec(activationCmd); |
| int result = process.waitFor(); |
| if (debug) |
| printDebug( "verify", "returns " + ServerMain.printResult( result ) ) ; |
| return result ; |
| } catch (Exception e) { |
| if (debug) |
| printDebug( "verify", "returns unknown error because of exception " + |
| e ) ; |
| return ServerMain.UNKNOWN_ERROR; |
| } |
| } |
| |
| private void printDebug(String method, String msg) |
| { |
| System.out.println("ServerTableEntry: method =" + method); |
| System.out.println("ServerTableEntry: server =" + serverId); |
| System.out.println("ServerTableEntry: state =" + printState()); |
| System.out.println("ServerTableEntry: message =" + msg); |
| System.out.println(); |
| } |
| |
| synchronized void activate() throws org.omg.CORBA.SystemException |
| { |
| state = ACTIVATED; |
| |
| try { |
| if (debug) |
| printDebug("activate", "activating server"); |
| process = Runtime.getRuntime().exec(activationCmd); |
| } catch (Exception e) { |
| deActivate(); |
| if (debug) |
| printDebug("activate", "throwing premature process exit"); |
| throw wrapper.unableToStartProcess() ; |
| } |
| } |
| |
| synchronized void register(Server server) |
| { |
| if (state == ACTIVATED) { |
| |
| serverObj = server; |
| |
| //state = RUNNING; |
| //notifyAll(); |
| |
| if (debug) |
| printDebug("register", "process registered back"); |
| |
| } else { |
| |
| if (debug) |
| printDebug("register", "throwing premature process exit"); |
| throw wrapper.serverNotExpectedToRegister() ; |
| } |
| } |
| |
| synchronized void registerPorts( String orbId, EndPointInfo [] endpointList) |
| throws ORBAlreadyRegistered |
| { |
| |
| // find if the ORB is already registered, then throw an exception |
| if (orbAndPortInfo.containsKey(orbId)) { |
| throw new ORBAlreadyRegistered(orbId); |
| } |
| |
| // store all listener ports and their types |
| int numListenerPorts = endpointList.length; |
| EndPointInfo [] serverListenerPorts = new EndPointInfo[numListenerPorts]; |
| |
| for (int i = 0; i < numListenerPorts; i++) { |
| serverListenerPorts[i] = new EndPointInfo (endpointList[i].endpointType, endpointList[i].port); |
| if (debug) |
| System.out.println("registering type: " + serverListenerPorts[i].endpointType + " port " + serverListenerPorts[i].port); |
| } |
| |
| // put this set of listener ports in the HashMap associated |
| // with the orbId |
| orbAndPortInfo.put(orbId, serverListenerPorts); |
| if (state == ACTIVATED) { |
| state = RUNNING; |
| notifyAll(); |
| } |
| // _REVISIT_, If the state is not equal to ACTIVATED then it is a bug |
| // need to log that error, once the Logging framework is in place |
| // for rip-int. |
| if (debug) |
| printDebug("registerPorts", "process registered Ports"); |
| } |
| |
| void install() |
| { |
| Server localServerObj = null; |
| synchronized ( this ) { |
| if (state == RUNNING) |
| localServerObj = serverObj; |
| else |
| throw wrapper.serverNotRunning() ; |
| } |
| if (localServerObj != null) { |
| localServerObj.install() ; |
| } |
| |
| } |
| |
| void uninstall() |
| { |
| Server localServerObj = null; |
| Process localProcess = null; |
| |
| synchronized (this) { |
| localServerObj = serverObj; |
| localProcess = process; |
| |
| if (state == RUNNING) { |
| |
| deActivate(); |
| |
| } else { |
| throw wrapper.serverNotRunning() ; |
| } |
| } |
| try { |
| if (localServerObj != null) { |
| localServerObj.shutdown(); // shutdown the server |
| localServerObj.uninstall() ; // call the uninstall |
| } |
| |
| if (localProcess != null) { |
| localProcess.destroy(); |
| } |
| } catch (Exception ex) { |
| // what kind of exception should be thrown |
| } |
| } |
| |
| synchronized void holdDown() |
| { |
| state = HELD_DOWN; |
| |
| if (debug) |
| printDebug( "holdDown", "server held down" ) ; |
| |
| notifyAll(); |
| } |
| |
| synchronized void deActivate() |
| { |
| state = DE_ACTIVATED; |
| |
| if (debug) |
| printDebug( "deActivate", "server deactivated" ) ; |
| |
| notifyAll(); |
| } |
| |
| synchronized void checkProcessHealth( ) { |
| // If the State in the ServerTableEntry is RUNNING and the |
| // Process was shut down abnormally, The method will change the |
| // server state as De-Activated. |
| if( state == RUNNING ) { |
| try { |
| int exitVal = process.exitValue(); |
| } catch (IllegalThreadStateException e1) { |
| return; |
| } |
| synchronized ( this ) { |
| // Clear the PortInformation as it is old |
| orbAndPortInfo.clear(); |
| // Move the state to De-Activated, So that the next |
| // call to this server will re-activate. |
| deActivate(); |
| } |
| } |
| } |
| |
| synchronized boolean isValid() |
| { |
| if ((state == ACTIVATING) || (state == HELD_DOWN)) { |
| if (debug) |
| printDebug( "isValid", "returns true" ) ; |
| |
| return true; |
| } |
| |
| try { |
| int exitVal = process.exitValue(); |
| } catch (IllegalThreadStateException e1) { |
| return true; |
| } |
| |
| if (state == ACTIVATED) { |
| if (activateRetryCount < ActivationRetryMax) { |
| if (debug) |
| printDebug("isValid", "reactivating server"); |
| activateRetryCount++; |
| activate(); |
| return true; |
| } |
| |
| if (debug) |
| printDebug("isValid", "holding server down"); |
| |
| holdDown(); |
| return true; |
| } |
| |
| deActivate(); |
| return false; |
| } |
| |
| synchronized ORBPortInfo[] lookup(String endpointType) throws ServerHeldDown |
| { |
| while ((state == ACTIVATING) || (state == ACTIVATED)) { |
| try { |
| wait(waitTime); |
| if (!isValid()) break; |
| } catch(Exception e) {} |
| } |
| ORBPortInfo[] orbAndPortList = null; |
| |
| if (state == RUNNING) { |
| orbAndPortList = new ORBPortInfo[orbAndPortInfo.size()]; |
| Iterator setORBids = orbAndPortInfo.keySet().iterator(); |
| |
| try { |
| int numElements = 0; |
| int i; |
| int port; |
| while (setORBids.hasNext()) { |
| String orbId = (String) setORBids.next(); |
| // get an entry corresponding to orbId |
| EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId); |
| port = -1; |
| // return the port corresponding to the endpointType |
| for (i = 0; i < serverListenerPorts.length; i++) { |
| if (debug) |
| System.out.println("lookup num-ports " + serverListenerPorts.length + " " + |
| serverListenerPorts[i].endpointType + " " + |
| serverListenerPorts[i].port ); |
| if ((serverListenerPorts[i].endpointType).equals(endpointType)) { |
| port = serverListenerPorts[i].port; |
| break; |
| } |
| } |
| orbAndPortList[numElements] = new ORBPortInfo(orbId, port); |
| numElements++; |
| } |
| } catch (NoSuchElementException e) { |
| // have everything in the table |
| } |
| return orbAndPortList; |
| } |
| |
| if (debug) |
| printDebug("lookup", "throwing server held down error"); |
| |
| throw new ServerHeldDown( serverId ) ; |
| } |
| |
| synchronized EndPointInfo[] lookupForORB(String orbId) |
| throws ServerHeldDown, InvalidORBid |
| { |
| while ((state == ACTIVATING) || (state == ACTIVATED)) { |
| try { |
| wait(waitTime); |
| if (!isValid()) break; |
| } catch(Exception e) {} |
| } |
| EndPointInfo[] portList = null; |
| |
| if (state == RUNNING) { |
| |
| try { |
| |
| // get an entry corresponding to orbId |
| EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId); |
| |
| portList = new EndPointInfo[serverListenerPorts.length]; |
| // return the port corresponding to the endpointType |
| for (int i = 0; i < serverListenerPorts.length; i++) { |
| if (debug) |
| System.out.println("lookup num-ports " + serverListenerPorts.length + " " |
| + serverListenerPorts[i].endpointType + " " + |
| serverListenerPorts[i].port ); |
| portList[i] = new EndPointInfo(serverListenerPorts[i].endpointType, serverListenerPorts[i].port); |
| } |
| } catch (NoSuchElementException e) { |
| // no element in HashMap corresponding to ORBid found |
| throw new InvalidORBid(); |
| } |
| return portList; |
| } |
| |
| if (debug) |
| printDebug("lookup", "throwing server held down error"); |
| |
| throw new ServerHeldDown( serverId ) ; |
| } |
| |
| synchronized String[] getORBList() |
| { |
| String [] orbList = new String[orbAndPortInfo.size()]; |
| Iterator setORBids = orbAndPortInfo.keySet().iterator(); |
| |
| try { |
| int numElements = 0; |
| while (setORBids.hasNext()) { |
| String orbId = (String) setORBids.next(); |
| orbList[numElements++] = orbId ; |
| } |
| } catch (NoSuchElementException e) { |
| // have everything in the table |
| } |
| return orbList; |
| } |
| |
| int getServerId() |
| { |
| return serverId; |
| } |
| |
| boolean isActive() |
| { |
| return (state == RUNNING) || (state == ACTIVATED); |
| } |
| |
| synchronized void destroy() |
| { |
| |
| Server localServerObj = null; |
| Process localProcess = null; |
| |
| synchronized (this) { |
| localServerObj = serverObj; |
| localProcess = process; |
| |
| deActivate(); |
| } |
| |
| try { |
| if (localServerObj != null) |
| localServerObj.shutdown(); |
| |
| if (debug) |
| printDebug( "destroy", "server shutdown successfully" ) ; |
| } catch (Exception ex) { |
| if (debug) |
| printDebug( "destroy", |
| "server shutdown threw exception" + ex ) ; |
| // ex.printStackTrace(); |
| } |
| |
| try { |
| if (localProcess != null) |
| localProcess.destroy(); |
| |
| if (debug) |
| printDebug( "destroy", "process destroyed successfully" ) ; |
| } catch (Exception ex) { |
| if (debug) |
| printDebug( "destroy", |
| "process destroy threw exception" + ex ) ; |
| |
| // ex.printStackTrace(); |
| } |
| } |
| |
| private boolean debug = false; |
| } |