You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by my...@apache.org on 2007/04/17 08:56:41 UTC

svn commit: r529505 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/jdbc/ testing/org/apache/derbyTesting/functionTests/master/ testing/org/apache/derbyTesting/functionTests/suites/ testing/org/apache/derbyTes...

Author: myrnavl
Date: Mon Apr 16 23:56:40 2007
New Revision: 529505

URL: http://svn.apache.org/viewvc?view=rev&rev=529505
Log:
DERBY-2296 - implement setShutdownDatabase, getShutdownDatabase, setCreateDatabase and getCreateDatabase methods for client datasources.
  Also added a new junit test, DSCreateShutdownDBTest, and converted the only test that was affected by the client code change, dataSourceReference.java, to junit test DataSourceReferenceTest.java.


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java   (with props)
Removed:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/dataSourceReference.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/dataSourceReference_app.properties
Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
    db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNet.exclude
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc20.runall
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/JDBCHarnessJavaTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Mon Apr 16 23:56:40 2007
@@ -184,8 +184,22 @@
         // "setConnectionAttributes" method.  
         databaseName_ = dataSource.getDatabaseName();
         String connAtrrs = dataSource.getConnectionAttributes();
+        if (dataSource.getCreateDatabase() != null) // can be "create" or null
+        {
+            if (connAtrrs == null)
+                connAtrrs = "create=true";
+            else
+                connAtrrs = connAtrrs + ";create=true";
+        }
+        if (dataSource.getShutdownDatabase() != null) // "shutdown" or null
+        {
+            if (connAtrrs == null)
+                connAtrrs = "shutdown=true";
+            else
+                connAtrrs = connAtrrs + ";shutdown=true";
+        }
         if(databaseName_ != null && connAtrrs != null)
-        	databaseName_ = databaseName_ + ";" + connAtrrs;
+            databaseName_ = databaseName_ + ";" + connAtrrs;
 
         retrieveMessageText_ = dataSource.getRetrieveMessageText();
 

Modified: db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/jdbc/ClientBaseDataSource.java Mon Apr 16 23:56:40 2007
@@ -677,7 +677,8 @@
                         new ClientMessageId(SQLState.INVALID_ATTRIBUTE_SYNTAX),
                         attributeString);
                 }
