db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From myrn...@apache.org
Subject svn commit: r627297 [3/4] - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi: DataSourceTest.java J2EEDataSourceTest.java _Suite.java
Date Wed, 13 Feb 2008 07:44:00 GMT
Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java?rev=627297&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/J2EEDataSourceTest.java Tue Feb 12 23:43:59 2008
@@ -0,0 +1,3753 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.jdbcapi.J2EEDataSourceTest
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.functionTests.tests.jdbcapi;
+
+import java.io.File;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Savepoint;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import org.apache.derbyTesting.functionTests.tests.jdbcapi.AssertEventCatcher;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.ConnectionEventListener;
+import javax.sql.ConnectionPoolDataSource;
+import javax.sql.DataSource;
+import javax.sql.PooledConnection;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derby.jdbc.ClientConnectionPoolDataSource;
+import org.apache.derby.jdbc.ClientXADataSource;
+import org.apache.derby.jdbc.EmbeddedSimpleDataSource;
+import org.apache.derbyTesting.functionTests.util.SecurityCheck;
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.J2EEDataSource;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.JDBCClient;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+/**
+ * Test the ConnectionPoolDataSource and XADataSource implementations of Derby.
+ * DataSource functionality common to DataSources including what is
+ * supported with JSR169 is tested in DataSourceTest. 
+ * 
+ * Performs SecurityCheck analysis on the JDBC objects returned.
+ * This is because this test returns to the client a number of
+ * different implementations of Connection, Statement etc.
+ * 
+ * @see org.apache.derbyTesting.functionTests.util.SecurityCheck
+ *
+ */
+public class J2EEDataSourceTest extends BaseJDBCTestCase {
+
+    private static final String dbName = 
+        TestConfiguration.getCurrent().getDefaultDatabaseName();
+    
+    /**
+     * A hashtable of opened connections.  This is used when checking to
+     * make sure connection strings are unique; we need to make sure all
+     * the connections are closed when we are done, so they are stored
+     * in this hashtable
+     */
+    protected static Hashtable conns = new Hashtable();
+    
+    /** The expected format of a connection string. In English:
+     * "<classname>@<hashcode> (XID=<xid>), (SESSION = <sessionid>),
+     *  (DATABASE=<dbname>), (DRDAID = <drdaid>)"
+     */
+    private static final String CONNSTRING_FORMAT = 
+        "\\S+@\\-?[0-9]+.* \\(XID = .*\\), \\(SESSIONID = [0-9]+\\), " +
+        "\\(DATABASE = [A-Za-z]+\\), \\(DRDAID = .*\\) "; 
+    
+    
+    /**
+     * Hang onto the SecurityCheck class while running the
+     * tests so that it is not garbage collected during the
+     * test and lose the information it has collected,
+     * in case it should get printed out.
+     */
+    private final Object nogc = SecurityCheck.class;
+    
+    public J2EEDataSourceTest(String name) {
+        super(name);
+    }
+    
+    /**
+     * Return a suite of tests that are run with a lower lock timeout.
+     *
+     * @param postfix suite name postfix
+     * @return A suite of tests being run with a lower lock timeout.
+     */
+    private static Test getTimeoutSuite(String postfix) {
+        TestSuite suite = new TestSuite("Lower lock timeout" + postfix);
+        suite.addTest(new J2EEDataSourceTest("timeoutTestDerby1144PooledDS"));
+        suite.addTest(new J2EEDataSourceTest("timeoutTestDerby1144XADS"));
+        // Reduce the timeout threshold to make the tests run faster.
+        return DatabasePropertyTestSetup.setLockTimeouts(suite, 3, 5);
+    }
+    
+    /**
+     * Return a suite of tests that are run with both client and embedded
+     * 
+     * @param postfix suite name postfix
+     * @return A suite of tests to be run with client and/or embedded
+     */
+    private static Test baseSuite(String postfix) {
+        TestSuite suite = new TestSuite("ClientAndEmbedded" + postfix);
+        suite.addTest(new J2EEDataSourceTest("testGlobalLocalInterleaf"));
+        suite.addTest(new J2EEDataSourceTest("testSetIsolationWithStatement"));
+        suite.addTest(new J2EEDataSourceTest("testJira95xads"));
+        suite.addTest(new J2EEDataSourceTest("testBadConnectionAttributeSyntax"));
+        suite.addTest(new J2EEDataSourceTest("testDescriptionProperty"));
+        suite.addTest(new J2EEDataSourceTest("testConnectionErrorEvent"));
+        suite.addTest(new J2EEDataSourceTest("testReadOnlyToWritableTran"));
+        suite.addTest(new J2EEDataSourceTest("testAutoCommitOnXAResourceStart"));
+        suite.addTest(new J2EEDataSourceTest("testAllDataSources"));
+        suite.addTest(new J2EEDataSourceTest("testClosedCPDSConnection"));
+        suite.addTest(new J2EEDataSourceTest("testClosedXADSConnection"));
+        suite.addTest(new J2EEDataSourceTest("testSetSchemaInXAConnection"));
+        return suite;
+    }
+
+    /**
+     * Return a suite of tests that are run with client only
+     * 
+     * @return A suite of tests being run with client only
+     */
+    private static Test getClientSuite() {
+        TestSuite suite = new TestSuite("Client/Server");
+        suite.addTest(new J2EEDataSourceTest("testClientDSConnectionAttributes"));
+        suite.addTest(new J2EEDataSourceTest(
+                "testClientTraceFileDSConnectionAttribute"));
+        suite.addTest(new J2EEDataSourceTest(
+                "testClientMessageTextConnectionAttribute"));
+        return suite;
+    }
+    
+    /**
+     * Return a suite of tests that are run with embedded only
+     * 
+     * @param postfix suite name postfix
+     * @return A suite of tests being run with embedded only
+     */
+    private static Test getEmbeddedSuite(String postfix) {
+        TestSuite suite = new TestSuite("Embedded" + postfix);
+        suite.addTest(new J2EEDataSourceTest("testDSRequestAuthentication"));
+        // Due to a bug following cannot be run for client - DERBY-3379
+        // To run this fixture with client, add to getClientSuite(),
+        // when DERBY-3379 is fixed, remove from here (and client) and
+        // move to baseSuite.
+        suite.addTest(new J2EEDataSourceTest("testPooledReuseOnClose"));
+        // when DERBY-2498 gets fixed, move this one to baseSuite
+        suite.addTest(new J2EEDataSourceTest("testJira95pds"));
+        // Following cannot run with client because of DERBY-2533; it hangs
+        // when fixed, this can be moved to baseSuite.
+        suite.addTest(new J2EEDataSourceTest("testReuseAcrossGlobalLocal"));
+        suite.addTest(new J2EEDataSourceTest("testXAHoldability"));
+        return suite;
+    }
+    
+    public static Test suite() {
+        if (JDBC.vmSupportsJSR169())
+        {
+            // test uses unsupported classes like DriverManager, XADataSource,
+            // ConnectionPoolDataSource, ConnectionEvenListenere, as well as
+            // unsupported methods, like Connection.setTypeMap()...
+            TestSuite suite = 
+                new TestSuite("J2EEDatasourceTest cannot run with JSR169");
+            return suite;
+        }
+        else
+        {
+            TestSuite suite = new TestSuite("J2EEDataSourceTest suite");
+            // Add tests that will run with both embedded
+            suite.addTest(baseSuite(":embedded"));
+            //  and network server/client
+            suite.addTest(TestConfiguration.clientServerDecorator(
+                    baseSuite(":client")));
+            // Add the tests that only run with client
+            suite.addTest(TestConfiguration.clientServerDecorator(
+                    getClientSuite()));
+            // Add the tests that only run with embedded
+            suite.addTest(getEmbeddedSuite("embedded"));
+            // Add the tests relying on getting timeouts.
+            suite.addTest(getTimeoutSuite(":embedded"));
+            suite.addTest(TestConfiguration.clientServerDecorator(
+                    getTimeoutSuite(":client")));
+            // wrap all in CleanDatabaseTestSetup that creates all database
+            // objects any fixture might need.
+            // Note that not all fixtures need (all of) these.
+            return new CleanDatabaseTestSetup(suite) {
+                /**
+                 * Create and populate database objects
+                 * 
+                 * @see org.apache.derbyTesting.junit.CleanDatabaseTestSetup#decorateSQL(java.sql.Statement)
+                 */
+                protected void decorateSQL(Statement s) throws SQLException {
+                    s.executeUpdate("create table autocommitxastart(i int)");
+                    s.executeUpdate("insert into autocommitxastart values 1,2,3,4,5");
+                    s.executeUpdate("create schema SCHEMA_Patricio");
+                    s.executeUpdate("create table " +
+                    "SCHEMA_Patricio.Patricio (id VARCHAR(255), value INTEGER)");
+                    s.executeUpdate("create table intTable(i int)");
+                    s.executeUpdate("create table hold_30 " +
+                    "(id int not null primary key, b char(30))");
+                    s.executeUpdate(
+                            "create procedure checkConn2(in dsname varchar(20)) " +
+                            "parameter style java language java modifies SQL DATA " +
+                            "external name " +
+                            "'org.apache.derbyTesting.functionTests.tests.jdbcapi.J2EEDataSourceTest." +
+                            getNestedMethodName() +
+                    "'");
+                }
+            };
+        }
+    }
+    
+    public void tearDown() throws Exception {
+        // attempt to get rid of any left-over trace files
+        AccessController.doPrivileged(new java.security.PrivilegedAction() {
+            public Object run() {
+                for (int i=0 ; i < 6 ; i++)
+                {   
+                    String traceFileName = "trace" + (i+1) + ".out";
+                    File traceFile = new File(traceFileName);
+                    if (traceFile.exists())
+                    {
+                        // if it exists, attempt to get rid of it
+                        traceFile.delete();
+                    }
+                } 
+                return null;
+            }
+        });
+        super.tearDown();
+    }
+
+    /* comment out. leaving in, just in case it's ever relevant.
+     * when uncommented, this will run when network server tests are
+     * started, and then reflect the results of the embedded checks.
+    // perform security analysis of the public api for the embedded engine
+    public void testDataSourceAPI() throws SQLException, ClassNotFoundException
+    {
+        SecurityCheck.report();
+    }
+     */
+    
+    /**
+     * Test case for DERBY-3172
+     * When the Derby engine is shutdown or Network Server is brought down, any
+     * api on JDBC Connection object should generate a Connection error event.
+     */
+    public void testConnectionErrorEvent() throws SQLException, Exception
+    {
+        AssertEventCatcher aes12 = new AssertEventCatcher(12);
+        
+        ConnectionPoolDataSource ds = J2EEDataSource.getConnectionPoolDataSource();
+
+        PooledConnection pc = ds.getPooledConnection();
+        //Add a connection event listener to ConnectionPoolDataSource
+        pc.addConnectionEventListener(aes12);
+        Connection conn = pc.getConnection();
+        
+        dropTable(conn, "TAB1");
+
+        //No event should have been generated at this point
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertFalse(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        //Shutdown the Derby engine or Network Server depending on what 
+        //mode we are running in.
+        if (usingEmbedded())
+        {
+        	getTestConfiguration().shutdownDatabase();
+        } else
+        {
+        	getTestConfiguration().stopNetworkServer();
+        }
+        //Now try to use various apis on the JDBC Connection object created 
+        //before shutdown and they all should generate connection error event.
+        try {
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+        } catch (SQLException e) {
+            //The first call on JDBC Connection object after Network Server
+            //shutdown will generate a communication error and that's why we
+            //are checking for SQL State 08006 rather than No current connection
+            //SQL State 08003. In embedded mode, we will get SQL State 08003
+        	//meaning No current connection
+            if (usingEmbedded())
+                assertSQLState("08003", e);
+            else
+                assertSQLState("08006", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)", 1);
+        } catch (SQLException e) {
+            assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+        	int[] columnIndexes = {1};
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)", 
+            		columnIndexes);
+        } catch (SQLException e) {
+            assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+        	String[] columnNames = {"col1"};
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)", 
+            		columnNames);
+        } catch (SQLException e) {
+            assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+            		ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareStatement("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+            		ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+            		ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.createStatement();
+        } catch (SQLException e) {
+            assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, 
+            		ResultSet.CONCUR_READ_ONLY,
+            		ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, 
+            ResultSet.CONCUR_READ_ONLY);
+        } catch (SQLException e) {
+            assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+            		ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.prepareCall("CREATE TABLE TAB1(COL1 INT NOT NULL)",
+            		ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
+            		ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.nativeSQL("CREATE TABLE TAB1(COL1 INT NOT NULL)");
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getAutoCommit();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setAutoCommit(false);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getHoldability();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setHoldability(1);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.commit();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.rollback();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setSavepoint();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setSavepoint("savept1");
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.rollback((Savepoint)null);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.releaseSavepoint((Savepoint)null);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getTransactionIsolation();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getWarnings();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.clearWarnings();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getMetaData();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.isReadOnly();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setReadOnly(true);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setCatalog(null);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getCatalog();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.getTypeMap();
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        try {
+            conn.setTypeMap(null);
+        } catch (SQLException e) {
+                assertSQLState("08003", e);
+        }
+        assertFalse(aes12.didConnectionClosedEventHappen());
+        assertTrue(aes12.didConnectionErrorEventHappen());
+        aes12.resetState();
+        if (usingEmbedded())
+        {
+            Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
+        }else
+        {
+        	getTestConfiguration().startNetworkServer();
+        }
+
+        // Get a new connection to the database
+        conn = getConnection();
+        conn.close();
+    }
+    
+    /**
+     * Test that a PooledConnection can be reused and closed
+     * (separately) during the close event raised by the
+     * closing of its logical connection.
+     * DERBY-2142.
+     * @throws SQLException 
+     *
+     */
+    public void testPooledReuseOnClose() throws SQLException
+    {
+    	// PooledConnection from a ConnectionPoolDataSource
+    	ConnectionPoolDataSource cpds =
+    		J2EEDataSource.getConnectionPoolDataSource();
+    	subtestPooledReuseOnClose(cpds.getPooledConnection());
+        subtestPooledCloseOnClose(cpds.getPooledConnection());
+        // DERBY-3401 - removing a callback during a close causes problems.
+        //subtestPooledRemoveListenerOnClose(cpds.getPooledConnection());
+
+    	// PooledConnection from an XDataSource
+    	XADataSource xads = J2EEDataSource.getXADataSource();
+    	subtestPooledReuseOnClose(xads.getXAConnection());
+        subtestPooledCloseOnClose(xads.getXAConnection());
+        // DERBY-3401 - removing a callback during a close causes problems.
+        //subtestPooledRemoveListenerOnClose(xads.getXAConnection());
+    }
+    
+    /**
+     * Tests that a pooled connection can successfully be reused
+     * (a new connection obtained from it) during the processing
+     * of its close event by its listener.
+     * Sections 11.2 & 12.5 of JDBC 4 specification indicate that the
+     * connection can be returned to the pool when the
+     * ConnectionEventListener.connectionClosed() is called.
+     */
+    private void subtestPooledReuseOnClose(final PooledConnection pc) throws SQLException
+    {
+    	final Connection[] newConn = new Connection[1];
+    	pc.addConnectionEventListener(new ConnectionEventListener() {
+
+    		/**
+    		 * Mimic a pool handler that returns the PooledConnection
+    		 * to the pool and then reallocates it to a new logical connection.
+    		 */
+			public void connectionClosed(ConnectionEvent event) {
+				PooledConnection pce = (PooledConnection) event.getSource();
+				assertSame(pc, pce);
+				try {
+					// open a new logical connection and pass
+					// back to the fixture.
+					newConn[0] = pce.getConnection();
+				} catch (SQLException e) {
+					// Need to catch the exception here because
+					// we cannot throw an exception through
+					// the api method.
+					fail(e.getMessage());
+				}
+			}
+
+			public void connectionErrorOccurred(ConnectionEvent event) {
+			}
+    		
+    	});
+    	
+    	// Open a connection then close it to trigger the
+    	// fetching of a new connection in the callback.
+    	Connection c1 = pc.getConnection();
+    	c1.close();
+    	
+    	// Fetch the connection created in the close callback
+    	Connection c2 = newConn[0];
+    	assertNotNull(c2);
+    	
+    	// Ensure the connection is useable, this hit a NPE before DERBY-2142
+    	// was fixed (for embedded).
+    	c2.createStatement().close();
+    	
+    	pc.close();
+    }
+    
+    /**
+     * Tests that a pooled connection can successfully be closed
+     * during the processing of its close event by its listener.
+     */
+    private void subtestPooledCloseOnClose(final PooledConnection pc) throws SQLException
+    {
+        pc.addConnectionEventListener(new ConnectionEventListener() {
+
+            /**
+             * Mimic a pool handler that closes the PooledConnection
+             * (say it no longer needs it, pool size being reduced)
+             */
+            public void connectionClosed(ConnectionEvent event) {
+                PooledConnection pce = (PooledConnection) event.getSource();
+                assertSame(pc, pce);
+                try {
+                    pce.close();
+                } catch (SQLException e) {
+                    // Need to catch the exception here because
+                    // we cannot throw an exception through
+                    // the api method.
+                    fail(e.getMessage());
+                }
+            }
+
+            public void connectionErrorOccurred(ConnectionEvent event) {
+            }
+            
+        });
+        
+        // Open and close a connection to invoke the logic above
+        // through the callback
+        pc.getConnection().close();
+                
+        // The callback closed the actual pooled connection
+        // so subsequent requests to get a logical connection
+        // should fail.
+        try {
+            pc.getConnection();
+            fail("PooledConnection should be closed");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+    }
+    
+    /**
+     * Tests that a listener of a pooled connection can successfully
+     * remove itself during the processing of its close event by its listener.
+     */
+    private void subtestPooledRemoveListenerOnClose(final PooledConnection pc) throws SQLException
+    {
+        
+        final int[] count1 = new int[1];
+        pc.addConnectionEventListener(new ConnectionEventListener() {
+
+            /**
+             * Mimic a pool handler that removes the listener during
+             * a logical close.
+             */
+            public void connectionClosed(ConnectionEvent event) {
+                PooledConnection pce = (PooledConnection) event.getSource();
+                assertSame(pc, pce);
+                count1[0]++;
+                pce.removeConnectionEventListener(this);
+            }
+
+            public void connectionErrorOccurred(ConnectionEvent event) {
+            }
+            
+        });
+        
+        // and have another listener to ensure removing one leaves
+        // the other working and intact.
+        final int[] count2 = new int[1];
+        pc.addConnectionEventListener(new ConnectionEventListener() {
+
+            /**
+             * Mimic a pool handler that closes the PooledConnection
+             * (say it no longer needs it, pool size being reduced)
+             */
+            public void connectionClosed(ConnectionEvent event) {             
+                PooledConnection pce = (PooledConnection) event.getSource();
+                assertSame(pc, pce);
+                count2[0]++;
+            }
+
+            public void connectionErrorOccurred(ConnectionEvent event) {
+            }
+            
+        });        
+        // no callback yet
+        assertEquals(0, count1[0]);
+        assertEquals(0, count2[0]);
+        
+        // Open and close a connection to invoke the logic above
+        // through the callback
+        pc.getConnection().close();
+        
+        // one callback for each
+        assertEquals(1, count1[0]);
+        assertEquals(1, count2[0]);
+              
+        // the callback (count1) that was removed is not called on the
+        // second close but the second callback (count2) is called.
+        pc.getConnection().close();
+        assertEquals(1, count1[0]);
+        assertEquals(2, count2[0]);
+        
+        pc.close();
+    }
+
+    
+    public void testAllDataSources() throws SQLException, Exception
+    {
+        Connection dmc = getConnection();
+        CallableStatement cs = dmc.prepareCall("call checkConn2(?)");
+        cs.setString(1,"Nested");
+        try {
+            cs.execute();
+        } catch (SQLException sqle) {
+            assertSQLState("40XC0", sqle);
+        }
+        cs.setString(1,"Nested2");
+        cs.execute();
+        
+        String EmptyMapValue=null;
+        // Note: currently, not supported
+        String NullMapValue=null;
+        String MapMapValue=null;
+        if (usingEmbedded())
+        {
+            EmptyMapValue="OK"; NullMapValue="XJ081"; MapMapValue="0A000";
+        }
+        else if (usingDerbyNetClient())
+        {
+            EmptyMapValue="0A000"; NullMapValue="0A000"; MapMapValue="0A000";
+        }
+        Object[] expectedValues = {
+            new Integer(ResultSet.HOLD_CURSORS_OVER_COMMIT), "XJ010",
+            new Integer(2), new Boolean(true), new Boolean(false), 
+            EmptyMapValue, NullMapValue, MapMapValue};
+
+        assertConnectionOK(expectedValues, "DriverManager ", dmc);
+    
+        if (usingEmbedded())
+            assertTenConnectionsUnique();
+
+        DataSource dscs = JDBCDataSource.getDataSource();
+        JDBCDataSource.setBeanProperty(dscs, "createDatabase", "false");
+        if (usingEmbedded()) 
+                assertToString(dscs);
+
+        DataSource ds = dscs;
+        assertConnectionOK(expectedValues, "DataSource", ds.getConnection());
+        
+        DataSource dssimple = null;
+        // simple datasource is only supported with embedded
+        if (usingEmbedded())
+        {
+            EmbeddedSimpleDataSource realdssimple = 
+                new EmbeddedSimpleDataSource();
+            realdssimple.setDatabaseName(dbName);
+            ds = realdssimple;
+            dssimple = (DataSource)realdssimple;
+            assertConnectionOK(
+                expectedValues, "SimpleDataSource", ds.getConnection());
+        }
+            
+        ConnectionPoolDataSource dsp = 
+            J2EEDataSource.getConnectionPoolDataSource();      
+        
+        if (usingEmbedded()) 
+            assertToString(dsp);
+
+        PooledConnection pc = dsp.getPooledConnection();
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(
+                pc, "javax.sql.PooledConnection");
+        }
+        AssertEventCatcher aes1 = new AssertEventCatcher(1);
+        pc.addConnectionEventListener(aes1);
+
+        // DERBY-2531
+        // with Network Server / DerbyNetClient, the assertConnectionOK check
+        // returns a different connection object...
+        assertConnectionOK(
+            expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes1.didConnectionClosedEventHappen());
+        assertFalse(aes1.didConnectionErrorEventHappen());
+        aes1.resetState();
+        assertConnectionOK(
+            expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes1.didConnectionClosedEventHappen());
+        assertFalse(aes1.didConnectionErrorEventHappen());
+        aes1.resetState();
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        JDBCDataSource.setBeanProperty(dsx, "createDatabase", "false");
+
+        if (usingEmbedded())
+            assertToString(dsx);
+
+        // shutdown db and check all's still ok thereafter
+        TestConfiguration.getCurrent().shutdownDatabase();
+
+        dmc = getConnection();
+        cs = dmc.prepareCall("call checkConn2(?)");
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(
+                cs, "java.sql.CallableStatement");
+        }
+        cs.setString(1,"Nested");
+        try {
+            cs.execute();
+        } catch (SQLException sqle) {
+            assertSQLState("40XC0", sqle);
+        }
+        cs.setString(1, "Nested2");
+        cs.execute();
+
+        XAConnection xac = dsx.getXAConnection();
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+            SecurityCheck.assertSourceSecurity(xac, "javax.sql.XAConnection");
+        }
+        AssertEventCatcher aes3 = new AssertEventCatcher(3);
+        xac.addConnectionEventListener(aes3);
+        assertConnectionOK(
+            expectedValues, "XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes3.didConnectionClosedEventHappen());
+        assertFalse(aes3.didConnectionErrorEventHappen());
+        aes3.resetState();
+                       
+        pc = dsp.getPooledConnection();
+        AssertEventCatcher aes2 = new AssertEventCatcher(2);
+        pc.addConnectionEventListener(aes2);
+        assertConnectionOK(
+            expectedValues, "ConnectionPoolDataSource", pc.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes2.didConnectionClosedEventHappen());
+        assertFalse(aes2.didConnectionErrorEventHappen());
+        aes2.resetState();
+
+        // test "local" XAConnections
+        xac = dsx.getXAConnection();
+        AssertEventCatcher aes4 = new AssertEventCatcher(4);
+        xac.addConnectionEventListener(aes4);
+        assertConnectionOK(
+            expectedValues, "XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes4.didConnectionClosedEventHappen());
+        assertFalse(aes4.didConnectionErrorEventHappen());
+        aes4.resetState();
+        assertConnectionOK(
+            expectedValues, "XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes4.didConnectionClosedEventHappen());
+        assertFalse(aes4.didConnectionErrorEventHappen());
+        aes4.resetState();
+        xac.close();
+
+        // test "global" XAConnections
+        xac = dsx.getXAConnection();
+        AssertEventCatcher aes5 = new AssertEventCatcher(5);
+        xac.addConnectionEventListener(aes5);
+        XAResource xar = xac.getXAResource();
+        // checks currently only implemented for embedded 
+        if (usingEmbedded())
+        {
+           SecurityCheck.assertSourceSecurity(
+                xar, "javax.transaction.xa.XAResource");
+        }
+        Xid xid = new cdsXid(1, (byte) 35, (byte) 47);
+        xar.start(xid, XAResource.TMNOFLAGS);
+        Connection xacc = xac.getConnection();
+        xacc.close();
+        expectedValues[0] = new Integer(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        if (usingEmbedded())
+            expectedValues[1] = "XJ058";
+        expectedValues[3] = new Boolean(false);
+        assertConnectionOK(
+            expectedValues, "Global XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+        assertConnectionOK(
+            expectedValues, "Global XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+
+        xar.end(xid, XAResource.TMSUCCESS);
+
+        expectedValues[0] = new Integer(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+        expectedValues[3] = new Boolean(true);
+        assertConnectionOK(expectedValues, 
+            "Switch to local XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+        assertConnectionOK(expectedValues, 
+            "Switch to local XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+
+        Connection backtoGlobal = xac.getConnection();
+
+        xar.start(xid, XAResource.TMJOIN);
+        expectedValues[0] = new Integer(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        expectedValues[3] = new Boolean(false);
+        assertConnectionOK(expectedValues, 
+            "Switch to global XADataSource", backtoGlobal);
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+        assertConnectionOK(expectedValues, 
+            "Switch to global XADataSource", xac.getConnection());
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+        xar.end(xid, XAResource.TMSUCCESS);
+        xar.commit(xid, true);
+
+        xac.close();
+    }
+    
+    public void testClosedCPDSConnection() throws SQLException, Exception {
+        // verify that outstanding updates from a closed connection, obtained
+        // from a ConnectionPoolDataSource, are not committed, but rolled back.
+        ConnectionPoolDataSource dsp = 
+            J2EEDataSource.getConnectionPoolDataSource();       
+        PooledConnection pc = dsp.getPooledConnection();
+        Connection c1 = pc.getConnection();
+        Statement s = c1.createStatement();
+        // start by deleting all rows from intTable
+        s.executeUpdate("delete from intTable");
+        c1.setAutoCommit(false);
+
+        // this update should get rolled back later
+        s.executeUpdate("insert into intTable values(1)");
+        // this should automatically close the original connection
+        c1 = pc.getConnection();
+
+        ResultSet rs = 
+            c1.createStatement().executeQuery("select count(*) from intTable");
+        rs.next();
+        assertEquals(0, rs.getInt(1));
+        c1.close();
+        
+        // check connection objects are closed once connection is closed
+        try {
+            rs.next();
+            fail("ResultSet is open for a closed connection obtained from PooledConnection");
+        } catch (SQLException sqle) {
+            // 08003 - No current connection; XCL16 - ResultSet not open
+            if (usingEmbedded())
+                assertSQLState("08003", sqle);
+            else if (usingDerbyNetClient())
+                assertSQLState("XCL16", sqle);
+        }
+
+        try {
+            s.executeUpdate("update intTable set i = 1");
+            fail("Statement is open for a closed connection " +
+                "obtained from PooledConnection");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+
+        pc.close();
+        pc = null;
+        PoolReset("ConnectionPoolDataSource", dsp.getPooledConnection());
+        s.close();
+        rs.close();
+        c1.close();
+    }
+
+    public void testClosedXADSConnection() throws SQLException, Exception {
+        // verify that outstanding updates from a closed connection, obtained
+        // from an XADataSource, are not committed, but rolled back.
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac = dsx.getXAConnection();
+        Connection c1 = xac.getConnection();
+        Statement s = c1.createStatement();
+
+        c1.setAutoCommit(false);
+
+        // this update should be rolled back
+        s.executeUpdate("insert into intTable values(2)");
+        
+        c1 = xac.getConnection();
+
+        ResultSet rs = c1.createStatement().executeQuery(
+           "select count(*) from intTable");
+        rs.next();
+
+        assertEquals(0, rs.getInt(1));
+
+        rs.close();
+        c1.close();
+        xac.close();
+        xac = null;
+
+        PoolReset("XADataSource", dsx.getXAConnection());
+    }
+
+    public void testGlobalLocalInterleaf() throws SQLException, XAException {    
+        // now some explicit tests for how connection state behaves
+        // when switching between global transactions and local
+        // and setting connection state.
+        // some of this may be tested elsewhere too.
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac = dsx.getXAConnection();
+        AssertEventCatcher aes6 = new AssertEventCatcher(6);
+        xac.addConnectionEventListener(aes6);
+        XAResource xar = xac.getXAResource();
+        Xid xid = new cdsXid(1, (byte) 93, (byte) 103);
+
+        // series 1 - Single connection object
+        Connection cs1 = xac.getConnection();
+        // initial local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+        xar.start(xid, XAResource.TMNOFLAGS);
+        // initial X1
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            false, false, cs1);
+        cs1.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+        cs1.setReadOnly(true);
+        setHoldability(cs1, false); // close cursors
+        // modified X1
+        boolean ReadOnly = false;
+        // see DERBY-911, ReadOnly state different for Embedded/DerbyNetClient
+        if (usingEmbedded())
+            ReadOnly = true;
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        xar.end(xid, XAResource.TMSUCCESS);
+        // the underlying local transaction/connection must pick up the
+        // state of the Connection handle cs1
+        // modified local:
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            true, ReadOnly, cs1);
+        
+        cs1.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+        cs1.setReadOnly(false);
+        setHoldability(cs1, false); // close cursors
+
+        // reset local
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+
+        // now re-join the transaction, should pick up the read-only
+        // and isolation level from the transaction,
+        // holdability remains that of this handle.
+        xar.start(xid, XAResource.TMJOIN);
+        // re-join X1
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        xar.end(xid, XAResource.TMSUCCESS);
+
+        // back to local - should be the same as the reset local
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+        
+        // test suspend/resume
+        // now re-join the transaction (X1) for the second time, should pick
+        // up the read-only and isolation level from the transaction,
+        // holdability remains that of this handle.
+        xar.start(xid, XAResource.TMJOIN);
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        
+        xar.end(xid, XAResource.TMSUSPEND);
+        // local after suspend
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+        
+        xar.start(xid, XAResource.TMRESUME);
+        // resume X1
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        
+        xar.end(xid, XAResource.TMSUCCESS);
+        // back to local (second time)
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+        
+        cs1.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+        cs1.setReadOnly(true);
+        setHoldability(cs1, true); // hold
+        //Confirm - no connection closed event & connection error event
+        assertFalse(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+        cs1.close();
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+        
+        cs1 = xac.getConnection();
+        // new handle - local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, cs1);
+        cs1.close();
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+        
+        xar.start(xid, XAResource.TMJOIN);
+        cs1 = xac.getConnection();
+        // re-join with new handle X1
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        cs1.close();
+        xar.end(xid, XAResource.TMSUCCESS);
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+
+        // now get a connection (attached to a local)
+        // attach to the global and commit it.
+        // state should be that of the local after the commit.
+        cs1 = xac.getConnection();
+        cs1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+        // pre-X1 commit - local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, cs1);
+        xar.start(xid, XAResource.TMJOIN);
+        // pre-X1 commit - X1
+        assertConnectionState(
+            ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, ReadOnly, cs1);
+        xar.end(xid, XAResource.TMSUCCESS);
+        // post-X1 end - local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, cs1);
+        xar.commit(xid, true);
+        // post-X1 commit - local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, cs1);
+        //Confirm - no connection closed event & connection error event
+        assertFalse(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+        cs1.close();
+        //Check if got connection closed event but not connection error event
+        assertTrue(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+    }
+    
+    // really part of testGlobalLocalInterLeaf:
+    /**
+     * @throws SQLException
+     * @throws XAException
+     */
+    public void testSetIsolationWithStatement() 
+    throws SQLException, XAException {
+        // DERBY-421 Setting isolation level with SQL was not getting 
+        // handled correctly 
+        // Some more isolation testing using SQL and JDBC api
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac = dsx.getXAConnection();
+        AssertEventCatcher aes6 = new AssertEventCatcher(6);
+        xac.addConnectionEventListener(aes6);
+        XAResource xar = xac.getXAResource();
+        Connection conn = xac.getConnection();
+        Statement s = conn.createStatement();
+        // initial local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_COMMITTED,
+            true, false, conn);
+
+        // Issue setTransactionIsolation in local transaction
+        conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+        // setTransactionIsolation in local
+        assertConnectionState(
+            ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            true, false, conn);
+
+        Xid xid;
+        //Issue SQL to change isolation in local transaction
+        s.executeUpdate("set current isolation = RR");
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_SERIALIZABLE,
+            true, false, conn);
+
+        xid = new cdsXid(1, (byte) 35, (byte) 47);
+        xar.start(xid, XAResource.TMNOFLAGS);
+        // 1st global (new)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT,
+            Connection.TRANSACTION_SERIALIZABLE,
+            false, false, conn);
+        xar.end(xid, XAResource.TMSUCCESS);
+
+        // local
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT,
+            Connection.TRANSACTION_SERIALIZABLE,
+            true, false, conn);
+        //Issue SQL to change isolation in local transaction
+        s.executeUpdate("set current isolation = RS");
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, conn);
+
+        // DERBY-1325 - Isolation level of local connection does not get reset after ending 
+        // a global transaction that was joined/resumed if the isolation level was changed 
+        // using SQL 
+        xar.start(xid, XAResource.TMJOIN);
+        // 1st global(existing)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_SERIALIZABLE,
+            false, false, conn);
+        xar.end(xid, XAResource.TMSUCCESS);
+        // local
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, conn);
+        // DERBY-1325 end test 
+
+        Xid xid2 = new cdsXid(1, (byte) 93, (byte) 103);
+        xar.start(xid2, XAResource.TMNOFLAGS);
+        // 2nd global (new)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            false, false, conn);
+        xar.end(xid2, XAResource.TMSUCCESS);
+
+        xar.start(xid, XAResource.TMJOIN);
+        // 1st global (existing)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_SERIALIZABLE,
+            false, false, conn);
+        xar.end(xid, XAResource.TMSUCCESS);
+
+        //local 
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            true, false, conn);
+
+        xar.start(xid, XAResource.TMJOIN);
+        
+        // 1st global (existing)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_SERIALIZABLE,
+            false, false, conn);
+        // Issue SQL to change isolation in 1st global transaction
+        s.executeUpdate("set current isolation = UR");
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            false, false, conn);
+        xar.end(xid, XAResource.TMSUCCESS);
+
+        // local
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            true, false, conn);
+
+        xar.start(xid2, XAResource.TMJOIN);
+        // 2nd global (existing)
+        assertConnectionState(ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+            Connection.TRANSACTION_REPEATABLE_READ,
+            false, false, conn);
+        xar.end(xid2, XAResource.TMSUCCESS);
+        xar.rollback(xid2);
+        // (After 2nd global rollback ) local
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            true, false, conn);
+
+        xar.rollback(xid);
+        // (After 1st global rollback) local
+        assertConnectionState(ResultSet.HOLD_CURSORS_OVER_COMMIT, 
+            Connection.TRANSACTION_READ_UNCOMMITTED,
+            true, false, conn);
+        //Confirm - no connection closed event & connection error event
+        assertFalse(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+    }
+
+    // This test includes some short-hand descriptions of the test cases
+    // left in for reference to the original non-junit test
+    public void testReuseAcrossGlobalLocal() throws SQLException, XAException {
+
+        // DERBY-2533 -
+        // network server cannot run this test - it hits a protocol error
+        // on tearDown. Embedded requires a database shutdown
+        if (usingDerbyNetClient())
+            return;
+        
+        int[] onetwothree = {1,2,3};
+        int[] three = {3};
+        int[] pspc = {1, 4}; // expected parameter count for prepared statements
+        int[] cspc = {2, 12, 12}; // for callable statements
+        
+        // statics for testReuseAcrossGlobalLocal
+        int[] StatementExpectedValues = {
+            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+            ResultSet.FETCH_REVERSE, 444, 713, 19, 
+            ResultSet.HOLD_CURSORS_OVER_COMMIT};
+            //ResultSet.CLOSE_CURSORS_AT_COMMIT};
+        int[] PreparedStatementExpectedValues = { 
+            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+            ResultSet.FETCH_REVERSE, 888, 317, 91,
+            ResultSet.HOLD_CURSORS_OVER_COMMIT};
+        int[] CallableStatementExpectedValues = { 
+            ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY,
+            ResultSet.FETCH_REVERSE, 999, 137, 85,
+            ResultSet.HOLD_CURSORS_OVER_COMMIT};
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac = dsx.getXAConnection();
+        AssertEventCatcher aes6 = new AssertEventCatcher(6);
+        xac.addConnectionEventListener(aes6);
+        XAResource xar = xac.getXAResource();
+        Xid xid = new cdsXid(1, (byte) 103, (byte) 119);
+
+        // now check re-use of *Statement objects across local/global 
+        // connections.
+        Connection cs1 = xac.getConnection();
+
+        // ensure read locks stay around until end-of transaction
+        cs1.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+        cs1.setAutoCommit(false);
+        assertLocks(null, cs1);
+
+        Statement sru1 = cs1.createStatement();
+        sru1.setCursorName("SN1");
+        sru1.executeUpdate("insert into intTable values 1,2,3");
+        Statement sruBatch = cs1.createStatement();
+        sruBatch.setCursorName("sruBatch");
+        Statement sruState = createFloatStatementForStateChecking(
+            StatementExpectedValues, cs1);
+        PreparedStatement psruState = createFloatStatementForStateChecking(
+            new int[] {1, 4}, PreparedStatementExpectedValues, cs1, 
+            "select i from intTable where i = ?");
+        CallableStatement csruState = createFloatCallForStateChecking(
+            new int[] {2, 12, 12}, CallableStatementExpectedValues, cs1, 
+            "CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(?,?)");
+        PreparedStatement psParams = 
+            cs1.prepareStatement("select * from intTable where i > ?");
+        psParams.setCursorName("params");
+        psParams.setInt(1, 2);
+        // Params-local-1
+        resultSetQuery("params", three, psParams.executeQuery());
+
+        sruBatch.addBatch("insert into intTable values 4");
+        // sru1-local-1
+        queryOnStatement("SN1", onetwothree, cs1, sru1);
+        cs1.commit(); // need to commit to switch to an global connection;
+
+        // simple case - underlying connection is re-used for global.
+        xar.start(xid, XAResource.TMNOFLAGS); 
+        // Expecting downgrade because global transaction sru1-global-2 is 
+        // using a statement with holdability true
+        // sru1-global-2
+        queryOnStatement("SN1", onetwothree, cs1, sru1);
+        sruBatch.addBatch("insert into intTable values 5");
+        Statement sru2 = cs1.createStatement();
+        sru2.setCursorName("OAK2");
+        //sru2-global-3
+        queryOnStatement("OAK2", onetwothree, cs1, sru2);
+        // Expecting downgrade because global transaction sru1-global-4 is
+        // using a statement with holdability true
+        // sru1-global-4
+        queryOnStatement("SN1", onetwothree, cs1, sru1);
+        // Global statement
+        StatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+        PreparedStatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+        CallableStatementExpectedValues[6] = ResultSet.CLOSE_CURSORS_AT_COMMIT;
+        assertStatementState(null, StatementExpectedValues ,sruState);
+        // Global PreparedStatement
+        assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+        // Global CallableStatement
+        assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+        // Params-global-1
+        resultSetQuery("params", three, psParams.executeQuery());
+
+        xar.end(xid, XAResource.TMSUCCESS);
+        // now a new underlying connection is created
+        // sru1-local-5
+        queryOnStatement("SN1", onetwothree, cs1, sru1);
+        // sru2-local-6
+        queryOnStatement("OAK2", onetwothree, cs1, sru2);
+        sruBatch.addBatch("insert into intTable values 6,7");
+        Statement sru3 = cs1.createStatement();
+        sru3.setCursorName("SF3");
+        // sru3-local-7
+        queryOnStatement("SF3", onetwothree, cs1, sru3);
+        // Two transactions should hold locks (global and the current XA);
+        // LOCAL
+        StatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        PreparedStatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        CallableStatementExpectedValues[6] = ResultSet.HOLD_CURSORS_OVER_COMMIT;
+        assertStatementState(null, StatementExpectedValues, sruState); 
+        assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+        assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+        // Params-local-2
+        resultSetQuery("params", three, psParams.executeQuery());
+        assertLocks(new int[] {14,14}, cs1);
+        cs1.commit();
+        //Confirm - no connection closed event & connection error event
+        assertFalse(aes6.didConnectionClosedEventHappen());
+        assertFalse(aes6.didConnectionErrorEventHappen());
+        aes6.resetState();
+
+        // attach the XA transaction to another connection and see what happens
+        XAConnection xac2 = dsx.getXAConnection();
+        AssertEventCatcher aes5 = new AssertEventCatcher(5);
+        xac2.addConnectionEventListener(aes5);
+        XAResource xar2 = xac2.getXAResource();
+
+        xar2.start(xid, XAResource.TMJOIN);
+        Connection cs2 = xac2.getConnection();
+
+        // these statements were generated by cs1 and thus are still
+        // in a local connection.
+        // sru1-local-8
+        queryOnStatement("SN1", onetwothree, cs1, sru1);
+        // sru2-local-9
+        queryOnStatement("OAK2", onetwothree, cs1, sru2);
+        // sru3-local-10
+        queryOnStatement("SF3", onetwothree, cs1, sru3);
+        sruBatch.addBatch("insert into intTable values 8");
+        // LOCAL 2
+        assertStatementState(null, StatementExpectedValues, sruState);
+        assertStatementState(pspc, PreparedStatementExpectedValues, psruState);
+        assertStatementState(cspc, CallableStatementExpectedValues, csruState);
+
+        assertLocks(new int[] {14, 12}, cs1);
+
+        int[] updateCounts = sruBatch.executeBatch();
+        int[] expectedUpdateCounts = {1, 1, 2, 1};
+        // sruBatch update counts: 
+        for (int i = 0; i < updateCounts.length; i++) {
+            assertEquals(expectedUpdateCounts[i], updateCounts[i]);
+        }
+        // sruBatch
+        queryOnStatement(
+            "sruBatch", new int[] {1,2,3,4,5,6,7,8}, cs1, sruBatch);
+
+        xar2.end(xid, XAResource.TMSUCCESS);
+        //Confirm - no connection closed event & connection error event
+        assertFalse(aes5.didConnectionClosedEventHappen());
+        assertFalse(aes5.didConnectionErrorEventHappen());
+        aes5.resetState();
+        xac2.close();
+
+        // allow close on already closed XAConnection
+        xac2.close();
+        xac2.addConnectionEventListener(null);
+        xac2.removeConnectionEventListener(null);
+
+        // test methods against a closed XAConnection and its resource
+        try {
+            xac2.getXAResource();
+            // DERBY-2532
+            // Network Server does not think this is worth an exception.
+            if (usingEmbedded())
+                fail("expected SQLException on " +
+                    "closed XAConnection.getXAResource");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+        try {
+            xac2.getConnection();
+            fail ("expected SQLException on XAConnection.getConnection");
+        } catch (SQLException sqle) {
+            assertSQLState("08003", sqle);
+        }
+        try {
+            xar2.start(xid, XAResource.TMJOIN);
+            fail ("expected XAException on XAResource.TMJOIN");
+        } catch (XAException xae) {
+            assertXAException("XAResource.start", xae);
+        }
+        try {
+            xar2.end(xid, XAResource.TMJOIN);
+            fail ("expected XAException on XAResource.TMJOIN");
+        } catch (XAException xae) {
+            assertXAException("XAResource.end", xae);
+        }
+        try {
+            xar2.commit(xid, true);
+            fail ("expected XAException on XAResource.commit");
+        } catch (XAException xae) {
+            assertXAException("XAResource.commit", xae);
+        }
+        try {
+            xar2.prepare(xid);
+            fail ("expected XAException on XAResource.prepare");
+        } catch (XAException xae) {
+            assertXAException("XAResource.prepare", xae);
+        }
+        try {
+            xar2.recover(0);
+            fail ("expected XAException on XAResource.recover");
+        } catch (XAException xae) {
+            assertXAException("XAResource.recover", xae);
+        }
+        try {
+            xar2.prepare(xid);
+            fail ("expected XAException on XAResource.prepare");
+        } catch (XAException xae) {
+            assertXAException("XAResource.prepare", xae);
+        }
+        try {
+            xar2.isSameRM(xar2);
+            fail ("expected XAException on XAResource.isSameRM");
+        } catch (XAException xae) {
+            assertXAException("XAResource.isSameRM", xae);
+        }
+        
+        // close everything
+        cs1.rollback();
+        sruState.close();
+        psruState.close();
+        csruState.close();
+        psParams.close();
+        sruBatch.close();
+        sru1.close();
+        sru2.close();
+        sru3.close();
+        cs1.close();
+        cs2.close();
+        xac.removeConnectionEventListener(null);
+        xac.close();
+        xac2.close();
+        
+        // but, still not enough.
+        // what with all the switching between global and local transactions
+        // we still have a lock open on intTable, which will interfere with
+        // our tearDown efforts. Bounce the database.
+        TestConfiguration.getCurrent().shutdownDatabase();
+    }
+    
+    public void testSetSchemaInXAConnection() throws SQLException {
+        // tests that set schema works correctly in an XA connection.
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac3 = dsx.getXAConnection();
+        Connection conn3 = xac3.getConnection();
+        Statement st3 = conn3.createStatement();
+        st3.execute("SET SCHEMA SCHEMA_Patricio");
+        st3.close();
+
+        PreparedStatement ps3 = 
+            conn3.prepareStatement("INSERT INTO Patricio VALUES (?, ?)");
+        ps3.setString(1, "Patricio");
+        ps3.setInt(2, 3);
+        ps3.executeUpdate();
+
+        assertEquals(1, ps3.getUpdateCount());
+        ps3.close();
+        conn3.close();
+        xac3.close();
+    }
+    
+    // test that an xastart in auto commit mode commits the existing work.
+    // test fix of a bug ('beetle 5178') wherein XAresource.start() when 
+    // auto-commit is true did not implictly commit any transaction
+    // Also tests DERBY-1025, same description, but for client.
+    public void testAutoCommitOnXAResourceStart() throws SQLException, XAException {
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac4 = dsx.getXAConnection();
+        Xid xid4a= null;
+
+        // We get an XAID_DUP error from networkserver when attempting
+        // the XAResource.start below if we use the same xid.
+        // Possibly because we're in the same jvm.
+        // When the test is run with clientserverSuite, rather than default,
+        // this wasn't needed, so just create a different id for client
+        if (usingEmbedded())
+            xid4a = new cdsXid(4, (byte) 23, (byte) 76);
+        else if (usingDerbyNetClient())
+            xid4a = new cdsXid(5, (byte) 23, (byte) 76);
+            
+        Connection conn4 = xac4.getConnection();
+        assertTrue(conn4.getAutoCommit());
+
+        Statement s4 = conn4.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
+        ResultSet rs4 = s4.executeQuery("select i from autocommitxastart");
+        rs4.next();
+        assertEquals(1, rs4.getInt(1));
+        rs4.next();
+        assertEquals(2, rs4.getInt(1));
+
+        // XAResource().start should commit the transaction
+        xac4.getXAResource().start(xid4a, XAResource.TMNOFLAGS);
+        xac4.getXAResource().end(xid4a, XAResource.TMSUCCESS);
+
+        try {
+            rs4.next();
+            fail ("expected an exception indicating resultset is closed.");
+        } catch (SQLException sqle) {
+            // Embedded gets 08003. No current connection (DERBY-2620)        	
+        	if (usingDerbyNetClient())
+        		assertSQLState("XCL16",sqle);
+        }
+
+        conn4.setAutoCommit(false);
+        assertFalse(conn4.getAutoCommit());
+
+        rs4 = s4.executeQuery("select i from autocommitxastart");
+        rs4.next();
+        assertEquals(1, rs4.getInt(1));
+        rs4.next();
+        assertEquals(2, rs4.getInt(1));
+        
+         // Get a new xid to begin another transaction. 
+        if (usingEmbedded())
+            xid4a = new cdsXid(4, (byte) 93, (byte) 103);
+        else if (usingDerbyNetClient())
+            xid4a = new cdsXid(5, (byte) 93, (byte) 103);
+
+        try {
+            xac4.getXAResource().start(xid4a, XAResource.TMNOFLAGS);
+        } catch (XAException xae) {
+            if (usingEmbedded())
+                assertNull(xae.getMessage());
+            else if (usingDerbyNetClient())
+            {
+                // This should give XAER_OUTSIDE exception because
+                // the resource manager is busy in the local transaction
+                assertTrue(xae.getMessage().indexOf("XAER_OUTSIDE") >=0 );
+            }
+            assertEquals(-9, xae.errorCode);
+        }
+        
+        rs4.next();
+        assertEquals(3, rs4.getInt(1));
+        rs4.close();
+
+        conn4.rollback();
+        conn4.close();
+        xac4.close();
+    }
+
+    public void testReadOnlyToWritableTran() throws SQLException, Exception
+    {
+        // This fixture will run twice, once with embedded, once with client,
+        // and insert 2 rows in addition to the 5 rows inserted during setup. 
+        // The fixture tests a commit, so before running, try to remove row 
+        // 6 and 7 in case this is the second run of the fixture.
+        Statement s = createStatement();
+        s.executeUpdate("delete from autocommitxastart where i = 6");
+        s.executeUpdate("delete from autocommitxastart where i = 7");
+        
+        // TESTING READ_ONLY TRANSACTION FOLLOWED BY WRITABLE TRANSACTION
+        // Test following sequence of steps
+        // 1)start a read-only global transaction 
+        // 2)finish that read-only transaction
+        // 3)start another global transaction 
+
+        XADataSource dsx = J2EEDataSource.getXADataSource();
+        XAConnection xac5 = dsx.getXAConnection();
+        Xid xid5a = new cdsXid(5, (byte) 119, (byte) 129);
+        Connection conn5 = xac5.getConnection();
+        Statement sru5a = conn5.createStatement();
+        XAResource xar = xac5.getXAResource();
+        xar.start(xid5a, XAResource.TMNOFLAGS);
+        conn5.setReadOnly(true);
+
+        // Read-Only XA transaction;
+        // holdability: (hold, or close cursors over commit) , 
+        // transaction isolation: read-committed, 
+        // auto-commit false, read-only true (with embedded)
+        if (usingEmbedded()) 
+        {
+            assertConnectionState(
+                ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+                Connection.TRANSACTION_READ_COMMITTED,
+                false, true, conn5);
+        }
+        // Note: the original test had no comments about this difference
+        //       between Embedded and DerbyNetClient, this has apparently
+        //       been accepted behavior.
+        else if (usingDerbyNetClient())
+        {
+            assertConnectionState(
+                ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+                Connection.TRANSACTION_READ_COMMITTED,
+                false, false, conn5);
+        }
+        
+        ResultSet rs5 = sru5a.executeQuery(
+            "select count(*) from autocommitxastart");
+        rs5.next();
+        assertEquals(5, rs5.getInt(1));
+        rs5.close();
+        xar.end(xid5a, XAResource.TMSUCCESS);
+        xar.commit(xid5a, true);
+        conn5.close();
+        
+        //now start a new transaction
+        conn5 = xac5.getConnection();
+        sru5a = conn5.createStatement();
+        xar.start(xid5a, XAResource.TMNOFLAGS);
+        
+        // Writeable XA transaction
+        // holdability: (hold, or close cursors over commit) , 
+        // transaction isolation: read-committed, 
+        // auto-commit false, read-only false
+        assertConnectionState(
+                ResultSet.CLOSE_CURSORS_AT_COMMIT, 
+                Connection.TRANSACTION_READ_COMMITTED,
+                false, false, conn5);
+        sru5a.executeUpdate("insert into autocommitxastart values 6,7");
+        rs5 = sru5a.executeQuery("select count(*) from autocommitxastart");
+        rs5.next();
+        assertEquals(7, rs5.getInt(1));
+        xar.end(xid5a, XAResource.TMSUCCESS);
+        xar.commit(xid5a, true);
+        conn5.close();
+        xac5.close();
+        sru5a.close();
+    }
+    
+    // test jira-derby 95 - a NullPointerException was returned when passing
+    // an incorrect database name, should now give error XCY00   
+    // with ConnectionPoolDataSource
+    public void testJira95pds() throws SQLException {
+        try {
+            ConnectionPoolDataSource pds = J2EEDataSource.getConnectionPoolDataSource();
+            JDBCDataSource.setBeanProperty(pds, "databaseName", "jdbc:derby:boo");
+            pds.getPooledConnection();
+            fail ("expected an SQLException!");
+        } catch (SQLException sqle) {
+            // DERBY-2498 - when fixed, remove if
+            if (usingEmbedded())
+                assertSQLState("XCY00", sqle);
+        } catch (Exception e) {
+            // DERBY-2498 - when fixed, remove if
+            if (usingEmbedded())
+                fail ("unexpected exception: " + e.toString());
+        }
+    }
+    
+    // test jira-derby 95 - a NullPointerException was returned when passing
+    // an incorrect database name, should now give error XCY00   
+    // with XADataSource
+    public void testJira95xads() throws SQLException {
+        try {
+            XADataSource dxs = J2EEDataSource.getXADataSource();
+            JDBCDataSource.setBeanProperty(dxs, "databaseName", "jdbc:derby:boo");
+            dxs.getXAConnection().getConnection();
+            fail ("expected an SQLException!");
+        } catch (SQLException sqle) {
+            assertSQLState("XCY00", sqle);
+        } catch (Exception e) {
+            fail ("unexpected exception: " + e.toString());
+        }
+    }
+    
+    // there is a corresponding fixture for datasources in DataSourceTest
+    public void testBadConnectionAttributeSyntax() throws SQLException {
+        
+        // ConnectionPoolDataSource - bad connatr syntax
+        ConnectionPoolDataSource cpds = J2EEDataSource.getConnectionPoolDataSource();
+        JDBCDataSource.setBeanProperty(cpds, "ConnectionAttributes", "bad");
+        try {
+            cpds.getPooledConnection();
+            fail ("should have seen an error");
+        } catch (SQLException e) {
+            assertSQLState("XJ028", e);
+        } 
+
+        // XADataSource - bad connattr syntax");
+        XADataSource xads = J2EEDataSource.getXADataSource();
+        JDBCDataSource.setBeanProperty(xads, "ConnectionAttributes", "bad");
+        try {
+            xads.getXAConnection();
+            fail ("should have seen an error");
+        } catch (SQLException e) {
+            assertSQLState("XJ028", e);
+        } 
+    } // End testBadConnectionAttributeSyntax
+        
+    /**
+     * Check that database name set using setConnectionAttributes is not used
+     * by ClientDataSource. This method tests DERBY-1130.
+     * 
+     * @throws SQLException
+     */
+    public void testClientDSConnectionAttributes() throws SQLException {
+        if (usingEmbedded())
+            return;
+
+        // now with ConnectionPoolDataSource
+        ClientConnectionPoolDataSource cpds = 
+            new ClientConnectionPoolDataSource();
+        // ConnectionPoolDataSource - EMPTY
+        dsConnectionRequests(new String[]  
+            {"08001","08001","08001","08001",
+             "08001","08001","08001","08001","08001"}, 
+            (ConnectionPoolDataSource)cpds);
+
+        // ConnectionPoolDataSource 
+        // - connectionAttributes=databaseName=<valid dbname>
+        cpds.setConnectionAttributes("databaseName=" + dbName);
+        dsConnectionRequests(new String[]  
+            {"08001","08001","08001","08001",
+             "08001","08001","08001","08001","08001"},
+            (ConnectionPoolDataSource)cpds);
+        cpds.setConnectionAttributes(null);
+
+        // Test that database name specified in connection attributes is 
+        // not used
+        // ConnectionPoolDataSource - databaseName=wombat and 
+        // connectionAttributes=databaseName=kangaroo
+        cpds.setConnectionAttributes("databaseName=kangaroo");
+        cpds.setDatabaseName(dbName);
+        dsConnectionRequests(new String[]  
+            {"OK","08001","OK","OK","08001","08001","OK","OK","OK"},
+            (ConnectionPoolDataSource)cpds);
+        cpds.setConnectionAttributes(null);
+        cpds.setDatabaseName(null);
+
+        // now with XADataSource
+        ClientXADataSource xads = new ClientXADataSource();
+        // XADataSource - EMPTY
+        dsConnectionRequests(new String[]  
+            {"08001","08001","08001","08001",
+             "08001","08001","08001","08001","08001"}, 
+            (XADataSource) xads);
+
+        // XADataSource - connectionAttributes=databaseName=<valid dbname>
+        xads.setConnectionAttributes("databaseName=wombat");
+        dsConnectionRequests(new String[]  
+            {"08001","08001","08001","08001",
+             "08001","08001","08001","08001","08001"},
+            (XADataSource) xads);
+        xads.setConnectionAttributes(null);
+
+        // Test that database name specified in connection attributes is not used
+        // XADataSource - databaseName=wombat and 
+        // connectionAttributes=databaseName=kangaroo
+        xads.setConnectionAttributes("databaseName=kangaroo");
+        xads.setDatabaseName("wombat");
+        dsConnectionRequests(new String[]  
+            {"OK","08001","OK","OK","08001","08001","OK","OK","OK"},
+            (XADataSource) xads);
+        xads.setConnectionAttributes(null);
+        xads.setDatabaseName(null);
+    } // End testClientDSConnectionAttributes
+            
+    // Following test is similar to testClientDSConnectionAttributes, but
+    // for embedded datasources.
+    // This subtest does not run for network server, it uses
+    // setAttributesAsPassword, which isn't supported for client datasources.
+    //
+    // Note that DataSourceTest has some more basic testing of
+    // an empty DataSource in a fixture with similar name - however
+    // that fixture does not test setAttributesAsPassword
+    public void testDSRequestAuthentication() throws SQLException {
+
+//        if (usingDerbyNetClient())
+//            return;
+        
+        JDBCClient dsclient = getTestConfiguration().getJDBCClient();
+        String dsName = dsclient.getDataSourceClassName();
+        DataSource ds = null;
+        try {
+            ds = (javax.sql.DataSource) Class.forName(dsName).newInstance();
+        } catch (Exception e) {
+            fail("unable to complete test because unable to create new instance of datasource");
+        }
+
+        // DataSource - attributesAsPassword=true");
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+
+        // DataSource - attributesAsPassword=true, 
+        // connectionAttributes=databaseName=kangaroo");
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+        JDBCDataSource.setBeanProperty(ds, "connectionAttributes", "databaseName=kangaroo");
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+        JDBCDataSource.clearStringBeanProperty(ds, "connectionAttributes");
+
+        // Enable Authentication;
+
+        setDatabaseProperty("derby.user.fred", "wilma");
+        setDatabaseProperty("derby.user.APP", "APP");
+        setDatabaseProperty("derby.authentication.provider", "BUILTIN");
+        setDatabaseProperty("derby.connection.requireAuthentication", "true");
+        
+        JDBCDataSource.setBeanProperty(ds, "shutdownDatabase", "shutdown");
+        try {
+            ds.getConnection();
+        } catch (SQLException sqle) {
+            assertSQLState("XJ015", sqle);
+        }
+
+        JDBCDataSource.clearStringBeanProperty(ds, "databaseName");
+        JDBCDataSource.clearStringBeanProperty(ds, "shutdownDatabase");
+
+        // "AUTHENTICATION NOW ENABLED");
+
+        // DataSource - attributesAsPassword=true
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+
+        // ensure the DS property password is not treated as a set of 
+        // attributes.
+        // DataSource - attributesAsPassword=true, user=fred, 
+        //     password=databaseName=wombat;password=wilma
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.TRUE);
+        JDBCDataSource.setBeanProperty(ds, "user", "fred");
+        JDBCDataSource.setBeanProperty(ds, "password", "databaseName=" + dbName + ";password=wilma");
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"}, ds);
+        JDBCDataSource.setBeanProperty(ds, "attributesAsPassword", Boolean.FALSE);
+        JDBCDataSource.clearStringBeanProperty(ds, "user");
+        JDBCDataSource.clearStringBeanProperty(ds, "password");
+        ds = null;
+
+        // now with ConnectionPoolDataSource
+        String cpdsName = dsclient.getConnectionPoolDataSourceClassName();
+        ConnectionPoolDataSource cpds = null;
+        try {
+            cpds = (javax.sql.ConnectionPoolDataSource) 
+                Class.forName(cpdsName).newInstance();
+        } catch (Exception e) {
+            fail("unable to complete test because unable " +
+                    "to create new instance of connection pool datasource");
+        }
+
+        // ConnectionPoolDataSource - EMPTY
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ004",
+            "XJ004","XJ004","XJ004","XJ004","XJ004"},
+            (ConnectionPoolDataSource)cpds);
+
+        // ConnectionPoolDataSource - 
+        // connectionAttributes=databaseName=wombat
+        JDBCDataSource.setBeanProperty(cpds, "connectionAttributes", "databaseName=" + dbName);
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ004",
+            "XJ004","XJ004","XJ004","XJ004","XJ004"},
+            (ConnectionPoolDataSource)cpds);
+        JDBCDataSource.clearStringBeanProperty(cpds, "connectionAttributes");
+
+        // ConnectionPoolDataSource - attributesAsPassword=true
+        JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.TRUE);
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"},
+            (ConnectionPoolDataSource)cpds);
+        JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.FALSE);
+        
+        // ensure the DS property password is not treated as a set of
+        // attributes.
+        // ConnectionPoolDataSource - attributesAsPassword=true, 
+        //     user=fred, password=databaseName=wombat;password=wilma");
+        JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.TRUE);
+        JDBCDataSource.setBeanProperty(cpds, "user", "fred");
+        JDBCDataSource.setBeanProperty(cpds, "password", "databaseName=" + dbName + ";password=wilma");
+        dsConnectionRequests(new String[] {  
+            "XJ004","XJ004","XJ004","XJ028",
+            "XJ028","XJ004","XJ004","XJ004","XJ004"},
+            (ConnectionPoolDataSource)cpds);
+        JDBCDataSource.setBeanProperty(cpds, "attributesAsPassword", Boolean.FALSE);
+        JDBCDataSource.clearStringBeanProperty(cpds, "user");
+        JDBCDataSource.clearStringBeanProperty(cpds, "password");
+        cpds = null;
+
+        // now with XADataSource

[... 1627 lines stripped ...]


Mime
View raw message