1 /* 2 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.corba.se.impl.activation; 26 27 /** 28 * 29 * @author Anita Jindal 30 * @since 1.2 31 */ 32 33 import org.omg.CORBA.CompletionStatus; 34 35 import com.sun.corba.se.spi.activation.Server; 36 import com.sun.corba.se.spi.activation.EndPointInfo; 37 import com.sun.corba.se.spi.activation.ORBAlreadyRegistered; 38 import com.sun.corba.se.spi.activation.ORBPortInfo; 39 import com.sun.corba.se.spi.activation.InvalidORBid; 40 import com.sun.corba.se.spi.activation.ServerHeldDown; 41 import com.sun.corba.se.spi.activation.RepositoryPackage.ServerDef; 42 import com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT; 43 import com.sun.corba.se.spi.orb.ORB ; 44 45 import com.sun.corba.se.impl.orbutil.ORBConstants; 46 import com.sun.corba.se.impl.logging.ActivationSystemException ; 47 48 import java.io.File; 49 import java.util.HashMap; 50 import java.util.Iterator; 51 import java.util.NoSuchElementException; 52 53 public class ServerTableEntry 54 { 55 56 private final static int DE_ACTIVATED = 0; 57 private final static int ACTIVATING = 1; 58 private final static int ACTIVATED = 2; 59 private final static int RUNNING = 3; 60 private final static int HELD_DOWN = 4; 61 62 63 private String printState() 64 { 65 String str = "UNKNOWN"; 66 67 switch (state) { 68 case (DE_ACTIVATED) : str = "DE_ACTIVATED"; break; 69 case (ACTIVATING ) : str = "ACTIVATING "; break; 70 case (ACTIVATED ) : str = "ACTIVATED "; break; 71 case (RUNNING ) : str = "RUNNING "; break; 72 case (HELD_DOWN ) : str = "HELD_DOWN "; break; 73 default: break; 74 } 75 76 return str; 77 } 78 79 private final static long waitTime = 2000; 80 private static final int ActivationRetryMax = 5; 81 82 // state of each entry 83 private int state; 84 private int serverId; 85 private HashMap orbAndPortInfo; 86 private Server serverObj; 87 private ServerDef serverDef; 88 private Process process; 89 private int activateRetryCount=0; 90 private String activationCmd; 91 private ActivationSystemException wrapper ; 92 public String toString() 93 { 94 return "ServerTableEntry[" + "state=" + printState() + 95 " serverId=" + serverId + 96 " activateRetryCount=" + activateRetryCount + "]" ; 97 } 98 99 // get the string needed to make the activation command 100 private static String javaHome, classPath, fileSep, pathSep; 101 102 static { 103 javaHome = System.getProperty("java.home"); 104 classPath = System.getProperty("java.class.path"); 105 fileSep = System.getProperty("file.separator"); 106 pathSep = System.getProperty("path.separator"); 107 } 108 109 ServerTableEntry( ActivationSystemException wrapper, 110 int serverId, ServerDef serverDef, int initialPort, 111 String dbDirName, boolean verify, boolean debug ) 112 { 113 this.wrapper = wrapper ; 114 this.serverId = serverId; 115 this.serverDef = serverDef; 116 this.debug = debug ; 117 // create a HashMap with capacity 255 118 // Since all methods are synchronized, we don't need any 119 // additional synchronization mechanisms 120 orbAndPortInfo = new HashMap(255); 121 122 activateRetryCount = 0; 123 state = ACTIVATING; 124 125 // compute the activation command 126 activationCmd = 127 128 // add path to the java vm 129 javaHome + fileSep + "bin" + fileSep + "java " + 130 131 // add any arguments to the server Java VM 132 serverDef.serverVmArgs + " " + 133 134 // add ORB properties 135 "-Dioser=" + System.getProperty( "ioser" ) + " " + 136 "-D" + ORBConstants.INITIAL_PORT_PROPERTY + "=" + initialPort + " " + 137 "-D" + ORBConstants.DB_DIR_PROPERTY + "=" + dbDirName + " " + 138 "-D" + ORBConstants.ACTIVATED_PROPERTY + "=true " + 139 "-D" + ORBConstants.SERVER_ID_PROPERTY + "=" + serverId + " " + 140 "-D" + ORBConstants.SERVER_NAME_PROPERTY + "=" + serverDef.serverName + " " + 141 // we need to pass in the verify flag, so that the server is not 142 // launched, when we try to validate its definition during registration 143 // into the RepositoryImpl 144 145 (verify ? "-D" + ORBConstants.SERVER_DEF_VERIFY_PROPERTY + "=true ": "") + 146 147 // add classpath to the server 148 "-classpath " + classPath + 149 (serverDef.serverClassPath.equals("") == true ? "" : pathSep) + 150 serverDef.serverClassPath + 151 152 // add server class name and arguments 153 " com.sun.corba.se.impl.activation.ServerMain " + serverDef.serverArgs 154 155 // Add the debug flag, if any 156 + (debug ? " -debug" : "") ; 157 158 if (debug) System.out.println( 159 "ServerTableEntry constructed with activation command " + 160 activationCmd); 161 } 162 163 /** 164 * Verify whether the server definition is valid. 165 */ 166 public int verify() 167 { 168 try { 169 170 if (debug) 171 System.out.println("Server being verified w/" + activationCmd); 172 173 process = Runtime.getRuntime().exec(activationCmd); 174 int result = process.waitFor(); 175 if (debug) 176 printDebug( "verify", "returns " + ServerMain.printResult( result ) ) ; 177 return result ; 178 } catch (Exception e) { 179 if (debug) 180 printDebug( "verify", "returns unknown error because of exception " + 181 e ) ; 182 return ServerMain.UNKNOWN_ERROR; 183 } 184 } 185 186 private void printDebug(String method, String msg) 187 { 188 System.out.println("ServerTableEntry: method =" + method); 189 System.out.println("ServerTableEntry: server =" + serverId); 190 System.out.println("ServerTableEntry: state =" + printState()); 191 System.out.println("ServerTableEntry: message =" + msg); 192 System.out.println(); 193 } 194 195 synchronized void activate() throws org.omg.CORBA.SystemException 196 { 197 state = ACTIVATED; 198 199 try { 200 if (debug) 201 printDebug("activate", "activating server"); 202 process = Runtime.getRuntime().exec(activationCmd); 203 } catch (Exception e) { 204 deActivate(); 205 if (debug) 206 printDebug("activate", "throwing premature process exit"); 207 throw wrapper.unableToStartProcess() ; 208 } 209 } 210 211 synchronized void register(Server server) 212 { 213 if (state == ACTIVATED) { 214 215 serverObj = server; 216 217 //state = RUNNING; 218 //notifyAll(); 219 220 if (debug) 221 printDebug("register", "process registered back"); 222 223 } else { 224 225 if (debug) 226 printDebug("register", "throwing premature process exit"); 227 throw wrapper.serverNotExpectedToRegister() ; 228 } 229 } 230 231 synchronized void registerPorts( String orbId, EndPointInfo [] endpointList) 232 throws ORBAlreadyRegistered 233 { 234 235 // find if the ORB is already registered, then throw an exception 236 if (orbAndPortInfo.containsKey(orbId)) { 237 throw new ORBAlreadyRegistered(orbId); 238 } 239 240 // store all listener ports and their types 241 int numListenerPorts = endpointList.length; 242 EndPointInfo [] serverListenerPorts = new EndPointInfo[numListenerPorts]; 243 244 for (int i = 0; i < numListenerPorts; i++) { 245 serverListenerPorts[i] = new EndPointInfo (endpointList[i].endpointType, endpointList[i].port); 246 if (debug) 247 System.out.println("registering type: " + serverListenerPorts[i].endpointType + " port " + serverListenerPorts[i].port); 248 } 249 250 // put this set of listener ports in the HashMap associated 251 // with the orbId 252 orbAndPortInfo.put(orbId, serverListenerPorts); 253 if (state == ACTIVATED) { 254 state = RUNNING; 255 notifyAll(); 256 } 257 // _REVISIT_, If the state is not equal to ACTIVATED then it is a bug 258 // need to log that error, once the Logging framework is in place 259 // for rip-int. 260 if (debug) 261 printDebug("registerPorts", "process registered Ports"); 262 } 263 264 void install() 265 { 266 Server localServerObj = null; 267 synchronized ( this ) { 268 if (state == RUNNING) 269 localServerObj = serverObj; 270 else 271 throw wrapper.serverNotRunning() ; 272 } 273 if (localServerObj != null) { 274 localServerObj.install() ; 275 } 276 277 } 278 279 void uninstall() 280 { 281 Server localServerObj = null; 282 Process localProcess = null; 283 284 synchronized (this) { 285 localServerObj = serverObj; 286 localProcess = process; 287 288 if (state == RUNNING) { 289 290 deActivate(); 291 292 } else { 293 throw wrapper.serverNotRunning() ; 294 } 295 } 296 try { 297 if (localServerObj != null) { 298 localServerObj.shutdown(); // shutdown the server 299 localServerObj.uninstall() ; // call the uninstall 300 } 301 302 if (localProcess != null) { 303 localProcess.destroy(); 304 } 305 } catch (Exception ex) { 306 // what kind of exception should be thrown 307 } 308 } 309 310 synchronized void holdDown() 311 { 312 state = HELD_DOWN; 313 314 if (debug) 315 printDebug( "holdDown", "server held down" ) ; 316 317 notifyAll(); 318 } 319 320 synchronized void deActivate() 321 { 322 state = DE_ACTIVATED; 323 324 if (debug) 325 printDebug( "deActivate", "server deactivated" ) ; 326 327 notifyAll(); 328 } 329 330 synchronized void checkProcessHealth( ) { 331 // If the State in the ServerTableEntry is RUNNING and the 332 // Process was shut down abnormally, The method will change the 333 // server state as De-Activated. 334 if( state == RUNNING ) { 335 try { 336 int exitVal = process.exitValue(); 337 } catch (IllegalThreadStateException e1) { 338 return; 339 } 340 synchronized ( this ) { 341 // Clear the PortInformation as it is old 342 orbAndPortInfo.clear(); 343 // Move the state to De-Activated, So that the next 344 // call to this server will re-activate. 345 deActivate(); 346 } 347 } 348 } 349 350 synchronized boolean isValid() 351 { 352 if ((state == ACTIVATING) || (state == HELD_DOWN)) { 353 if (debug) 354 printDebug( "isValid", "returns true" ) ; 355 356 return true; 357 } 358 359 try { 360 int exitVal = process.exitValue(); 361 } catch (IllegalThreadStateException e1) { 362 return true; 363 } 364 365 if (state == ACTIVATED) { 366 if (activateRetryCount < ActivationRetryMax) { 367 if (debug) 368 printDebug("isValid", "reactivating server"); 369 activateRetryCount++; 370 activate(); 371 return true; 372 } 373 374 if (debug) 375 printDebug("isValid", "holding server down"); 376 377 holdDown(); 378 return true; 379 } 380 381 deActivate(); 382 return false; 383 } 384 385 synchronized ORBPortInfo[] lookup(String endpointType) throws ServerHeldDown 386 { 387 while ((state == ACTIVATING) || (state == ACTIVATED)) { 388 try { 389 wait(waitTime); 390 if (!isValid()) break; 391 } catch(Exception e) {} 392 } 393 ORBPortInfo[] orbAndPortList = null; 394 395 if (state == RUNNING) { 396 orbAndPortList = new ORBPortInfo[orbAndPortInfo.size()]; 397 Iterator setORBids = orbAndPortInfo.keySet().iterator(); 398 399 try { 400 int numElements = 0; 401 int i; 402 int port; 403 while (setORBids.hasNext()) { 404 String orbId = (String) setORBids.next(); 405 // get an entry corresponding to orbId 406 EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId); 407 port = -1; 408 // return the port corresponding to the endpointType 409 for (i = 0; i < serverListenerPorts.length; i++) { 410 if (debug) 411 System.out.println("lookup num-ports " + serverListenerPorts.length + " " + 412 serverListenerPorts[i].endpointType + " " + 413 serverListenerPorts[i].port ); 414 if ((serverListenerPorts[i].endpointType).equals(endpointType)) { 415 port = serverListenerPorts[i].port; 416 break; 417 } 418 } 419 orbAndPortList[numElements] = new ORBPortInfo(orbId, port); 420 numElements++; 421 } 422 } catch (NoSuchElementException e) { 423 // have everything in the table 424 } 425 return orbAndPortList; 426 } 427 428 if (debug) 429 printDebug("lookup", "throwing server held down error"); 430 431 throw new ServerHeldDown( serverId ) ; 432 } 433 434 synchronized EndPointInfo[] lookupForORB(String orbId) 435 throws ServerHeldDown, InvalidORBid 436 { 437 while ((state == ACTIVATING) || (state == ACTIVATED)) { 438 try { 439 wait(waitTime); 440 if (!isValid()) break; 441 } catch(Exception e) {} 442 } 443 EndPointInfo[] portList = null; 444 445 if (state == RUNNING) { 446 447 try { 448 449 // get an entry corresponding to orbId 450 EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId); 451 452 portList = new EndPointInfo[serverListenerPorts.length]; 453 // return the port corresponding to the endpointType 454 for (int i = 0; i < serverListenerPorts.length; i++) { 455 if (debug) 456 System.out.println("lookup num-ports " + serverListenerPorts.length + " " 457 + serverListenerPorts[i].endpointType + " " + 458 serverListenerPorts[i].port ); 459 portList[i] = new EndPointInfo(serverListenerPorts[i].endpointType, serverListenerPorts[i].port); 460 } 461 } catch (NoSuchElementException e) { 462 // no element in HashMap corresponding to ORBid found 463 throw new InvalidORBid(); 464 } 465 return portList; 466 } 467 468 if (debug) 469 printDebug("lookup", "throwing server held down error"); 470 471 throw new ServerHeldDown( serverId ) ; 472 } 473 474 synchronized String[] getORBList() 475 { 476 String [] orbList = new String[orbAndPortInfo.size()]; 477 Iterator setORBids = orbAndPortInfo.keySet().iterator(); 478 479 try { 480 int numElements = 0; 481 while (setORBids.hasNext()) { 482 String orbId = (String) setORBids.next(); 483 orbList[numElements++] = orbId ; 484 } 485 } catch (NoSuchElementException e) { 486 // have everything in the table 487 } 488 return orbList; 489 } 490 491 int getServerId() 492 { 493 return serverId; 494 } 495 496 boolean isActive() 497 { 498 return (state == RUNNING) || (state == ACTIVATED); 499 } 500 501 synchronized void destroy() 502 { 503 504 Server localServerObj = null; 505 Process localProcess = null; 506 507 synchronized (this) { 508 localServerObj = serverObj; 509 localProcess = process; 510 511 deActivate(); 512 } 513 514 try { 515 if (localServerObj != null) 516 localServerObj.shutdown(); 517 518 if (debug) 519 printDebug( "destroy", "server shutdown successfully" ) ; 520 } catch (Exception ex) { 521 if (debug) 522 printDebug( "destroy", 523 "server shutdown threw exception" + ex ) ; 524 // ex.printStackTrace(); 525 } 526 527 try { 528 if (localProcess != null) 529 localProcess.destroy(); 530 531 if (debug) 532 printDebug( "destroy", "process destroyed successfully" ) ; 533 } catch (Exception ex) { 534 if (debug) 535 printDebug( "destroy", 536 "process destroy threw exception" + ex ) ; 537 538 // ex.printStackTrace(); 539 } 540 } 541 542 private boolean debug = false; 543 }