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