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