-
+                //if (shutdownDatabase != null )
+                
                 augmentedProperties.setProperty((v.substring(0, eqPos)).trim(), (v.substring(eqPos + 1)).trim());
             }
         } catch (NoSuchElementException e) {
@@ -852,6 +853,63 @@
             return getUpgradedSecurityMechanism(password);
         
         return securityMechanism;
+    }
+
+    // ----------------------- set/getCreate/ShutdownDatabase ---------------------------
+    /**
+     * Set to true if the database should be created.
+     */
+    private boolean createDatabase;
+
+    /**
+     * Set to true if the database should be shutdown.
+     */
+    private boolean shutdownDatabase;
+    
+    /**
+     * Set this property to create a new database.  If this property is not
+     * set, the database (identified by databaseName) is assumed to be already
+     * existing.
+     * @param create if set to the string "create", this data source will try
+     *               to create a new database of databaseName, or boot the 
+     *               database if one by that name already exists.
+     * 
+     */
+    public final void setCreateDatabase(String create) {
+        if (create != null && create.equalsIgnoreCase("create"))
+            this.createDatabase = true;
+    }
+    
+    /** @return "create" if create is set, or null if not 
+     */
+    public final String getCreateDatabase() {
+        String createstr=null;
+        if (createDatabase)
+            createstr="create";
+        return createstr;
+    }
+    
+    /**
+     * Set this property if one wishes to shutdown the database identified by
+     * databaseName. 
+     * @param shutdown if set to the string "shutdown", this data source will 
+     *                 shutdown the database if it is running.
+     * 
+     */
+    public final void setShutdownDatabase(String shutdown) {
+        if (shutdown != null && shutdown.equalsIgnoreCase("shutdown"))
+            this.shutdownDatabase = true;
+    }
+
+    /** @return "shutdown" if shutdown is set, or null if not 
+     */
+    public final String getShutdownDatabase() {
+        String shutdownstr=null;
+        if (shutdownDatabase)
+        {
+            shutdownstr = "shutdown"; 
+        }           
+        return shutdownstr;
     }
 
     protected String connectionAttributes = null;

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNet.exclude
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNet.exclude?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNet.exclude (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNet.exclude Mon Apr 16 23:56:40 2007
@@ -5,7 +5,6 @@
 # excluding jdbcapi/SetQueryTimeoutTest.java because neither the JCC driver nor the ClientDriver support setQueryTimeout() yet.
 # excluding jdbcapi/rsgetXXXcolumnNames.java as it fails incorrectly, according to JDBC spec. Forwarding test case to JCC team.
 # excluding jdbcapi/statementJdbc30.java - Client behaves differently. Need to look into this
-# excluding jdbcapi/dataSourceReference.java - client side only tests, tests all data sources
 #           regardless of framework
 # excluding largedata/LobLimits.java to run with the network server because currently lobs are materialized and this test tests for 2G lobs.
 # 			see DERBY-326 and DERBY-550 issues
@@ -17,7 +16,6 @@
 jdbcapi/SetQueryTimeoutTest.java
 jdbcapi/blobSetBinaryStream.java
 jdbcapi/statementJdbc30.java
-jdbcapi/dataSourceReference.java
 #no XA for JCC
 jdbcapi/savepointJdbc30_XA.java
 # excluding jdbcapi/derbyStress.java - jcc runs out of memory with this test

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude Mon Apr 16 23:56:40 2007
@@ -1,7 +1,6 @@
 # excluding TestErrorStreamTarget.java since it's not relevant for clients
 # excluding statementJdbc20.java because this tests fetch_reverse throughout the test
 # excluding jdbcapi/statementJdbc30.java - Client behaves differently. Need to look into this
-# excluding jdbcapi/dataSourceReference.java - client side only tests, tests all data sources
 #           regardless of framework
 # excluding largedata/LobLimits.java to run with the network server because currently lobs are materialized and this test tests for 2G lobs.
 # 			see DERBY-326 and DERBY-550 issues
@@ -9,7 +8,6 @@
 #
 jdbcapi/statementJdbc20.java
 jdbcapi/statementJdbc30.java
-jdbcapi/dataSourceReference.java
 largedata/LobLimits.java
 #
 # This test brings the network server up and down by itself

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc20.runall
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc20.runall?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc20.runall (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/jdbc20.runall Mon Apr 16 23:56:40 2007
@@ -1,2 +1 @@
 jdbcapi/getCurConnJdbc20.sql
-jdbcapi/dataSourceReference.java

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java?view=auto&rev=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java Mon Apr 16 23:56:40 2007
@@ -0,0 +1,389 @@
+/*
+ * 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.lang.reflect.Method;
+import java.security.AccessController;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import junit.extensions.TestSetup;
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.BaseTestCase;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+public class DSCreateShutdownDBTest extends BaseJDBCTestCase {
+
+    static final String[] ADDITIONAL_DBS = {
+        "dscreateshutdowndb1", 
+        "dscreateshutdowndb2",
+        "conflict1",
+        "conflict2",
+        "conflict3",
+        "conflict4",
+        "conflict5",
+        "conflict6",
+        "conflict7"
+    };
+    
+    static String DBNotFoundState;
+    
+    public DSCreateShutdownDBTest(String name) {
+        super(name);
+    }
+
+    public static Test suite() 
+    {
+        TestSuite suite = new TestSuite("DSCreateShutdownTest"); 
+        Test test = TestConfiguration.defaultSuite(DSCreateShutdownDBTest.class);        
+        //Test test = TestConfiguration.clientServerSuite(DSCreateShutdownDBTest.class);
+        suite.addTest(test);
+        
+        TestSetup setup = TestConfiguration.singleUseDatabaseDecorator(suite);
+        // we need a couple extra databases to test they get created
+        for (int i = 0; i < ADDITIONAL_DBS.length; i++)
+        {
+            setup = TestConfiguration.additionalDatabaseDecorator(setup,
+                "emb" + ADDITIONAL_DBS[i]);
+            setup = TestConfiguration.additionalDatabaseDecorator(setup,
+                "srv" + ADDITIONAL_DBS[i]);
+        }
+    
+        return suite;
+    }
+    
+    public void tearDown() throws Exception {
+        // attempt to get rid of any databases. 
+        // only 4 dbs (in addition to defaultdb) should actually get
+        // created, but just in case...
+        AccessController.doPrivileged(new java.security.PrivilegedAction() {
+            public Object run() {
+                for (int i=0 ; i < ADDITIONAL_DBS.length ; i++)
+                {   
+                    removeDatabase("emb" + ADDITIONAL_DBS[i]);
+                    removeDatabase("srv" + ADDITIONAL_DBS[i]);
+                } 
+                return null;
+            }
+            
+            void removeDatabase(String dbName)
+            {
+                //TestConfiguration config = TestConfiguration.getCurrent();
+                dbName = dbName.replace('/', File.separatorChar);
+                String dsh = BaseTestCase.getSystemProperty("derby.system.home");
+                if (dsh == null) {
+                    fail("not implemented");
+                } else {
+                    dbName = dsh + File.separator + dbName;
+                }
+                removeDirectory(dbName);
+            }
+
+            void removeDirectory(String path)
+            {
+                final File dir = new File(path);
+                removeDir(dir);
+            }
+
+            private void removeDir(File dir) {
+                
+                // Check if anything to do!
+                // Database may not have been created.
+                if (!dir.exists())
+                    return;
+
+                String[] list = dir.list();
+
+                // Some JVMs return null for File.list() when the
+                // directory is empty.
+                if (list != null) {
+                    for (int i = 0; i < list.length; i++) {
+                        File entry = new File(dir, list[i]);
+
+                        if (entry.isDirectory()) {
+                            removeDir(entry);
+                        } else {
+                            entry.delete();
+                            //assertTrue(entry.getPath(), entry.delete());
+                        }
+                    }
+                }
+                dir.delete();
+                //assertTrue(dir.getPath(), dir.delete());
+            }
+        });
+        super.tearDown();
+    }
+
+    public void testCreateAndShutdown() throws SQLException {
+        
+        if (usingEmbedded())
+            DBNotFoundState = "XJ004";
+        else
+            DBNotFoundState = "08004";
+        
+        // first play with default db, which is already created.
+        String dbName = 
+            TestConfiguration.getCurrent().getDefaultDatabaseName();
+        // just check that we really access the database
+        assertUpdateCount(createStatement(), 0, "set schema APP");
+   
+        // check that first the value is null
+        assertGetNull(dbName);
+        // check that we can set & that when set we can get
+        // doesn't actually open connections so a little silly.
+        assertSetAndGet(dbName, "shutdownDatabase", "shutdown");
+        assertSetAndGet(dbName, "createDatabase", "create");
+        // set to an invalid value, should get ignored
+        assertNotSetAndGet(dbName, "shutdownDatabase", "boo");
+        assertNotSetAndGet(dbName, "createDatabase", "boo");
+        assertNotSetAndGet(dbName, "shutdownDatabase", "false");
+        assertNotSetAndGet(dbName, "createDatabase", "false");
+        
+        // check that shutting down using Attributes works
+        assertShutdownUsingConnAttrsOK(dbName);
+        // re-vive db
+        getConnection();
+        
+        // now, actually create, and shutdown a database
+        // first ensure it's not there yet
+        dbName = composeDatabaseName(ADDITIONAL_DBS[0]);
+        assertNoDB(dbName);
+        // straightforward create and shutdown
+        assertPositive(dbName);
+        
+        // what happens when you combine set*Database and 
+        // matching connection attribute? (should work)
+        dbName = composeDatabaseName(ADDITIONAL_DBS[1]);
+        assertNoDB(dbName);
+        assertTwiceOK(dbName);
+        
+        // the rest of the testing is on conflicted settings
+        // the result is not defined, so a change in behavior does not 
+        // necessarily indicate a bug, but may be relevant for existing apps
+        // what happens when you combine create and shutdown connattr?
+        // database does not get created.
+        assertShutdownAndCreateConnAttr(DBNotFoundState, 
+            composeDatabaseName(ADDITIONAL_DBS[2]), 
+            "shutdown=true;create=true");
+        assertShutdownAndCreateConnAttr(DBNotFoundState, 
+            composeDatabaseName(ADDITIONAL_DBS[3]), 
+            "create=true;shutdown=true");
+
+        // and when you set both setShutdownDatabase and setCreateDatabase?
+        // database does not get created
+        assertConflictedSettersOK(composeDatabaseName(ADDITIONAL_DBS[4]));
+        
+        // what happens when you combine set*Database and
+        // opposing connection attributes? database does not get created. 
+        assertConflictedSetterConnAttrOK();
+    }
+    
+    protected String composeDatabaseName(String dbName) {
+        if (usingEmbedded())
+            return "emb" + dbName;
+        else 
+            return "srv" + dbName;
+    }
+    
+    protected void assertGetNull(String dbName) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSourceLogical(dbName);
+        assertNull(getBeanProperty(ds, "shutdownDatabase"));
+        assertNull(getBeanProperty(ds, "createDatabase"));
+    }
+    
+    protected void assertSetAndGet(
+        String dbName, String propertyString, String setValue)
+    throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSourceLogical(dbName);
+        JDBCDataSource.setBeanProperty(ds, propertyString, setValue);
+        assertEquals(setValue,getBeanProperty(ds, propertyString).toString());
+    }
+    
+    protected void assertNotSetAndGet(
+        String dbName, String propertyString, String setValue)
+    throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSourceLogical(dbName);
+        JDBCDataSource.setBeanProperty(ds, propertyString, setValue);
+        assertNull(getBeanProperty(ds, propertyString));
+    }
+    
+    public static Object getBeanProperty(Object ds, String propertyString)
+    {
+        String getterName = getGetterName(propertyString);
+
+        // Base the type of the setter method from the value's class.
+
+        Object retObject=null;
+        try {
+            Method getter = ds.getClass().getMethod(getterName, null);
+            retObject = getter.invoke(ds, null);
+        } catch (Exception e) {
+            Assert.fail(e.getMessage());
+        }
+        return retObject;
+    }
+
+    private static String getGetterName(String attribute) {
+        return "get" + Character.toUpperCase(attribute.charAt(0))
+        + attribute.substring(1);
+    }
+    
+    // if the connattr parameter is true, we set both setShutdownDatabase
+    // and ConnectionAttribute shutdown=true.
+    protected void assertShutdownUsingSetOK(String dbName, boolean connAttr)
+    throws SQLException {
+
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        JDBCDataSource.setBeanProperty(ds, "shutdownDatabase", "shutdown");
+        if (connAttr)
+            JDBCDataSource.setBeanProperty(
+                ds, "ConnectionAttributes", "shutdown=true");
+        assertDSConnectionFailed("08006", ds);
+    }
+    
+    protected void assertShutdownUsingConnAttrsOK(String dbName)
+    throws SQLException {
+
+        DataSource ds = JDBCDataSource.getDataSourceLogical(dbName);
+        JDBCDataSource.setBeanProperty(
+            ds, "ConnectionAttributes", "shutdown=true");
+        assertDSConnectionFailed("08006", ds);
+    }
+
+    protected void assertShutdownAndCreateConnAttr(
+        String expectedSQLState, String dbName, String twoPropertyString)
+    throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        JDBCDataSource.setBeanProperty(
+            ds, "ConnectionAttributes", twoPropertyString);
+        assertDSConnectionFailed(expectedSQLState, ds);
+    }
+    
+    protected void assertDSConnectionFailed(
+        String expectedSQLState, DataSource ds) throws SQLException {
+        try {
+            ds.getConnection();
+            fail("expected an sqlexception " + expectedSQLState);
+        } catch (SQLException sqle) {
+            assertSQLState(expectedSQLState, sqle);
+        }
+    }    
+    
+    protected void assertNoDB(String dbName) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        assertDSConnectionFailed(DBNotFoundState, ds);
+    }
+    
+    protected void assertPositive(String dbName) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        JDBCDataSource.setBeanProperty(ds, "CreateDatabase", "create");
+        // check that the db exists; execute an unnecessary, but harmless, stmt
+        assertUpdateCount(
+            ds.getConnection().createStatement(), 0, "set schema APP");
+        JDBCDataSource.clearStringBeanProperty(ds, "CreateDatabase");
+        assertShutdownUsingSetOK(dbName, false);
+    }
+
+    protected void assertTwiceOK(String dbName) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        JDBCDataSource.setBeanProperty(ds, "CreateDatabase", "create");
+        JDBCDataSource.setBeanProperty(
+            ds, "ConnectionAttributes", "create=true");
+        // check that the db exists; execute an unnecessary, but harmless, stmt
+        assertUpdateCount(
+            ds.getConnection().createStatement(), 0, "set schema APP");
+        JDBCDataSource.clearStringBeanProperty(ds, "CreateDatabase");
+        JDBCDataSource.clearStringBeanProperty(ds, "ConnectionAttributes");
+        assertShutdownUsingSetOK(dbName, true);
+    }
+    
+    protected void assertConflictedSettersOK(String dbName) throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        JDBCDataSource.setBeanProperty(ds, "CreateDatabase", "create");
+        JDBCDataSource.setBeanProperty(ds, "shutdownDatabase", "shutdown");
+        try {
+            ds.getConnection();
+        } catch (SQLException se) {
+            assertSQLState(DBNotFoundState, se);
+        }
+    }
+
+    protected void assertConflictedSetterConnAttrOK() 
+    throws SQLException {
+        assertConSetOK(DBNotFoundState, composeDatabaseName(ADDITIONAL_DBS[5]), 
+            "shutdown=true", "CreateDatabase", "create");
+        // with the new networkserver methods, this actually works...
+        assertConSetOK(DBNotFoundState, composeDatabaseName(ADDITIONAL_DBS[6]),
+            "create=true", "ShutdownDatabase", "shutdown");
+        assertSetConOK(DBNotFoundState, composeDatabaseName(ADDITIONAL_DBS[7]), 
+            "shutdown=true", "CreateDatabase", "create");
+        // with the new networkserver methods, this actually works...
+        assertSetConOK(DBNotFoundState, composeDatabaseName(ADDITIONAL_DBS[8]),
+            "create=true", "ShutdownDatabase", "shutdown");
+
+    }
+    
+    // first sets setCreate/ShutdownDB, then sets ConnectionAttributes
+    protected void assertConSetOK(String expectedSQLState, String dbName, 
+        String connAttrValue, String setter, String setValue) 
+    throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        
+        JDBCDataSource.setBeanProperty(ds, setter, setValue);
+        JDBCDataSource.setBeanProperty(
+            ds, "ConnectionAttributes", connAttrValue);
+        // check that the db exists; execute an unnecessary, but harmless, stmt
+        try {
+            ds.getConnection();
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se);
+        }
+        JDBCDataSource.clearStringBeanProperty(ds, setter);
+        JDBCDataSource.clearStringBeanProperty(ds, "ConnectionAttributes");
+    }
+
+    // sets ConnectionAttributes first, then SetCreate/ShutdownDB
+    protected void assertSetConOK(String expectedSQLState, String dbName, 
+        String connAttrValue, String setter, String setValue) 
+    throws SQLException {
+        DataSource ds = JDBCDataSource.getDataSource(dbName);
+        
+        JDBCDataSource.setBeanProperty(
+            ds, "ConnectionAttributes", connAttrValue);
+        JDBCDataSource.setBeanProperty(ds, setter, setValue);
+        // check that the db exists; execute an unnecessary, but harmless, stmt
+        try {
+            ds.getConnection();
+        } catch (SQLException se) {
+            assertSQLState(expectedSQLState, se);
+        }
+        JDBCDataSource.clearStringBeanProperty(ds, "ConnectionAttributes");
+        JDBCDataSource.clearStringBeanProperty(ds, setter);
+    }
+
+}
\ No newline at end of file

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DSCreateShutdownDBTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java?view=auto&rev=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java Mon Apr 16 23:56:40 2007
@@ -0,0 +1,381 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.functionTests.tests.jdbcapi.DataSourceReferenceTest
+
+   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.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.spi.ObjectFactory;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.J2EEDataSource;
+import org.apache.derbyTesting.junit.JDBC;
+import org.apache.derbyTesting.junit.JDBCDataSource;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+
+/**
+ * Test obtaining a javax.naming.Reference from a Derby data source
+ * and recreating a Derby data source from it. Tests that the recreated
+ * value has the same value for all the properties the data source supports.
+ * The list of properties is obtained dynamically from the getXXX methods
+ * that return int, String, boolean, short, long. Should Derby data sources
+ * support any other bean property types then this test should be modified
+ * to pick them up and handle them. Hopefully the test should fail when such
+ * a property is added.
+ * 
+ * At no point does this test attempt to connect using these data sources.
+ */
+public class DataSourceReferenceTest extends BaseJDBCTestCase {
+
+    private static String[][][] expectedValues = {
+        // org.apache.derby.jdbc.Embedded*DataSource
+        {{"attributesAsPassword", "false"}, null, null, null, null, null, 
+         {"loginTimeout", "0"}, null, null, null}, 
+        {{"attributesAsPassword", "true"}, 
+         {"connectionAttributes", "XX_connectionAttributes_2135"},
+         {"createDatabase", "create"},
+         {"dataSourceName", "XX_dataSourceName_1420"},
+         {"databaseName", "XX_databaseName_1206"},
+         {"description", "XX_description_1188"},
+         {"loginTimeout", "1280"},
+         {"password", "XX_password_883"},
+         {"shutdownDatabase", "shutdown"},
+         {"user", "XX_user_447"}},
+        // org.apache.derby.jdbc.Client*DataSource
+        { null, null, null, null, null, {"loginTimeout", "0"}, null, 
+         {"portNumber", "tmpportno"},
+         {"retrieveMessageText", "true"},
+         {"securityMechanism", "4"},
+         {"serverName", "tmphostName"}, null, null, null, 
+         {"traceFileAppend", "false"},
+         {"traceLevel", "-1"},
+         {"user", "tmpUserName"}},
+        {{"connectionAttributes", "XX_connectionAttributes_2135"},
+         {"createDatabase", "create"},
+         {"dataSourceName", "XX_dataSourceName_1420"},
+         {"databaseName", "XX_databaseName_1206"},
+         {"description", "XX_description_1188"},
+         {"loginTimeout", "1280"},
+         {"password", "XX_password_883"},
+         {"portNumber", "1070"},
+         {"retrieveMessageText", "false"},
+         {"securityMechanism", "1805"},
+         {"serverName", "XX_serverName_1048"},
+         {"shutdownDatabase", "shutdown"},
+         {"traceDirectory", "XX_traceDirectory_1476"},
+         {"traceFile", "XX_traceFile_911"},
+         {"traceFileAppend", "true"},
+         {"traceLevel", "1031"},
+         {"user", "XX_user_447"}}
+    };
+    
+    public DataSourceReferenceTest(String name) {
+        super(name);
+    }
+    
+    public static Test suite() {
+        if (JDBC.vmSupportsJSR169())
+        {
+            // Referencable is not supported with JSR169
+            TestSuite suite = 
+                new TestSuite("DatasourceTest cannot run with JSR169");
+            return suite;
+        }
+        else
+        {
+            return 
+                TestConfiguration.defaultSuite(DataSourceReferenceTest.class);
+        }
+    }
+    
+    /**
+     * Test a data source
+     * <OL>
+     * <LI> Create an empty one from the class name
+     * <LI> Discover the property list
+     * <LI> Create a reference and recreate a data source
+     * <LI> Compare the two
+     * <LI> Serialize the data source and recreate
+     * <LI> Compare the two
+     * <LI> Set every property for the data source
+     * <LI> Create a reference and recreate a data source
+     * <LI> Compare the two
+     * </OL>
+     * @throws Exception
+     */
+    public static void testDSReference() throws Exception
+    {
+        String ds;
+        ds = JDBCDataSource.getDataSource().getClass().getName();
+        int expectedArray=0;
+        if (usingDerbyNetClient())
+            expectedArray = 2;
+        assertDataSourceReference(expectedArray, ds);
+        ds = J2EEDataSource.getConnectionPoolDataSource().getClass().getName();
+        assertDataSourceReference(expectedArray, ds);
+        ds = J2EEDataSource.getXADataSource().getClass().getName();
+        assertDataSourceReference(expectedArray, ds);
+    }
+        
+    public static void assertDataSourceReference(
+        int expectedArrayIndex, String dsName) throws Exception {
+
+        if (usingDerbyNetClient())
+        {
+            expectedValues[expectedArrayIndex][7][1] =
+                String.valueOf(TestConfiguration.getCurrent().getPort());
+            expectedValues[expectedArrayIndex][10][1] =
+                TestConfiguration.getCurrent().getHostName();
+            expectedValues[expectedArrayIndex][16][1] =
+                TestConfiguration.getCurrent().getUserName();
+        }
+        
+        Object ds = Class.forName(dsName).newInstance();
+        
+        println("DataSource class " + dsName);
+        String[] properties = getPropertyBeanList(ds);
+        assertEquals(
+            expectedValues[expectedArrayIndex+1].length, properties.length);
+        println(" property list");
+        
+        for (int i = 0; i < properties.length; i++)
+        {
+            assertEquals(
+                expectedValues[expectedArrayIndex+1][i][0], properties[i]);
+            println("  " + properties[i]);
+        }
+        
+        Referenceable refDS = (Referenceable) ds;
+        
+        Reference dsAsReference = refDS.getReference();
+        
+        String factoryClassName = dsAsReference.getFactoryClassName();
+        
+        ObjectFactory factory = 
+            (ObjectFactory) Class.forName(factoryClassName).newInstance();  
+        
+        Object recreatedDS = 
+            factory.getObjectInstance(dsAsReference, null, null, null);
+        
+        println(" empty DataSource recreated using Reference as " +
+            recreatedDS.getClass().getName());
+        // empty DataSource recreated using Reference should not be 
+        // the same as the original
+        assertNotSame(recreatedDS, ds);
+        
+        compareDS(expectedArrayIndex, properties, ds, recreatedDS);
+        
+        // now serialize and recreate
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(baos);  
+        oos.writeObject(ds);
+        oos.flush();
+        oos.close();
+        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bais);
+        recreatedDS = ois.readObject();
+        println(" empty DataSource recreated using serialization");
+        compareDS(expectedArrayIndex, properties, ds, recreatedDS);
+        
+        // now populate the data source
+        for (int i = 0; i < properties.length; i++)
+        {
+            String property = properties[i];
+            Method getMethod = getGet(property, ds);
+            
+            Method setMethod = getSet(getMethod, ds);
+            
+            Class pt = getMethod.getReturnType();
+            
+            // generate a somewhat unique value for a property
+            int val = 0;
+            for (int j = 0; j < property.length(); j++)
+                val += property.charAt(j);
+            
+            if (pt.equals(Integer.TYPE))
+            {
+                setMethod.invoke(ds, new Object[] {new Integer(val)});
+                continue;
+            }
+            if (pt.equals(String.class))
+            {
+                String value;
+                if (property.equals("createDatabase"))
+                    value = "create";
+                else if (property.equals("shutdownDatabase"))
+                    value = "shutdown";
+                else
+                    value = "XX_" + property + "_" + val;
+                    
+                setMethod.invoke(ds, new Object[] {value});
+                continue;
+            }
+            if (pt.equals(Boolean.TYPE))
+            {
+                // set the opposite value
+                Object gbv = getMethod.invoke(ds, null);
+                Boolean sbv = 
+                    Boolean.FALSE.equals(gbv) ? Boolean.TRUE : Boolean.FALSE;
+                setMethod.invoke(ds, new Object[] {sbv});
+                continue;
+            }           
+            if (pt.equals(Short.TYPE))
+            {
+                setMethod.invoke(ds, new Object[] {new Short((short)val)});
+                continue;
+            }
+            if (pt.equals(Long.TYPE))
+            {
+                setMethod.invoke(ds, new Object[] {new Long(val)});
+                continue;
+            }
+            fail ( property + " not settable - update test!!");
+        }
+        
+        dsAsReference = refDS.getReference();
+        recreatedDS = 
+            factory.getObjectInstance(dsAsReference, null, null, null);
+        println(" populated DataSource recreated using Reference as " 
+            + recreatedDS.getClass().getName());
+        // again, recreated should not be same instance
+        assertNotSame(recreatedDS, ds);
+        
+        compareDS(expectedArrayIndex+1, properties, ds, recreatedDS);     
+
+        // now serialize and recreate
+        baos = new ByteArrayOutputStream();
+        oos = new ObjectOutputStream(baos); 
+        oos.writeObject(ds);
+        oos.flush();
+        oos.close();
+        bais = new ByteArrayInputStream(baos.toByteArray());
+        ois = new ObjectInputStream(bais);
+        recreatedDS = ois.readObject();
+        println(" populated DataSource recreated using serialization");
+        compareDS(expectedArrayIndex+1, properties, ds, recreatedDS);
+    }
+    
+    private static String[] getPropertyBeanList(Object ds) throws Exception
+    {
+        Method[] allMethods = ds.getClass().getMethods();
+        
+        ArrayList properties = new ArrayList();
+        for (int i = 0; i < allMethods.length; i++)
+        {
+            Method m = allMethods[i];
+            String methodName = m.getName();
+            // Need at least getXX
+            if (methodName.length() < 5)
+                continue;
+            if (!methodName.startsWith("get"))
+                continue;
+            if (m.getParameterTypes().length != 0)
+                continue;
+
+            Class rt = m.getReturnType();
+            
+            if (rt.equals(Integer.TYPE) || rt.equals(String.class) || 
+                rt.equals(Boolean.TYPE) || rt.equals(Short.TYPE) ||
+                rt.equals(Long.TYPE))
+            {
+                // valid Java Bean property
+                 String beanName = methodName.substring(3,4).toLowerCase() 
+                     + methodName.substring(4);
+
+                properties.add(beanName);
+                continue;
+            }
+        
+            
+            assertFalse(rt.isPrimitive());
+            println("if rt.isPrimitive, method " + methodName + 
+                " not supported - update test!!");
+
+        }
+        
+        String[] propertyList = (String[]) properties.toArray(new String[0]);
+        
+        Arrays.sort(propertyList);
+        
+        return propertyList;
+    }
+    
+    private static Method getGet(String property, Object ds) throws Exception
+    {
+        String methodName =
+            "get" + property.substring(0,1).toUpperCase()
+            + property.substring(1);
+        Method m = ds.getClass().getMethod(methodName, null);
+        return m;
+    }
+
+    private static Method getSet(Method getMethod, Object ds) throws Exception
+    {
+        String methodName = "s" + getMethod.getName().substring(1);
+        Method m = ds.getClass().getMethod(
+            methodName, new Class[] {getMethod.getReturnType()});
+        return m;
+    }   
+
+    private static void compareDS(int expectedValuesArrayIndex,
+        String[] properties, Object ds, Object rds) throws Exception
+    {
+        println(" Start compare recreated");
+        for (int i = 0; i < properties.length; i++)
+        {
+            Method getMethod = getGet(properties[i], ds);
+            
+            Object dsValue = getMethod.invoke(ds, null);
+            Object rdsValue = getMethod.invoke(rds, null);
+            
+            if (dsValue == null)
+            {
+                // properties[i] originally null, should be recreated as null.
+                assertNull(rdsValue);
+            }
+            else
+            {
+                // properties[i] originally dsValue, should be recreated as
+                // rdsValue
+                assertEquals(dsValue, rdsValue);
+            }
+            if (dsValue != null)
+            {
+                assertEquals(expectedValues[expectedValuesArrayIndex][i][0], 
+                    properties[i]);
+                assertEquals(expectedValues[expectedValuesArrayIndex][i][1], 
+                    dsValue.toString());
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/DataSourceReferenceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/JDBCHarnessJavaTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/JDBCHarnessJavaTest.java?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/JDBCHarnessJavaTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/JDBCHarnessJavaTest.java Mon Apr 16 23:56:40 2007
@@ -49,7 +49,6 @@
             "connectionJdbc20",
             // "statementJdbc20", runs in embedded only
             "resultsetJdbc20",           
-            // "dataSourceReference", TODO: investigate failure/convert
             
             // from old jdbcapi.runall
             "derbyStress",

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java?view=diff&rev=529505&r1=529504&r2=529505
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/_Suite.java Mon Apr 16 23:56:40 2007
@@ -101,7 +101,10 @@
             // Tests uses JDBC 3.0 datasources
             suite.addTest(PoolDSAuthenticationTest.suite());
             suite.addTest(XADSAuthenticationTest.suite());
-            
+
+            // Test uses JDBC 3.0 datasources, and javax.naming.Reference etc.
+            suite.addTest(DataSourceReferenceTest.suite());
+
             // Test uses DriverManager, Pooled and XADataSources, and
             // an inner class implements ConnectionEventListener.
             suite.addTest(DataSourceTest.suite());