Author: ppoddar
Date: Fri Jul 11 13:28:49 2008
New Revision: 676073

URL: http://svn.apache.org/viewvc?rev=676073&view=rev
Log:
OPENJPA-656: raise error messages with connection parameters on connect failure

Added:
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java?rev=676073&r1=676072&r2=676073&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/DataSourceFactory.java
 Fri Jul 11 13:28:49 2008
@@ -26,6 +26,7 @@
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+
 import javax.sql.DataSource;
 
 import org.apache.commons.lang.StringUtils;
@@ -45,7 +46,6 @@
 import org.apache.openjpa.lib.util.Options;
 import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.StoreException;
 import org.apache.openjpa.util.UserException;
 
 /**
@@ -59,7 +59,7 @@
 public class DataSourceFactory {
 
     private static final Localizer _loc = Localizer.forPackage
-        (DataSourceFactory.class);
+        (DataSourceFactory.class);
 
     /**
      * Create a datasource using the given configuration.
@@ -120,7 +120,7 @@
         catch (OpenJPAException ke) {
             throw ke;
         } catch (Exception e) {
-            throw new StoreException(e).setFatal(true);
+            throw newConnectException(conf, factory2, e);
         }
 
         // not a driver or a data source; die
@@ -175,7 +175,7 @@
         } catch (OpenJPAException ke) {
             throw ke;
         } catch (Exception e) {
-            throw new StoreException(e).setFatal(true);
+            throw newConnectException(conf, factory2, e);
         }
     }
 
@@ -237,14 +237,7 @@
 
             return ds;
         } catch (Exception e) {
-               throw new StoreException(_loc.get("conn-failed", factory2 
-                 ? new Object[]{conf.getConnection2DriverName(), 
-                                        conf.getConnection2URL(), 
-                                        conf.getConnection2Properties()}
-                 : new Object[]{conf.getConnectionDriverName(),
-                                    conf.getConnectionURL(), 
-                                    conf.getConnectionProperties()}),
-                                    e);
+               throw newConnectException(conf, factory2, e);
         } finally {
             if (conn != null)
                 try {
@@ -255,6 +248,18 @@
                 }
         }
     }
+    
+    static OpenJPAException newConnectException(JDBCConfiguration conf, 
+               boolean factory2, Exception cause) {
+       return new UserException(_loc.get("conn-failed", factory2 
+                 ? new Object[]{conf.getConnection2DriverName(), 
+                                        conf.getConnection2URL(), 
+                                        conf.getConnection2Properties()}
+                 : new Object[]{conf.getConnectionDriverName(),
+                                    conf.getConnectionURL(), 
+                                    conf.getConnectionProperties()}),
+                                    cause).setFatal(true);
+    }
 
     /**
      * Return a data source with the given user name and password

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java?rev=676073&r1=676072&r2=676073&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SimpleDriverDataSource.java
 Fri Jul 11 13:28:49 2008
@@ -77,8 +77,8 @@
         throws SQLException {
        Connection con = getDriver().connect(_connectionURL, props);
        if (con == null) {
-               throw new UserException(_loc.get("conn-failed",
-                               _connectionDriverName, _connectionURL, props));
+               throw new SQLException(_loc.get("conn-failed",
+                               _connectionDriverName, _connectionURL, 
props).getMessage());
         }
         return con;
     }

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java?rev=676073&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/conf/TestBadJdbcUrl.java
 Fri Jul 11 13:28:49 2008
@@ -0,0 +1,198 @@
+/*
+ * 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.openjpa.conf;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceException;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * Verifies appropriate exception is thrown when an incorrect protocol or
+ * sub-protocol is specified in the JDBC URL. Per the JDBC specification, the
+ * Driver should return a null connection upon getConnection() when a bad 
driver
+ * is specified on the URL. OpenJPA must be able to handle this condition and
+ * return an appropriate message.
+ * 
+ * OpenJPA JIRA: [EMAIL PROTECTED] 
http://issues.apache.org/jira/browse/OPENJPA-656}
+ * 
+ * @author Jeremy Bauer
+ * @author Pinaki Poddar
+ * 
+ */
+public class TestBadJdbcUrl extends TestCase {
+       public static final String GOOD_URL = 
"jdbc:derby:target/database/openjpa-derby-database;create=true";
+       public static final String GOOD_DRIVER = 
"org.apache.derby.jdbc.EmbeddedDriver";
+       public static final String GOOD_DATASOURCE = 
"org.apache.commons.dbcp.BasicDataSource";
+
+       public static final String BAD_DRIVER = "bad.driver";
+       public static final String BAD_URL_PROTOCOL = "bad.url.protocol";
+       public static final String BAD_URL_SUBPROTOCOL = "bad.url.sub.protocol";
+       public static final String BAD_CONN_PROPS = 
"connectionUrl=bad,connectionDriver=bad";
+
+       /*
+        * Test specifying URL with bad protocol but a valid Driver.
+        */
+       public void testBadUrlProtocolValueWithValidDriverClass() {
+               Properties p = new Properties();
+               p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+               p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
+               verifyConnectException(p, PersistenceException.class,
+                               UserException.class, GOOD_DRIVER, 
BAD_URL_PROTOCOL);
+       }
+
+       /*
+        * Test specifying URL with bad protocol but a valid DataSource.
+        */
+       public void testBadUrlProtocolValueWithValidDataSource() {
+               Properties p = new Properties();
+               p.put("openjpa.ConnectionDriverName", GOOD_DATASOURCE);
+               p.put("openjpa.ConnectionURL", BAD_URL_PROTOCOL);
+               p.put("openjpa.ConnectionProperties", BAD_CONN_PROPS);
+               verifyConnectException(p, PersistenceException.class,
+                               null, (String[])null);
+       }
+
+       /*
+        * Test specifying URL with bad sub-protocol but a valid Driver.
+        */
+       public void testBadUrlSubprotocolValueWithValidDriverClass() {
+               Properties p = new Properties();
+               p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+               p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
+               verifyConnectException(p, PersistenceException.class,
+                               UserException.class, GOOD_DRIVER, 
BAD_URL_SUBPROTOCOL);
+       }
+
+       /*
+        * Test specifying URL with bad sub-protocol but a valid Driver.
+        */
+       public void testBadUrlSubprotocolValueWithValidDataSource() {
+               Properties p = new Properties();
+               p.put("openjpa.ConnectionDriverName", GOOD_DRIVER);
+               p.put("openjpa.ConnectionURL", BAD_URL_SUBPROTOCOL);
+               verifyConnectException(p, PersistenceException.class,
+                               UserException.class, GOOD_DRIVER, 
BAD_URL_SUBPROTOCOL);
+       }
+
+       /*
+        * Test specifying Valid URL with an invalid Driver.
+        */
+       public void testValidUrlWithInvalidDriver() {
+               Properties p = new Properties();
+               p.put("openjpa.ConnectionDriverName", BAD_DRIVER);
+               p.put("openjpa.ConnectionURL", GOOD_URL);
+               verifyConnectException(p, PersistenceException.class,
+                               UserException.class, GOOD_URL, BAD_DRIVER);
+       }
+
+       /**
+        * Attempts to connect with given properties and analyze exception for 
the
+        * existence of given target exception and error message strings.
+        * 
+        * @param props
+        *            the properties to initialize the persistence unit
+        * @param target
+        *            the type expected exception to be raised.
+        * @param nested
+        *            the type expected nested exception. null implies not to 
look
+        *            for any.
+        * @param keys
+        *            the strings that must occur in the exception message.
+        */
+       private void verifyConnectException(Properties props, Class targetType,
+                       Class nestedType, String... keys) {
+               EntityManagerFactory emf = null;
+               EntityManager em = null;
+               try {
+                       emf = Persistence.createEntityManagerFactory("test", 
props);
+                       em = emf.createEntityManager();
+                       OpenJPAPersistence.cast(em).getConnection();
+                       fail("Should have caught a " + targetType.getName());
+               } catch (Throwable t) {
+                       assertException(t, targetType, nestedType);
+                       assertMessage(t, keys);
+               } finally {
+                       if (em != null)
+                               em.close();
+                       if (emf != null)
+                               emf.close();
+               }
+       }
+
+       /**
+        * Asserts that the given targetType is assignable from actual. Asserts 
that
+        * the nestedType is a nested within the given actual Throwable
+        * 
+        * @param actual
+        * @param targetType
+        * @param nestedType
+        */
+       void assertException(final Throwable actual, Class targetType,
+                       Class nestedTargetType) {
+               if (targetType == null)
+                       return;
+               assertNotNull(actual);
+               Class actualType = actual.getClass();
+               if (!targetType.isAssignableFrom(actualType)) {
+                       actual.printStackTrace();
+                       fail(targetType.getName() + " is not assignable from "
+                                       + actualType.getName());
+               }
+
+               if (nestedTargetType != null) {
+                       Throwable nested = actual.getCause();
+                       Class nestedType = (nested == null) ? null : 
nested.getClass();
+                       while (nestedType != null) {
+                               if 
(nestedType.isAssignableFrom(nestedTargetType)) {
+                                       return;
+                               } else {
+                                       Throwable next = nested.getCause();
+                                       if (next == null || next == nested)
+                                               break;
+                                       nestedType = next.getClass();
+                                       nested     = next;
+                               }
+                       }
+                       actual.printStackTrace();
+                       fail("No nested type " + nestedTargetType + " in " + 
actual);
+               }
+       }
+
+       /**
+        * Assert that each of given keys are present in the message of the 
given
+        * Throwable.
+        */
+       void assertMessage(Throwable actual, String... keys) {
+               if (actual == null || keys == null)
+                       return;
+               String message = actual.getMessage();
+               for (String key : keys) {
+                       assertTrue(key + " is not in " + message, 
message.contains(key));
+               }
+       }
+}


Reply via email to