1. /*
  2. * @(#)ServerTableEntry.java 1.28 03/06/25
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.activation;
  8. /**
  9. *
  10. * @version 1.28
  11. * @author Anita Jindal
  12. * @since JDK1.2
  13. */
  14. import org.omg.CORBA.CompletionStatus;
  15. import com.sun.corba.se.spi.activation.Server;
  16. import com.sun.corba.se.spi.activation.EndPointInfo;
  17. import com.sun.corba.se.spi.activation.ORBAlreadyRegistered;
  18. import com.sun.corba.se.spi.activation.ORBPortInfo;
  19. import com.sun.corba.se.spi.activation.InvalidORBid;
  20. import com.sun.corba.se.spi.activation.ServerHeldDown;
  21. import com.sun.corba.se.spi.activation.RepositoryPackage.ServerDef;
  22. import com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT;
  23. import com.sun.corba.se.spi.orb.ORB ;
  24. import com.sun.corba.se.impl.orbutil.ORBConstants;
  25. import com.sun.corba.se.impl.logging.ActivationSystemException ;
  26. import java.io.File;
  27. import java.util.HashMap;
  28. import java.util.Iterator;
  29. import java.util.NoSuchElementException;
  30. public class ServerTableEntry
  31. {
  32. private final static int DE_ACTIVATED = 0;
  33. private final static int ACTIVATING = 1;
  34. private final static int ACTIVATED = 2;
  35. private final static int RUNNING = 3;
  36. private final static int HELD_DOWN = 4;
  37. private String printState()
  38. {
  39. String str = "UNKNOWN";
  40. switch (state) {
  41. case (DE_ACTIVATED) : str = "DE_ACTIVATED"; break;
  42. case (ACTIVATING ) : str = "ACTIVATING "; break;
  43. case (ACTIVATED ) : str = "ACTIVATED "; break;
  44. case (RUNNING ) : str = "RUNNING "; break;
  45. case (HELD_DOWN ) : str = "HELD_DOWN "; break;
  46. default: break;
  47. }
  48. return str;
  49. }
  50. private final static long waitTime = 2000;
  51. private static final int ActivationRetryMax = 5;
  52. // state of each entry
  53. private int state;
  54. private int serverId;
  55. private HashMap orbAndPortInfo;
  56. private Server serverObj;
  57. private ServerDef serverDef;
  58. private Process process;
  59. private int activateRetryCount=0;
  60. private String activationCmd;
  61. private ActivationSystemException wrapper ;
  62. public String toString()
  63. {
  64. return "ServerTableEntry[" + "state=" + printState() +
  65. " serverId=" + serverId +
  66. " activateRetryCount=" + activateRetryCount + "]" ;
  67. }
  68. // get the string needed to make the activation command
  69. private static String javaHome, classPath, fileSep, pathSep;
  70. static {
  71. javaHome = System.getProperty("java.home");
  72. classPath = System.getProperty("java.class.path");
  73. fileSep = System.getProperty("file.separator");
  74. pathSep = System.getProperty("path.separator");
  75. }
  76. ServerTableEntry( ActivationSystemException wrapper,
  77. int serverId, ServerDef serverDef, int initialPort,
  78. String dbDirName, boolean verify, boolean debug )
  79. {
  80. this.wrapper = wrapper ;
  81. this.serverId = serverId;
  82. this.serverDef = serverDef;
  83. this.debug = debug ;
  84. // create a HashMap with capacity 255
  85. // Since all methods are synchronized, we don't need any
  86. // additional synchronization mechanisms
  87. orbAndPortInfo = new HashMap(255);
  88. activateRetryCount = 0;
  89. state = ACTIVATING;
  90. // compute the activation command
  91. activationCmd =
  92. // add path to the java vm
  93. javaHome + fileSep + "bin" + fileSep + "java " +
  94. // add any arguments to the server Java VM
  95. serverDef.serverVmArgs + " " +
  96. // add ORB properties
  97. "-Dioser=" + System.getProperty( "ioser" ) + " " +
  98. "-D" + ORBConstants.INITIAL_PORT_PROPERTY + "=" + initialPort + " " +
  99. "-D" + ORBConstants.DB_DIR_PROPERTY + "=" + dbDirName + " " +
  100. "-D" + ORBConstants.ACTIVATED_PROPERTY + "=true " +
  101. "-D" + ORBConstants.SERVER_ID_PROPERTY + "=" + serverId + " " +
  102. "-D" + ORBConstants.SERVER_NAME_PROPERTY + "=" + serverDef.serverName + " " +
  103. // we need to pass in the verify flag, so that the server is not
  104. // launched, when we try to validate its definition during registration
  105. // into the RepositoryImpl
  106. (verify ? "-D" + ORBConstants.SERVER_DEF_VERIFY_PROPERTY + "=true ": "") +
  107. // add classpath to the server
  108. "-classpath " + classPath +
  109. (serverDef.serverClassPath.equals("") == true ? "" : pathSep) +
  110. serverDef.serverClassPath +
  111. // add server class name and arguments
  112. " com.sun.corba.se.impl.activation.ServerMain " + serverDef.serverArgs
  113. // Add the debug flag, if any
  114. + (debug ? " -debug" : "") ;
  115. if (debug) System.out.println(
  116. "ServerTableEntry constructed with activation command " +
  117. activationCmd);
  118. }
  119. /**
  120. * Verify whether the server definition is valid.
  121. */
  122. public int verify()
  123. {
  124. try {
  125. if (debug)
  126. System.out.println("Server being verified w/" + activationCmd);
  127. process = Runtime.getRuntime().exec(activationCmd);
  128. int result = process.waitFor();
  129. if (debug)
  130. printDebug( "verify", "returns " + ServerMain.printResult( result ) ) ;
  131. return result ;
  132. } catch (Exception e) {
  133. if (debug)
  134. printDebug( "verify", "returns unknown error because of exception " +
  135. e ) ;
  136. return ServerMain.UNKNOWN_ERROR;
  137. }
  138. }
  139. private void printDebug(String method, String msg)
  140. {
  141. System.out.println("ServerTableEntry: method =" + method);
  142. System.out.println("ServerTableEntry: server =" + serverId);
  143. System.out.println("ServerTableEntry: state =" + printState());
  144. System.out.println("ServerTableEntry: message =" + msg);
  145. System.out.println();
  146. }
  147. synchronized void activate() throws org.omg.CORBA.SystemException
  148. {
  149. state = ACTIVATED;
  150. try {
  151. if (debug)
  152. printDebug("activate", "activating server");
  153. process = Runtime.getRuntime().exec(activationCmd);
  154. } catch (Exception e) {
  155. deActivate();
  156. if (debug)
  157. printDebug("activate", "throwing premature process exit");
  158. throw wrapper.unableToStartProcess() ;
  159. }
  160. }
  161. synchronized void register(Server server)
  162. {
  163. if (state == ACTIVATED) {
  164. serverObj = server;
  165. //state = RUNNING;
  166. //notifyAll();
  167. if (debug)
  168. printDebug("register", "process registered back");
  169. } else {
  170. if (debug)
  171. printDebug("register", "throwing premature process exit");
  172. throw wrapper.serverNotExpectedToRegister() ;
  173. }
  174. }
  175. synchronized void registerPorts( String orbId, EndPointInfo [] endpointList)
  176. throws ORBAlreadyRegistered
  177. {
  178. // find if the ORB is already registered, then throw an exception
  179. if (orbAndPortInfo.containsKey(orbId)) {
  180. throw new ORBAlreadyRegistered(orbId);
  181. }
  182. // store all listener ports and their types
  183. int numListenerPorts = endpointList.length;
  184. EndPointInfo [] serverListenerPorts = new EndPointInfo[numListenerPorts];
  185. for (int i = 0; i < numListenerPorts; i++) {
  186. serverListenerPorts[i] = new EndPointInfo (endpointList[i].endpointType, endpointList[i].port);
  187. if (debug)
  188. System.out.println("registering type: " + serverListenerPorts[i].endpointType + " port " + serverListenerPorts[i].port);
  189. }
  190. // put this set of listener ports in the HashMap associated
  191. // with the orbId
  192. orbAndPortInfo.put(orbId, serverListenerPorts);
  193. if (state == ACTIVATED) {
  194. state = RUNNING;
  195. notifyAll();
  196. }
  197. // _REVISIT_, If the state is not equal to ACTIVATED then it is a bug
  198. // need to log that error, once the Logging framework is in place
  199. // for rip-int.
  200. if (debug)
  201. printDebug("registerPorts", "process registered Ports");
  202. }
  203. void install()
  204. {
  205. Server localServerObj = null;
  206. synchronized ( this ) {
  207. if (state == RUNNING)
  208. localServerObj = serverObj;
  209. else
  210. throw wrapper.serverNotRunning() ;
  211. }
  212. if (localServerObj != null) {
  213. localServerObj.install() ;
  214. }
  215. }
  216. void uninstall()
  217. {
  218. Server localServerObj = null;
  219. Process localProcess = null;
  220. synchronized (this) {
  221. localServerObj = serverObj;
  222. localProcess = process;
  223. if (state == RUNNING) {
  224. deActivate();
  225. } else {
  226. throw wrapper.serverNotRunning() ;
  227. }
  228. }
  229. try {
  230. if (localServerObj != null) {
  231. localServerObj.shutdown(); // shutdown the server
  232. localServerObj.uninstall() ; // call the uninstall
  233. }
  234. if (localProcess != null) {
  235. localProcess.destroy();
  236. }
  237. } catch (Exception ex) {
  238. // what kind of exception should be thrown
  239. }
  240. }
  241. synchronized void holdDown()
  242. {
  243. state = HELD_DOWN;
  244. if (debug)
  245. printDebug( "holdDown", "server held down" ) ;
  246. notifyAll();
  247. }
  248. synchronized void deActivate()
  249. {
  250. state = DE_ACTIVATED;
  251. if (debug)
  252. printDebug( "deActivate", "server deactivated" ) ;
  253. notifyAll();
  254. }
  255. synchronized void checkProcessHealth( ) {
  256. // If the State in the ServerTableEntry is RUNNING and the
  257. // Process was shut down abnormally, The method will change the
  258. // server state as De-Activated.
  259. if( state == RUNNING ) {
  260. try {
  261. int exitVal = process.exitValue();
  262. } catch (IllegalThreadStateException e1) {
  263. return;
  264. }
  265. synchronized ( this ) {
  266. // Clear the PortInformation as it is old
  267. orbAndPortInfo.clear();
  268. // Move the state to De-Activated, So that the next
  269. // call to this server will re-activate.
  270. deActivate();
  271. }
  272. }
  273. }
  274. synchronized boolean isValid()
  275. {
  276. if ((state == ACTIVATING) || (state == HELD_DOWN)) {
  277. if (debug)
  278. printDebug( "isValid", "returns true" ) ;
  279. return true;
  280. }
  281. try {
  282. int exitVal = process.exitValue();
  283. } catch (IllegalThreadStateException e1) {
  284. return true;
  285. }
  286. if (state == ACTIVATED) {
  287. if (activateRetryCount < ActivationRetryMax) {
  288. if (debug)
  289. printDebug("isValid", "reactivating server");
  290. activateRetryCount++;
  291. activate();
  292. return true;
  293. }
  294. if (debug)
  295. printDebug("isValid", "holding server down");
  296. holdDown();
  297. return true;
  298. }
  299. deActivate();
  300. return false;
  301. }
  302. synchronized ORBPortInfo[] lookup(String endpointType) throws ServerHeldDown
  303. {
  304. while ((state == ACTIVATING) || (state == ACTIVATED)) {
  305. try {
  306. wait(waitTime);
  307. if (!isValid()) break;
  308. } catch(Exception e) {}
  309. }
  310. ORBPortInfo[] orbAndPortList = null;
  311. if (state == RUNNING) {
  312. orbAndPortList = new ORBPortInfo[orbAndPortInfo.size()];
  313. Iterator setORBids = orbAndPortInfo.keySet().iterator();
  314. try {
  315. int numElements = 0;
  316. int i;
  317. int port;
  318. while (setORBids.hasNext()) {
  319. String orbId = (String) setORBids.next();
  320. // get an entry corresponding to orbId
  321. EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId);
  322. port = -1;
  323. // return the port corresponding to the endpointType
  324. for (i = 0; i < serverListenerPorts.length; i++) {
  325. if (debug)
  326. System.out.println("lookup num-ports " + serverListenerPorts.length + " " +
  327. serverListenerPorts[i].endpointType + " " +
  328. serverListenerPorts[i].port );
  329. if ((serverListenerPorts[i].endpointType).equals(endpointType)) {
  330. port = serverListenerPorts[i].port;
  331. break;
  332. }
  333. }
  334. orbAndPortList[numElements] = new ORBPortInfo(orbId, port);
  335. numElements++;
  336. }
  337. } catch (NoSuchElementException e) {
  338. // have everything in the table
  339. }
  340. return orbAndPortList;
  341. }
  342. if (debug)
  343. printDebug("lookup", "throwing server held down error");
  344. throw new ServerHeldDown( serverId ) ;
  345. }
  346. synchronized EndPointInfo[] lookupForORB(String orbId)
  347. throws ServerHeldDown, InvalidORBid
  348. {
  349. while ((state == ACTIVATING) || (state == ACTIVATED)) {
  350. try {
  351. wait(waitTime);
  352. if (!isValid()) break;
  353. } catch(Exception e) {}
  354. }
  355. EndPointInfo[] portList = null;
  356. if (state == RUNNING) {
  357. try {
  358. // get an entry corresponding to orbId
  359. EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId);
  360. portList = new EndPointInfo[serverListenerPorts.length];
  361. // return the port corresponding to the endpointType
  362. for (int i = 0; i < serverListenerPorts.length; i++) {
  363. if (debug)
  364. System.out.println("lookup num-ports " + serverListenerPorts.length + " "
  365. + serverListenerPorts[i].endpointType + " " +
  366. serverListenerPorts[i].port );
  367. portList[i] = new EndPointInfo(serverListenerPorts[i].endpointType, serverListenerPorts[i].port);
  368. }
  369. } catch (NoSuchElementException e) {
  370. // no element in HashMap corresponding to ORBid found
  371. throw new InvalidORBid();
  372. }
  373. return portList;
  374. }
  375. if (debug)
  376. printDebug("lookup", "throwing server held down error");
  377. throw new ServerHeldDown( serverId ) ;
  378. }
  379. synchronized String[] getORBList()
  380. {
  381. String [] orbList = new String[orbAndPortInfo.size()];
  382. Iterator setORBids = orbAndPortInfo.keySet().iterator();
  383. try {
  384. int numElements = 0;
  385. while (setORBids.hasNext()) {
  386. String orbId = (String) setORBids.next();
  387. orbList[numElements++] = orbId ;
  388. }
  389. } catch (NoSuchElementException e) {
  390. // have everything in the table
  391. }
  392. return orbList;
  393. }
  394. int getServerId()
  395. {
  396. return serverId;
  397. }
  398. boolean isActive()
  399. {
  400. return (state == RUNNING) || (state == ACTIVATED);
  401. }
  402. synchronized void destroy()
  403. {
  404. Server localServerObj = null;
  405. Process localProcess = null;
  406. synchronized (this) {
  407. localServerObj = serverObj;
  408. localProcess = process;
  409. deActivate();
  410. }
  411. try {
  412. if (localServerObj != null)
  413. localServerObj.shutdown();
  414. if (debug)
  415. printDebug( "destroy", "server shutdown successfully" ) ;
  416. } catch (Exception ex) {
  417. if (debug)
  418. printDebug( "destroy",
  419. "server shutdown threw exception" + ex ) ;
  420. // ex.printStackTrace();
  421. }
  422. try {
  423. if (localProcess != null)
  424. localProcess.destroy();
  425. if (debug)
  426. printDebug( "destroy", "process destroyed successfully" ) ;
  427. } catch (Exception ex) {
  428. if (debug)
  429. printDebug( "destroy",
  430. "process destroy threw exception" + ex ) ;
  431. // ex.printStackTrace();
  432. }
  433. }
  434. private boolean debug = false;
  435. }