001: /*
002:
003: Derby - Class org.apache.derbyTesting.functionTests.tests.derbynet.dataSourcePermissions_net
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.tests.derbynet;
023:
024: import org.apache.derby.jdbc.EmbeddedDataSource;
025: import org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource;
026: import org.apache.derby.jdbc.EmbeddedXADataSource;
027:
028: import java.sql.Connection;
029: import java.sql.ResultSet;
030: import java.sql.PreparedStatement;
031: import java.sql.CallableStatement;
032: import java.sql.Statement;
033: import java.sql.SQLException;
034: import java.sql.DriverManager;
035:
036: import javax.sql.DataSource;
037: import javax.sql.XADataSource;
038: import javax.sql.PooledConnection;
039: import javax.sql.XAConnection;
040: import javax.sql.ConnectionPoolDataSource;
041: import javax.transaction.xa.XAResource;
042: import javax.transaction.xa.XAException;
043: import javax.transaction.xa.Xid;
044: import javax.sql.ConnectionEventListener;
045: import javax.sql.ConnectionEvent;
046: import org.apache.derby.tools.JDBCDisplayUtil;
047: import org.apache.derby.tools.ij;
048: import org.apache.derby.drda.NetworkServerControl;
049: import org.apache.derbyTesting.functionTests.util.TestUtil;
050: import java.io.*;
051: import java.net.InetAddress;
052: import java.util.Hashtable;
053: import java.util.Properties;
054:
055: import javax.naming.*;
056: import javax.naming.directory.*;
057:
058: import java.lang.reflect.*;
059:
060: public class dataSourcePermissions_net
061: extends
062: org.apache.derbyTesting.functionTests.tests.jdbcapi.dataSourcePermissions {
063:
064: private static int NETWORKSERVER_PORT;
065: private static String hostName;
066: private static NetworkServerControl networkServer = null;
067:
068: private static FileOutputStream serverOutput;
069:
070: public static void main(String[] args) throws Exception {
071:
072: hostName = TestUtil.getHostName();
073: if (hostName.equals("localhost"))
074: NETWORKSERVER_PORT = 20000;
075: else
076: NETWORKSERVER_PORT = 1527;
077:
078: // Load harness properties.
079: ij.getPropertyArg(args);
080:
081: // "runTest()" is going to try to connect to the database through
082: // the server at port NETWORKSERVER_PORT. Thus, we have to
083: // start the server on that port before calling runTest.
084: // Except when we are using a remote server, then we assume the port is 1527,
085: // and we assume the server has been started already
086:
087: try {
088: TestUtil.loadDriver();
089: } catch (Exception e) {
090: e.printStackTrace();
091: }
092:
093: String fileName = System.getProperty("derby.system.home", "")
094: + "serverConsoleOutput.log";
095: serverOutput = new FileOutputStream(fileName);
096:
097: if (hostName.equals("localhost")) {
098: // Start the NetworkServer on another thread
099: networkServer = new NetworkServerControl(InetAddress
100: .getByName("localhost"), NETWORKSERVER_PORT);
101: networkServer.start(new PrintWriter(serverOutput));
102:
103: // Wait for the NetworkServer to start.
104: if (!isServerStarted(networkServer, 60))
105: System.exit(-1);
106: }
107:
108: // Now, go ahead and run the test.
109: try {
110: dataSourcePermissions_net tester = new dataSourcePermissions_net();
111: tester.setProperties();
112: tester.runTest();
113: if (TestUtil.isDerbyNetClientFramework())
114: tester.testClientDataSourceProperties();
115: new dataSourcePermissions_net().cleanUp();
116:
117: } catch (Exception e) {
118: // if we catch an exception of some sort, we need to make sure to
119: // close our streams before returning; otherwise, we can get
120: // hangs in the harness. SO, catching all exceptions here keeps
121: // us from exiting before closing the necessary streams.
122: System.out
123: .println("FAIL - Exiting due to unexpected error: "
124: + e.getMessage());
125: e.printStackTrace();
126: }
127:
128: // Shutdown the server.
129: if (hostName.equals("localhost")) {
130:
131: networkServer.shutdown();
132:
133: // how do we do this with the new api?
134: //networkServer.join();
135: Thread.sleep(5000);
136: }
137: System.out.println("Completed dataSourcePermissions_net");
138:
139: serverOutput.close();
140:
141: }
142:
143: public dataSourcePermissions_net() {
144:
145: }
146:
147: public void setProperties() {
148: // Set required server properties.
149: System.setProperty("database", TestUtil.getJdbcUrlPrefix(
150: hostName, NETWORKSERVER_PORT)
151: + "wombat;create=true");
152: System.setProperty("ij.user", "EDWARD");
153: System.setProperty("ij.password", "noodle");
154:
155: }
156:
157: public String getJDBCUrl(String db, String attrs) {
158: // this method is accessed from subclasses - need to establish hostName
159: String hostName = TestUtil.getHostName();
160: if (hostName.equals("localhost"))
161: NETWORKSERVER_PORT = 20000;
162: else
163: NETWORKSERVER_PORT = 1527;
164: String s = TestUtil.getJdbcUrlPrefix(hostName,
165: NETWORKSERVER_PORT)
166: + db;
167: if (attrs != null)
168: if (TestUtil.isJCCFramework())
169: s = s + ":" + attrs + ";";
170: else
171: s = s + ";" + attrs;
172: return s;
173:
174: }
175:
176: public javax.sql.DataSource getDS(String database, String user,
177: String password) {
178: return getDS(database, user, password, null);
179: }
180:
181: public javax.sql.DataSource getDS(String database, String user,
182: String password, Properties attrs) {
183:
184: if (attrs == null)
185: attrs = new Properties();
186: attrs.setProperty("databaseName", database);
187: if (user != null)
188: attrs.setProperty("user", user);
189: if (password != null)
190: attrs.setProperty("password", password);
191: attrs = addRequiredAttributes(attrs);
192: return TestUtil.getDataSource(attrs);
193: }
194:
195: public javax.sql.ConnectionPoolDataSource getCPDS(String database,
196: String user, String password) {
197: Properties attrs = new Properties();
198: attrs.setProperty("databaseName", database);
199: if (user != null)
200: attrs.setProperty("user", user);
201: if (password != null)
202: attrs.setProperty("password", password);
203: attrs = addRequiredAttributes(attrs);
204: return TestUtil.getConnectionPoolDataSource(attrs);
205: }
206:
207: private Properties addRequiredAttributes(Properties attrs) {
208: // this method is accessed from subclasses - need to establish hostName
209: hostName = TestUtil.getHostName();
210: if (TestUtil.isJCCFramework()) {
211: attrs.setProperty("driverType", "4");
212: /**
213: * As per the fix of derby-410 servername should
214: * default to localhost, but for jcc it's still needed
215: */
216: attrs.setProperty("serverName", hostName);
217: }
218: /**
219: * For a remote host of course it's also needed
220: */
221: if (!hostName.equals("localhost")) {
222: attrs.setProperty("serverName", hostName);
223: attrs.setProperty("portNumber", "1527");
224: } else
225: attrs.setProperty("portNumber", "20000");
226: //attrs.setProperty("retrieveMessagesFromServerOnGetMessage","true");
227: return attrs;
228: }
229:
230: public boolean supportsUnicodeNames() {
231: return false;
232: }
233:
234: public boolean supportsPooling() {
235: return true;
236: }
237:
238: public boolean supportsXA() {
239: return false;
240: }
241:
242: public void start() {
243: }
244:
245: public void shutdown() {
246:
247: try {
248:
249: DriverManager.getConnection(TestUtil.getJdbcUrlPrefix(
250: hostName, NETWORKSERVER_PORT)
251: + "wombat;shutdown=true", "EDWARD", "noodle");
252:
253: System.out.println("FAIL - Shutdown returned connection");
254:
255: } catch (SQLException sqle) {
256:
257: System.out
258: .println("EXPECTED SHUTDOWN " + sqle.getMessage());
259: }
260:
261: }
262:
263: protected static boolean isServerStarted(
264: NetworkServerControl server, int ntries) {
265: for (int i = 1; i <= ntries; i++) {
266: try {
267: Thread.sleep(500);
268: server.ping();
269: return true;
270: } catch (Exception e) {
271: if (i == ntries)
272: return false;
273: }
274: }
275: return false;
276: }
277:
278: /**
279: * Test Client specific dataSource Properties
280: *
281: */
282: public void testClientDataSourceProperties() throws SQLException {
283: testRetrieveMessageText();
284: testDescription();
285:
286: //Added for Derby-409
287: testConnectionAttributes();
288:
289: //Added for Derby-406
290: allUsernameAndPasswordTests();
291: }
292:
293: /**
294: * Test property retrieveMessageText to retrieve message text
295: * Property defaults to true for Network Client but can be set to
296: * false to disable the procedure call.
297: */
298: public void testRetrieveMessageText() throws SQLException {
299: Connection conn;
300: String retrieveMessageTextProperty = "retrieveMessageText";
301: Class[] argType = { Boolean.TYPE };
302: String methodName = TestUtil
303: .getSetterName(retrieveMessageTextProperty);
304: Object[] args;
305:
306: try {
307: DataSource ds = getDS("wombat", "EDWARD", "noodle");
308: Method sh = ds.getClass().getMethod(methodName, argType);
309: args = new Boolean[] { new Boolean(false) };
310: sh.invoke(ds, args);
311: conn = ds.getConnection();
312: checkMessageText(conn, "false");
313: conn.close();
314:
315: // now try with retrieveMessageText = true
316: ds = getDS("wombat", "EDWARD", "noodle");
317: args = new Boolean[] { new Boolean(true) };
318: sh.invoke(ds, args);
319: conn = ds.getConnection();
320: checkMessageText(conn, "true");
321: conn.close();
322: } catch (Exception e) {
323: System.out
324: .println("FAIL: testRetrieveMessageText() Unexpected Exception "
325: + e.getMessage());
326: e.printStackTrace();
327: }
328: }
329:
330: /**
331: * Test description property
332: */
333: public void testDescription() throws SQLException {
334: String descriptionProperty = "description";
335: Class[] argType = { String.class };
336: String setterMethodName = TestUtil
337: .getSetterName(descriptionProperty);
338: String getterMethodName = TestUtil
339: .getGetterName(descriptionProperty);
340:
341: Object[] args;
342:
343: try {
344: String setDescription = "Everything you ever wanted to know about this datasource";
345: DataSource ds = getDS("wombat", "EDWARD", "noodle");
346: // Set the description
347: Method sh = ds.getClass().getMethod(setterMethodName,
348: argType);
349: args = new Object[] { new String(setDescription) };
350: sh.invoke(ds, args);
351: // Now check it
352: sh = ds.getClass().getMethod(getterMethodName, null);
353: String getDescription = (String) sh.invoke(ds, null);
354: if (!setDescription.equals(getDescription))
355: throw new Exception("getDescription() "
356: + getDescription
357: + " does not match setDescription() ");
358: } catch (Exception e) {
359: System.out
360: .println("FAIL: testDescription() Unexpected Exception "
361: + e.getMessage());
362: e.printStackTrace();
363: }
364: }
365:
366: public void checkMessageText(Connection conn,
367: String retrieveMessageTextValue) throws SQLException {
368: System.out
369: .println("** checkMessageText() with retrieveMessageText= "
370: + retrieveMessageTextValue);
371:
372: try {
373: conn.createStatement().executeQuery(
374: "SELECT * FROM APP.NOTTHERE");
375: } catch (SQLException e) {
376: String expectedSQLState = "42X05";
377: String sqlState = e.getSQLState();
378: if (sqlState == null || !sqlState.equals(expectedSQLState)) {
379: System.out.println("Incorrect SQLState. Got: "
380: + sqlState + " should be: " + expectedSQLState);
381: throw e;
382: }
383: if (retrieveMessageTextValue.equals("true")) {
384: if (e.getMessage().indexOf("does not exist") != -1)
385: System.out
386: .println("PASS: Message Text retrieved properly");
387: else {
388: System.out
389: .println("FAIL: Message text was not retrieved");
390: throw e;
391: }
392: } else
393: // retrieveMessageTextValue is false
394: if (e.getMessage().indexOf("does not exist") == -1) {
395: System.out.println("PASS: Message text not retrieved");
396: } else {
397: System.out
398: .println("FAIL: Message Text should not have been retrieved");
399: throw e;
400: }
401:
402: }
403: }
404:
405: /**
406: * Added for Derby-409
407: *
408: * Designed to test combinations of attributes to insure that
409: * no exceptions are thrown.
410: */
411: public void testConnectionAttributes() {
412: try {
413: System.out.println("Begin connection attribute tests");
414: testDataSourceConnection("One attribute test: ", "EDWARD",
415: "noodle", "create=true");
416: testDataSourceConnection("Another different attribute: ",
417: "EDWARD", "noodle", "tracefile=trace.out");
418: testDataSourceConnection("Two Attributes: ", "EDWARD",
419: "noodle", "create=true;tracefile=trace.out");
420: System.out.println("End connection attribute tests");
421: } catch (Exception e) {
422: System.out
423: .println("FAIL: testSetConnectionAttributes() Unexpected Exception "
424: + e.getMessage());
425: e.printStackTrace(System.out);
426: }
427: }
428:
429: /**
430: * Added for Derby-406
431: *
432: * Tests DataSource with a number of different username/password
433: * input combinations.
434: */
435: public void allUsernameAndPasswordTests() {
436:
437: try {
438: System.out.println("Begin username and password tests");
439:
440: testDataSourceConnection("Normal test: ", "EDWARD",
441: "noodle", null);
442:
443: testDataSourceConnection(
444: "No username or password, only attributes test: ",
445: null, null, "user=EDWARD;password=noodle");
446:
447: testDataSourceConnection(
448: "Bogus username and password, good attributes test: ",
449: "Whatis", "theMatrix?",
450: "user=EDWARD;password=noodle");
451:
452: testDataSourceConnection(
453: "Username, password attribute test: ", "EDWARD",
454: null, "password=noodle");
455:
456: testDataSourceConnection(
457: "Password, username attribute test: ", null,
458: "noodle", "user=EDWARD");
459:
460: System.out.println("Turning off authentication");
461: DataSource ds = getDS("wombat", "EDWARD", "noodle");
462: Connection conn = ds.getConnection();
463: CallableStatement cs = conn
464: .prepareCall("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
465: cs.setString(1, "derby.connection.requireAuthentication");
466: cs.setString(2, "false");
467: cs.execute();
468: cs.close();
469: cs = null;
470: conn.close();
471: //We have to shut down before the changes will take effect.
472: shutdown();
473: start();
474:
475: testDataSourceConnection("Username, no password test: ",
476: "EDWARD", null, null);
477:
478: testDataSourceConnection("No username, password test: ",
479: null, "noodle", null);
480:
481: testDataSourceConnection("No username, no password test: ",
482: null, null, null);
483:
484: System.out.println("Turning on authentication");
485: ds = getDS("wombat", "EDWARD", "noodle");
486: conn = ds.getConnection();
487: cs = conn
488: .prepareCall("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?, ?)");
489: cs.setString(1, "derby.connection.requireAuthentication");
490: cs.setString(2, "true");
491: cs.execute();
492: cs.close();
493: cs = null;
494: conn.close();
495: shutdown();
496: start();
497:
498: System.out.println("End username and password tests");
499: } catch (Exception e) {
500: System.out
501: .println("FAIL: allUsernameAndPasswordTests. Unexpected Exception "
502: + e.getMessage());
503: e.printStackTrace(System.out);
504: }
505: }
506:
507: /**
508: * A method that attempts to retrieve the connection via a datasource
509: * with the given user, password and connection attributes.
510: *
511: * @param testType A string description of the type of test
512: * @param username The user
513: * @param password The Password
514: * @param attributes A string to be added to a properties object. A
515: * null string means null Property object.
516: * @throws SQLException
517: */
518: public void testDataSourceConnection(String testType,
519: String username, String password, String attributes)
520: throws SQLException {
521: try {
522: System.out.print(testType);
523: Properties props = null;
524: if (attributes != null) {
525: props = new Properties();
526: props.put("ConnectionAttributes", attributes);
527: }
528: DataSource ds = getDS("wombat", username, password, props);
529: Connection conn = ds.getConnection();
530: conn.close();
531: System.out.println("PASS.");
532: } catch (SQLException e) {
533: System.out.println("FAIL. Unexpected Exception: ");
534: e.printStackTrace(System.out);
535: }
536: }
537: }
|