--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.iapi.jdbc.DRDAServerStarter\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.iapi.jdbc;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.monitor.ModuleControl;\r
+import org.apache.derby.iapi.reference.MessageId;\r
+import org.apache.derby.iapi.reference.Property;\r
+import java.io.PrintWriter;\r
+import java.lang.Runnable;\r
+import java.lang.Thread;\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.net.InetAddress;\r
+import java.security.AccessController;\r
+import java.security.PrivilegedAction;\r
+import java.security.PrivilegedActionException;\r
+import java.security.PrivilegedExceptionAction;\r
+\r
+/**\r
+ * Class that starts the network server in its own daemon thread.\r
+ * Works in two situations.\r
+ * <BR>\r
+ * As a module in the engine's Monitor, booted if the\r
+ * property derby.drda.startNetworkServer is set to true.\r
+ * In this case the boot and shutdown is through the\r
+ * standard ModuleControl methods.\r
+ * <BR>\r
+ * Direct calls from the NetworkServerControlImpl start methods.\r
+ * This is to centralize the creation of the daemon thread in\r
+ * this class in the engine code, since the Monitor provides\r
+ * the thread. This means that NetworkServerControlImpl calls\r
+ * this class to create a thread which in turn calls back\r
+ * to NetworkServerControlImpl.runServer to start the server.\r
+ *\r
+ * @see ModuleControl#boot\r
+ * @see ModuleControl#stop\r
+ */\r
+public final class DRDAServerStarter implements ModuleControl, Runnable\r
+{\r
+ /**\r
+ * The instance of the NetworkServerControlImpl\r
+ * being used to run the server.\r
+ */\r
+ private Object server;\r
+ \r
+ /**\r
+ * Reflect reference to the method to run the server.\r
+ * NetworkServerControlImpl.blockingStart\r
+ */\r
+ private Method runServerMethod;\r
+ \r
+ /**\r
+ * Reflect reference to the method to directly\r
+ * shutdown the server.\r
+ * NetworkServerControlImpl.directShutdown\r
+ */\r
+ private Method serverShutdownMethod;\r
+\r
+ private Thread serverThread;\r
+ private static final String serverClassName = "org.apache.derby.impl.drda.NetworkServerControlImpl";\r
+ private Class serverClass;\r
+ \r
+ private InetAddress listenAddress =null;\r
+ private int portNumber = -1;\r
+ private PrintWriter consoleWriter = null;\r
+\r
+ /**\r
+ * Try to start the DRDA server. Log an error in error log and continue if it cannot be started.\r
+ */\r
+// public static void start()\r
+// {\r
+\r
+\r
+ public void setStartInfo(InetAddress listenAddress, int portNumber, PrintWriter\r
+ consoleWriter)\r
+ {\r
+ this.listenAddress = listenAddress;\r
+ this.portNumber = portNumber;\r
+\r
+ // wrap the user-set consoleWriter with autoflush to true.\r
+ // this will ensure that messages to console will be \r
+ // written out to the consoleWriter on a println.\r
+ // DERBY-1466\r
+ if (consoleWriter != null)\r
+ this.consoleWriter = new PrintWriter(consoleWriter,true);\r
+ else\r
+ this.consoleWriter = consoleWriter;\r
+ }\r
+\r
+ /**\r
+ * Find the methods to start and shutdown the server.\r
+ * Perfomed through reflection so that the engine\r
+ * code is not dependent on the network server code.\r
+ * @param serverClass\r
+ * @throws NoSuchMethodException \r
+ * @throws SecurityException \r
+ */\r
+ private void findStartStopMethods(final Class serverClass)\r
+ throws SecurityException, NoSuchMethodException\r
+ {\r
+ // Methods are public so no need for privilege blocks.\r
+ runServerMethod = serverClass.getMethod(\r
+ "blockingStart", new Class[] { java.io.PrintWriter.class});\r
+ \r
+ serverShutdownMethod = serverClass.getMethod(\r
+ "directShutdown", null);\r
+ }\r
+\r
+ public void boot(boolean create,\r
+ java.util.Properties properties)\r
+ {\r
+ if( server != null)\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ SanityManager.THROWASSERT( "Network server starter module booted twice.");\r
+ return;\r
+ }\r
+ // Load the server class indirectly so that Derby does not require the network code\r
+ try\r
+ {\r
+ serverClass = Class.forName( serverClassName);\r
+ //Added by Jeff Huang\r
+ //TODO: FIXIT\r
+ }\r
+ catch( ClassNotFoundException cnfe)\r
+ {\r
+ Monitor.logTextMessage( MessageId.CONN_NETWORK_SERVER_CLASS_FIND, serverClassName);\r
+ return;\r
+ }\r
+ catch( java.lang.Error e)\r
+ {\r
+ Monitor.logTextMessage( MessageId.CONN_NETWORK_SERVER_CLASS_LOAD,\r
+ serverClassName,\r
+ e.getMessage());\r
+ return;\r
+ }\r
+ try\r
+ {\r
+ Constructor serverConstructor;\r
+ try\r
+ {\r
+ serverConstructor = (Constructor) AccessController.doPrivileged(\r
+ new PrivilegedExceptionAction() {\r
+ public Object run() throws NoSuchMethodException, SecurityException\r
+ {\r
+ if (listenAddress == null)\r
+ return serverClass.getConstructor(null);\r
+ else\r
+ return\r
+ serverClass.getConstructor(new\r
+ Class[] {java.net.InetAddress.class,\r
+ Integer.TYPE});}\r
+ }\r
+ );\r
+ }\r
+ catch( PrivilegedActionException e)\r
+ {\r
+ Exception e1 = e.getException();\r
+ Monitor.logTextMessage(\r
+ MessageId.CONN_NETWORK_SERVER_START_EXCEPTION, e1.getMessage());\r
+ e.printStackTrace(Monitor.getStream().getPrintWriter());\r
+ return;\r
+\r
+ }\r
+ \r
+ findStartStopMethods(serverClass);\r
+ \r
+ if (listenAddress == null)\r
+ server = serverConstructor.newInstance( null);\r
+ else\r
+ server = serverConstructor.newInstance(new Object[]\r
+ {listenAddress, new Integer(portNumber)});\r
+\r
+ serverThread = Monitor.getMonitor().getDaemonThread( this, "NetworkServerStarter", false);\r
+ serverThread.start();\r
+ }\r
+ catch( Exception e)\r
+ {\r
+ Monitor.logTextMessage( MessageId.CONN_NETWORK_SERVER_START_EXCEPTION, e.getMessage());\r
+ server = null;\r
+ e.printStackTrace(Monitor.getStream().getPrintWriter());\r
+ }\r
+ } // end of boot\r
+\r
+ public void run()\r
+ {\r
+ try\r
+ {\r
+ runServerMethod.invoke( server,\r
+ new Object[] {consoleWriter });\r
+ }\r
+ catch( InvocationTargetException ite)\r
+ {\r
+ Monitor.logTextMessage(\r
+ MessageId.CONN_NETWORK_SERVER_START_EXCEPTION, ite.getTargetException().getMessage());\r
+ ite.printStackTrace(Monitor.getStream().getPrintWriter());\r
+\r
+ server = null;\r
+ }\r
+ catch( Exception e)\r
+ {\r
+ Monitor.logTextMessage( MessageId.CONN_NETWORK_SERVER_START_EXCEPTION, e.getMessage());\r
+ server = null;\r
+ e.printStackTrace(Monitor.getStream().getPrintWriter());\r
+ }\r
+ }\r
+ \r
+ public void stop()\r
+ {\r
+ try {\r
+ if( serverThread != null && serverThread.isAlive())\r
+ {\r
+ serverShutdownMethod.invoke( server,\r
+ null);\r
+ AccessController.doPrivileged(\r
+ new PrivilegedAction() {\r
+ public Object run() {\r
+ serverThread.interrupt();\r
+ return null;\r
+ }\r
+ }); \r
+ serverThread = null;\r
+ }\r
+ \r
+ }\r
+ catch( InvocationTargetException ite)\r
+ {\r
+ Monitor.logTextMessage(\r
+ MessageId.CONN_NETWORK_SERVER_SHUTDOWN_EXCEPTION, ite.getTargetException().getMessage());\r
+ ite.printStackTrace(Monitor.getStream().getPrintWriter());\r
+ \r
+ }\r
+ catch( Exception e)\r
+ {\r
+ Monitor.logTextMessage( MessageId.CONN_NETWORK_SERVER_SHUTDOWN_EXCEPTION, e.getMessage());\r
+ e.printStackTrace(Monitor.getStream().getPrintWriter());\r
+ }\r
+ \r
+ serverThread = null;\r
+ server = null;\r
+ serverClass = null;\r
+ listenAddress = null;\r
+ portNumber = -1;\r
+ consoleWriter = null;\r
+ \r
+ } // end of stop\r
+}\r