1. /*
  2. * @(#)ServerMain.java 1.19 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * @(#)ServerMain.java 1.19 03/12/19
  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.impl.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.spi.activation.Activator ;
  30. import com.sun.corba.se.spi.activation.ActivatorHelper ;
  31. import com.sun.corba.se.impl.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",
  243. "com.sun.corba.se.impl.orb.ORBImpl" ) ;
  244. // NOTE: Very important to pass this property, otherwise the
  245. // Persistent Server registration will be unsucessfull.
  246. props.put( ORBConstants.ACTIVATED_PROPERTY, "false" );
  247. String args[] = null ;
  248. ORB orb = ORB.init( args, props ) ;
  249. ServerCallback serverObj = new ServerCallback( orb,
  250. installMethod, uninstallMethod, shutdownMethod ) ;
  251. int serverId = getServerId() ;
  252. try {
  253. Activator activator = ActivatorHelper.narrow(
  254. orb.resolve_initial_references( ORBConstants.SERVER_ACTIVATOR_NAME ));
  255. activator.active(serverId, serverObj);
  256. } catch (Exception ex) {
  257. logTerminal( "exception " + ex.getMessage(),
  258. REGISTRATION_FAILED ) ;
  259. }
  260. }
  261. }
  262. class ServerCallback extends
  263. com.sun.corba.se.spi.activation._ServerImplBase
  264. {
  265. private ORB orb;
  266. private Method installMethod ;
  267. private Method uninstallMethod ;
  268. private Method shutdownMethod ;
  269. private Object methodArgs[] ;
  270. ServerCallback(ORB orb, Method installMethod, Method uninstallMethod,
  271. Method shutdownMethod )
  272. {
  273. this.orb = orb;
  274. this.installMethod = installMethod ;
  275. this.uninstallMethod = uninstallMethod ;
  276. this.shutdownMethod = shutdownMethod ;
  277. orb.connect( this ) ;
  278. methodArgs = new Object[] { orb } ;
  279. }
  280. private void invokeMethod( Method method )
  281. {
  282. if (method != null)
  283. try {
  284. method.invoke( null, methodArgs ) ;
  285. } catch (Exception exc) {
  286. ServerMain.logError( "could not invoke " + method.getName() +
  287. " method: " + exc.getMessage() ) ;
  288. }
  289. }
  290. // shutdown the ORB and wait for completion
  291. public void shutdown()
  292. {
  293. ServerMain.logInformation( "Shutdown starting" ) ;
  294. invokeMethod( shutdownMethod ) ;
  295. orb.shutdown(true);
  296. ServerMain.logTerminal( "Shutdown completed", ServerMain.OK ) ;
  297. }
  298. public void install()
  299. {
  300. ServerMain.logInformation( "Install starting" ) ;
  301. invokeMethod( installMethod ) ;
  302. ServerMain.logInformation( "Install completed" ) ;
  303. }
  304. public void uninstall()
  305. {
  306. ServerMain.logInformation( "uninstall starting" ) ;
  307. invokeMethod( uninstallMethod ) ;
  308. ServerMain.logInformation( "uninstall completed" ) ;
  309. }
  310. }