001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.harness.NetServer
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.functionTests.harness;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileOutputStream;
027: import java.util.Locale;
028: import java.util.Properties;
029: import java.util.Vector;
030: import java.util.Hashtable;
031: import java.lang.reflect.Method;
032: import java.lang.reflect.Constructor;
033: import java.net.ConnectException;
034: import java.net.Socket;
035: import org.apache.derbyTesting.functionTests.util.TestUtil;
036:
037: public class NetServer {
038:
039: File homeDir; // The server directory (usually the test directory)
040: String jvmName = "jdk13";
041: String clPath;
042: String javaCmd;
043: String jvmflags;
044: String framework;
045: static String hostName;
046:
047: Object[] frameworkInfo;
048: int port;
049: Process pr;
050: BackgroundStreamSaver outSaver, errSaver;
051: FileOutputStream fosOut, fosErr;
052: private String java;
053: private boolean startServer; // whether test will start it's own server
054:
055: // Variables for test connection
056: Object networkServer; // Server needs to be created with reflection
057: Method pingMethod;
058:
059: private static String NETWORK_SERVER_CLASS_NAME = "org.apache.derby.drda.NetworkServerControl";
060:
061: public static Hashtable m;
062: public static int PREFIX_POS = 0;
063: public static int SUFFIX_POS = 1;
064: public static int DRIVER_POS = 2;
065: public static int PORT_POS = 3;
066: public static int START_CMD_POS = 4;
067: public static int STOP_CMD1_POS = 5;
068: public static int STOP_CMD2_POS = 6;
069:
070: static {
071: hostName = TestUtil.getHostName();
072: m = new Hashtable();
073: // Hashtable is keyed on framework name and has
074: // an array of the framework prefix, suffix, driver, port and
075: // String[] command arguments to start the server
076: // String[] Command arguments to stop the server
077: String url = "jdbc:derby:net://" + hostName + ":1527/";
078: m.put("DerbyNet", new Object[] {
079: url, //prefix
080: "", // suffix
081: "com.ibm.db2.jcc.DB2Driver", //driver
082: "1527", // port
083: new String[] { NETWORK_SERVER_CLASS_NAME, //start
084: "start" },
085: new String[] { NETWORK_SERVER_CLASS_NAME, //shutdown
086: "shutdown" }, null }); //shutdown2
087:
088: url = "jdbc:derby://" + hostName + ":1527/";
089: m.put("DerbyNetClient", new Object[] {
090: url, //prefix
091: "", // suffix
092: "org.apache.derby.jdbc.ClientDriver", //driver
093: "1527", // port
094: new String[] { NETWORK_SERVER_CLASS_NAME, //start
095: "start" },
096: new String[] { NETWORK_SERVER_CLASS_NAME, //shutdown
097: "shutdown" }, null }); //shutdown2
098:
099: url = "jdbc:db2://" + hostName + ":50000/";
100: m.put("DB2jcc", new Object[] { url, //prefix
101: "", //suffix
102: "com.ibm.db2.jcc.DB2Driver", //driver
103: "50000", //port
104: null, //start
105: null, null });
106:
107: m.put("DB2app",
108: new Object[] { "jdbc:db2:", "",
109: "COM.ibm.db2.jdbc.app.DB2Driver", "0", null,
110: null, null });
111: }
112:
113: public NetServer(File homeDir, String jvmName, String clPath,
114: String javaCmd, String jvmflags, String framework,
115: boolean startServer) throws Exception {
116: this .homeDir = homeDir;
117: this .jvmName = jvmName;
118: this .clPath = clPath;
119: this .javaCmd = javaCmd;
120: this .jvmflags = jvmflags;
121: this .framework = framework;
122: frameworkInfo = (Object[]) m.get(framework);
123:
124: this .port = Integer.parseInt((String) frameworkInfo[PORT_POS]);
125: this .startServer = startServer;
126: // System.out.println("framework: " + this.framework + "port: " + this.port);
127:
128: }
129:
130: public void start() throws Exception {
131: if (!startServer) {
132: System.out
133: .println("startServer = false. Bypass server startup");
134: return;
135: }
136:
137: // Create the Server directory under the server dir
138: (new File(homeDir, framework + "Server")).mkdir();
139: String[] startcmd = (String[]) frameworkInfo[START_CMD_POS];
140: // if we are just connecting to DB2 we return
141: if (startcmd == null)
142: return;
143:
144: // Build the command to run the WL server
145: String homeDirName = homeDir.getCanonicalPath();
146: jvm jvm = null; // to quiet the compiler
147: jvm = jvm.getJvm(jvmName);
148: if (jvmName.equals("jview"))
149: jvm.setJavaCmd("jview");
150: else if (javaCmd != null)
151: jvm.setJavaCmd(javaCmd);
152:
153: Vector jvmProps = new Vector();
154: if ((clPath != null) && (clPath.length() > 0))
155: jvm.setClasspath(clPath);
156:
157: if ((jvmflags != null) && (jvmflags.length() > 0)) {
158: jvm.setFlags(jvmflags);
159: // Set no flags by default (DERBY-1614).
160: // The jvmflags property can be used to set any kind of JVM option.
161: }
162:
163: jvmProps.addElement("derby.system.home=" + homeDirName);
164: jvm.setD(jvmProps);
165: jvm.setSecurityProps();
166: // For some platforms (like Mac) the process exec command
167: // must be a string array; so we build this with a Vector
168: // first because some strings (paths) could have spaces
169: Vector vCmd = jvm.getCommandLine();
170: for (int i = 0; i < startcmd.length; i++)
171: vCmd.addElement(startcmd[i]);
172:
173: String serverCmd[] = new String[vCmd.size()];
174: for (int i = 0; i < vCmd.size(); i++) {
175: serverCmd[i] = (String) vCmd.elementAt(i);
176: System.out.print(serverCmd[i] + " ");
177: }
178: System.out.println("");
179: // Start a process to run the Server
180: pr = Runtime.getRuntime().exec(serverCmd);
181:
182: // Write the out and err files to the server directory also
183: File out = new File(homeDir, framework + ".out");
184: fosOut = new FileOutputStream(out);
185: outSaver = new BackgroundStreamSaver(pr.getInputStream(),
186: fosOut);
187: File err = new File(homeDir, framework + ".err");
188: fosErr = new FileOutputStream(err);
189: errSaver = new BackgroundStreamSaver(pr.getErrorStream(),
190: fosErr);
191:
192: for (int i = 0; i <= 120; i++) {
193: // No need to wait for DB2
194: if (isDB2Connection(framework))
195: break;
196:
197: try {
198: if (isNetworkServerConnection(framework)) {
199: // adding a testconnection check
200: // so that the test does not start before the server is up
201: if (testNetworkServerConnection())
202: break;
203: } else {
204: Socket s = new Socket(hostName, this .port);
205: s.close();
206: break;
207: }
208:
209: } catch (Exception e) {
210: // bail out if something has been written to stderr
211: if (err.length() > 0) {
212: break;
213: } else {
214: // it's probably unnecessary to sleep, since the
215: // connection request generally takes a long time when
216: // the listener hasn't started yet, but what the heck ...
217: Thread.sleep(1000);
218: // but here we iterate, and after 120 seconds, we stop
219: // waiting to connect.
220: }
221:
222: }
223: }
224: }
225:
226: public boolean testNetworkServerConnection() throws Exception {
227: if (!startServer) {
228: System.out
229: .println("startServer = false. Bypass server check");
230: return true;
231: }
232:
233: Object[] testConnectionArg = null;
234: if (networkServer == null) {
235: Constructor serverConstructor;
236: Class serverClass = Class
237: .forName(NETWORK_SERVER_CLASS_NAME);
238: serverConstructor = serverClass.getConstructor(null);
239: networkServer = serverConstructor.newInstance(null);
240: pingMethod = networkServer.getClass().getMethod("ping",
241: null);
242: }
243: pingMethod.invoke(networkServer, null);
244: return true;
245: }
246:
247: // stop the Server
248: public void stop() throws Exception {
249: if (!startServer) {
250: return;
251: }
252:
253: System.out.println("Attempt to shutdown framework: "
254: + framework);
255: jvm jvm = null; // to quiet the compiler
256: jvm = jvm.getJvm(jvmName);
257: Vector jvmCmd = jvm.getCommandLine();
258:
259: Vector connV = new Vector();
260: for (int i = 0; i < jvmCmd.size(); i++) {
261: connV.addElement((String) jvmCmd.elementAt(i));
262: }
263:
264: String[] stopcmd1 = (String[]) frameworkInfo[STOP_CMD1_POS];
265: if (stopcmd1 == null)
266: return;
267:
268: for (int i = 0; i < stopcmd1.length; i++)
269: connV.addElement(stopcmd1[i]);
270:
271: String[] connCmd = new String[connV.size()];
272: for (int i = 0; i < connV.size(); i++) {
273: connCmd[i] = (String) connV.elementAt(i);
274: }
275:
276: Vector stopV = new Vector();
277: for (int i = 0; i < jvmCmd.size(); i++) {
278: stopV.addElement((String) jvmCmd.elementAt(i));
279: }
280: Process prconn = Runtime.getRuntime().exec(connCmd);
281: // Give the server sixty seconds to shutdown.
282: TimedProcess tp = new TimedProcess(prconn);
283: tp.waitFor(60);
284:
285: String[] stopcmd2 = (String[]) frameworkInfo[STOP_CMD2_POS];
286: if (stopcmd2 != null) {
287: for (int i = 0; i < stopcmd2.length; i++)
288: stopV.addElement(stopcmd2[i]);
289:
290: String[] stopCmd = new String[stopV.size()];
291: for (int i = 0; i < stopV.size(); i++) {
292: stopCmd[i] = (String) stopV.elementAt(i);
293: }
294:
295: Process prstop = Runtime.getRuntime().exec(stopCmd);
296: prstop.waitFor();
297: }
298:
299: // Try a TimedProcess as Phil did for the WLServer
300: tp = new TimedProcess(pr);
301: // In case the Server didn't shut down, force it to ...
302: tp.waitFor(60);
303:
304: // Finish and close the redirected out and err files
305: outSaver.finish();
306: errSaver.finish();
307: }
308:
309: public void printFramworkInfo(String framework) {
310: System.out.println("PREFIX = " + frameworkInfo[PREFIX_POS]);
311: System.out.println("SUFFIX = " + frameworkInfo[SUFFIX_POS]);
312: System.out.println("DRIVER = " + frameworkInfo[DRIVER_POS]);
313: System.out.println("PORT = " + frameworkInfo[PORT_POS]);
314:
315: for (int index = START_CMD_POS; index <= STOP_CMD2_POS; index++) {
316: String cmdString = "";
317: String[] cmdArray = (String[]) frameworkInfo[index];
318: for (int i = 0; i < cmdArray.length; i++) {
319: cmdString += " " + cmdArray[i];
320: }
321: if (index == START_CMD_POS)
322: System.out.println("START_CMD = " + cmdString);
323: else
324: System.out.println("STOP_CMD = " + cmdString);
325:
326: }
327: }
328:
329: // Get Framework Info
330: public static String getURLPrefix(String fm) {
331: Object[] info = (Object[]) m.get(fm);
332: return (String) info[PREFIX_POS];
333: }
334:
335: public static String getURLSuffix(String fm) {
336: Object[] info = (Object[]) m.get(fm);
337: return (String) info[SUFFIX_POS];
338: }
339:
340: public static String getDriverName(String fm) {
341: Object[] info = (Object[]) m.get(fm);
342: if (info != null)
343: return (String) info[DRIVER_POS];
344: else
345: return null;
346: }
347:
348: public static boolean isDB2Connection(String fm) {
349: return (fm.toUpperCase(Locale.ENGLISH).equals("DB2APP") || fm
350: .toUpperCase(Locale.ENGLISH).equals("DB2JCC"));
351:
352: }
353:
354: public static boolean isNetworkServerConnection(String fm) {
355: return (fm.toUpperCase(Locale.ENGLISH).startsWith("DERBYNET"));
356: }
357:
358: public static boolean isClientConnection(String fm) {
359: return (fm.toUpperCase(Locale.ENGLISH).startsWith("DERBYNET") || fm
360: .toUpperCase(Locale.ENGLISH).equals("DB2JCC"));
361: }
362:
363: public static boolean isJCCConnection(String fm) {
364: return fm.toUpperCase(Locale.ENGLISH).equals("DB2JCC")
365: || fm.toUpperCase(Locale.ENGLISH).equals("DERBYNET");
366: }
367:
368: /**
369: * @param fm framework name. database url from properties file
370: * @return
371: * altered url (i.e. attributes stripped for DB2 and DerbyNet)
372: */
373:
374: public static String alterURL(String fm, String url) {
375: String urlPrefix = "jdbc:derby:";
376: String newURLPrefix = getURLPrefix(fm);
377: String newURLSuffix = getURLSuffix(fm);
378:
379: // If we don't have a URL prefix for this framework
380: // just return
381: if (newURLPrefix == null)
382: return url;
383:
384: if (newURLSuffix == null)
385: newURLSuffix = "";
386:
387: if (url.equals(urlPrefix)) // Replace embedded
388: return newURLPrefix;
389:
390: // If this is a DB2 connection we need to strip
391: // the connection attributes
392: int attrOffset = url.indexOf(';');
393: if (NetServer.isDB2Connection(fm) && attrOffset != -1)
394: url = url.substring(0, attrOffset);
395:
396: if (url.startsWith(urlPrefix)) {
397: // replace jdbc:derby: with our url:
398: url = newURLPrefix + url.substring(urlPrefix.length())
399: + newURLSuffix;
400: } else {
401: if (!(url.startsWith("jdbc:"))) {
402: url = newURLPrefix + url + newURLSuffix;
403: }
404: }
405: return url;
406: }
407:
408: }
|