ServerMain.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 1997, 2012, 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 26package com.sun.corba.se.impl.activation; 27 28import java.lang.reflect.Method; 29import java.lang.reflect.Modifier; 30import java.io.*; 31import java.util.Date; 32import java.util.Properties ; 33 34import org.omg.CORBA.ORB ; 35import com.sun.corba.se.spi.activation.Activator ; 36import com.sun.corba.se.spi.activation.ActivatorHelper ; 37import com.sun.corba.se.impl.orbutil.ORBConstants ; 38 39/** 40 * @author Ken Cavanaugh 41 * @since JDK1.2 42 */ 43public class ServerMain 44{ 45 /* TODO: 46 * 1. Rewrite all uses of ORB properties to use constants from someplace. 47 * The strings are scattered between here, the ORB classes, and 48 * ServerTableEntry. 49 * 2. Consider a more general log facility. 50 * 3. Remove ServerCallback from POAORB. 51 * 4. Needs to be merged with Harold's changes to support SSL. 52 * 5. Logs need to be internationalized. 53 */ 54 55 public final static int OK = 0; 56 public final static int MAIN_CLASS_NOT_FOUND = 1; 57 public final static int NO_MAIN_METHOD = 2; 58 public final static int APPLICATION_ERROR = 3; 59 public final static int UNKNOWN_ERROR = 4; 60 public final static int NO_SERVER_ID = 5 ; 61 public final static int REGISTRATION_FAILED = 6; 62 63 public static String printResult( int result ) 64 { 65 switch (result) { 66 case OK : return "Server terminated normally" ; 67 case MAIN_CLASS_NOT_FOUND : return "main class not found" ; 68 case NO_MAIN_METHOD : return "no main method" ; 69 case APPLICATION_ERROR : return "application error" ; 70 case NO_SERVER_ID : return "server ID not defined" ; 71 case REGISTRATION_FAILED: return "server registration failed" ; 72 default : return "unknown error" ; 73 } 74 } 75 76 private void redirectIOStreams() 77 { 78 // redirect out and err streams 79 try { 80 String logDirName = 81 System.getProperty( ORBConstants.DB_DIR_PROPERTY ) + 82 System.getProperty("file.separator") + 83 ORBConstants.SERVER_LOG_DIR + 84 System.getProperty("file.separator"); 85 86 File logDir = new File(logDirName); 87 String server = System.getProperty( 88 ORBConstants.SERVER_ID_PROPERTY ) ; 89 90 FileOutputStream foutStream = 91 new FileOutputStream(logDirName + server+".out", true); 92 FileOutputStream ferrStream = 93 new FileOutputStream(logDirName + server+".err", true); 94 95 PrintStream pSout = new PrintStream(foutStream, true); 96 PrintStream pSerr = new PrintStream(ferrStream, true); 97 98 System.setOut(pSout); 99 System.setErr(pSerr); 100 101 logInformation( "Server started" ) ; 102 103 } catch (Exception ex) {} 104 } 105 106 /** Write a time-stamped message to the indicated PrintStream. 107 */ 108 private static void writeLogMessage( PrintStream pstream, String msg ) 109 { 110 Date date = new Date(); 111 pstream.print( "[" + date.toString() + "] " + msg + "\n"); 112 } 113 114 /** Write information to standard out only. 115 */ 116 public static void logInformation( String msg ) 117 { 118 writeLogMessage( System.out, " " + msg ) ; 119 } 120 121 /** Write error message to standard out and standard err. 122 */ 123 public static void logError( String msg ) 124 { 125 writeLogMessage( System.out, "ERROR: " + msg ) ; 126 writeLogMessage( System.err, "ERROR: " + msg ) ; 127 } 128 129 /** Write final message to log(s) and then terminate by calling 130 * System.exit( code ). If code == OK, write a normal termination 131 * message to standard out, otherwise write an abnormal termination 132 * message to standard out and standard error. 133 */ 134 public static void logTerminal( String msg, int code ) 135 { 136 if (code == 0) { 137 writeLogMessage( System.out, " " + msg ) ; 138 } else { 139 writeLogMessage( System.out, "FATAL: " + 140 printResult( code ) + ": " + msg ) ; 141 142 writeLogMessage( System.err, "FATAL: " + 143 printResult( code ) + ": " + msg ) ; 144 } 145 146 System.exit( code ) ; 147 } 148 149 private Method getMainMethod( Class serverClass ) 150 { 151 Class argTypes[] = new Class[] { String[].class } ; 152 Method method = null ; 153 154 try { 155 method = serverClass.getDeclaredMethod( "main", argTypes ) ; 156 } catch (Exception exc) { 157 logTerminal( exc.getMessage(), NO_MAIN_METHOD ) ; 158 } 159 160 if (!isPublicStaticVoid( method )) 161 logTerminal( "", NO_MAIN_METHOD ) ; 162 163 return method ; 164 } 165 166 private boolean isPublicStaticVoid( Method method ) 167 { 168 // check modifiers: public static 169 int modifiers = method.getModifiers (); 170 if (!Modifier.isPublic (modifiers) || !Modifier.isStatic (modifiers)) { 171 logError( method.getName() + " is not public static" ) ; 172 return false ; 173 } 174 175 // check return type and exceptions 176 if (method.getExceptionTypes ().length != 0) { 177 logError( method.getName() + " declares exceptions" ) ; 178 return false ; 179 } 180 181 if (!method.getReturnType().equals (Void.TYPE)) { 182 logError( method.getName() + " does not have a void return type" ) ; 183 return false ; 184 } 185 186 return true ; 187 } 188 189 private Method getNamedMethod( Class serverClass, String methodName ) 190 { 191 Class argTypes[] = new Class[] { org.omg.CORBA.ORB.class } ; 192 Method method = null ; 193 194 try { 195 method = serverClass.getDeclaredMethod( methodName, argTypes ) ; 196 } catch (Exception exc) { 197 return null ; 198 } 199 200 if (!isPublicStaticVoid( method )) 201 return null ; 202 203 return method ; 204 } 205 206 private void run(String[] args) 207 { 208 try { 209 redirectIOStreams() ; 210 211 String serverClassName = System.getProperty( 212 ORBConstants.SERVER_NAME_PROPERTY ) ; 213 214 // determine the class loader to be used for loading the class 215 // since ServerMain is going to be in JDK and we need to have this 216 // class to load application classes, this is required here. 217 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 218 219 if (cl == null) 220 cl = ClassLoader.getSystemClassLoader(); 221 222 // determine the main class 223 Class serverClass = null; 224 225 try { 226 // determine the main class, try loading with current class loader 227 serverClass = Class.forName( serverClassName ) ; 228 } catch (ClassNotFoundException ex) { 229 // eat the exception and try to load using SystemClassLoader 230 serverClass = Class.forName( serverClassName, true, cl); 231 } 232 233 if (debug) 234 System.out.println("class " + serverClassName + " found"); 235 236 // get the main method 237 Method mainMethod = getMainMethod( serverClass ) ; 238 239 // This piece of code is required, to verify the server definition 240 // without launching it. 241 242 // verify the server 243 244 boolean serverVerifyFlag = Boolean.getBoolean( 245 ORBConstants.SERVER_DEF_VERIFY_PROPERTY) ; 246 if (serverVerifyFlag) { 247 if (mainMethod == null) 248 logTerminal("", NO_MAIN_METHOD); 249 else { 250 if (debug) 251 System.out.println("Valid Server"); 252 logTerminal("", OK); 253 } 254 } 255 256 257 registerCallback( serverClass ) ; 258 259 // build args to the main and call it 260 Object params [] = new Object [1]; 261 params[0] = args; 262 mainMethod.invoke(null, params); 263 264 } catch (ClassNotFoundException e) { 265 logTerminal("ClassNotFound exception: " + e.getMessage(), 266 MAIN_CLASS_NOT_FOUND); 267 } catch (Exception e) { 268 logTerminal("Exception: " + e.getMessage(), 269 APPLICATION_ERROR); 270 } 271 } 272 273 public static void main(String[] args) { 274 ServerMain server = new ServerMain(); 275 server.run(args); 276 } 277 278 private static final boolean debug = false; 279 280 private int getServerId() 281 { 282 Integer serverId = Integer.getInteger( ORBConstants.SERVER_ID_PROPERTY ) ; 283 284 if (serverId == null) 285 logTerminal( "", NO_SERVER_ID ) ; 286 287 return serverId.intValue() ; 288 } 289 290 private void registerCallback( Class serverClass ) 291 { 292 Method installMethod = getNamedMethod( serverClass, "install" ) ; 293 Method uninstallMethod = getNamedMethod( serverClass, "uninstall" ) ; 294 Method shutdownMethod = getNamedMethod( serverClass, "shutdown" ) ; 295 296 Properties props = new Properties() ; 297 props.put( "org.omg.CORBA.ORBClass", 298 "com.sun.corba.se.impl.orb.ORBImpl" ) ; 299 // NOTE: Very important to pass this property, otherwise the 300 // Persistent Server registration will be unsucessfull. 301 props.put( ORBConstants.ACTIVATED_PROPERTY, "false" ); 302 String args[] = null ; 303 ORB orb = ORB.init( args, props ) ; 304 305 ServerCallback serverObj = new ServerCallback( orb, 306 installMethod, uninstallMethod, shutdownMethod ) ; 307 308 int serverId = getServerId() ; 309 310 try { 311 Activator activator = ActivatorHelper.narrow( 312 orb.resolve_initial_references( ORBConstants.SERVER_ACTIVATOR_NAME )); 313 activator.active(serverId, serverObj); 314 } catch (Exception ex) { 315 logTerminal( "exception " + ex.getMessage(), 316 REGISTRATION_FAILED ) ; 317 } 318 } 319} 320 321class ServerCallback extends 322 com.sun.corba.se.spi.activation._ServerImplBase 323{ 324 private ORB orb; 325 private transient Method installMethod ; 326 private transient Method uninstallMethod ; 327 private transient Method shutdownMethod ; 328 private Object methodArgs[] ; 329 330 ServerCallback(ORB orb, Method installMethod, Method uninstallMethod, 331 Method shutdownMethod ) 332 { 333 this.orb = orb; 334 this.installMethod = installMethod ; 335 this.uninstallMethod = uninstallMethod ; 336 this.shutdownMethod = shutdownMethod ; 337 338 orb.connect( this ) ; 339 340 methodArgs = new Object[] { orb } ; 341 } 342 343 private void invokeMethod( Method method ) 344 { 345 if (method != null) 346 try { 347 method.invoke( null, methodArgs ) ; 348 } catch (Exception exc) { 349 ServerMain.logError( "could not invoke " + method.getName() + 350 " method: " + exc.getMessage() ) ; 351 } 352 } 353 354 // shutdown the ORB and wait for completion 355 public void shutdown() 356 { 357 ServerMain.logInformation( "Shutdown starting" ) ; 358 359 invokeMethod( shutdownMethod ) ; 360 361 orb.shutdown(true); 362 363 ServerMain.logTerminal( "Shutdown completed", ServerMain.OK ) ; 364 } 365 366 public void install() 367 { 368 ServerMain.logInformation( "Install starting" ) ; 369 370 invokeMethod( installMethod ) ; 371 372 ServerMain.logInformation( "Install completed" ) ; 373 } 374 375 public void uninstall() 376 { 377 ServerMain.logInformation( "uninstall starting" ) ; 378 379 invokeMethod( uninstallMethod ) ; 380 381 ServerMain.logInformation( "uninstall completed" ) ; 382 } 383} 384