You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jg...@apache.org on 2015/11/09 17:43:26 UTC

svn commit: r1713475 - in /openjpa/branches/2.2.x: openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java

Author: jgrassel
Date: Mon Nov  9 16:43:26 2015
New Revision: 1713475

URL: http://svn.apache.org/viewvc?rev=1713475&view=rev
Log:
OPENJPA-2605: DelegatingConnection.unwrap() doesn't adhere to java.sql.Wrapper.unwrap() contract

Modified:
    openjpa/branches/2.2.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java
    openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java

Modified: openjpa/branches/2.2.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java?rev=1713475&r1=1713474&r2=1713475&view=diff
==============================================================================
--- openjpa/branches/2.2.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java (original)
+++ openjpa/branches/2.2.x/openjpa-lib/src/main/java/org/apache/openjpa/lib/jdbc/DelegatingConnection.java Mon Nov  9 16:43:26 2015
@@ -460,12 +460,27 @@ public class DelegatingConnection implem
         return iface.isAssignableFrom(getDelegate().getClass());
     }
 
+    /**
+     * From java.sql.Wrapper javadoc:
+     * 
+     * Returns an object that implements the given interface to allow access to 
+     * non-standard methods, or standard methods not exposed by the proxy. If 
+     * the receiver implements the interface then the result is the receiver 
+     * or a proxy for the receiver. If the receiver is a wrapper and the 
+     * wrapped object implements the interface then the result is the wrapped 
+     * object or a proxy for the wrapped object. Otherwise return the the 
+     * result of calling unwrap recursively on the wrapped object or a proxy 
+     * for that result. If the receiver is not a wrapper and does not implement
+     * the interface, then an SQLException is thrown.
+     * 
+     */
     @Override
     public <T> T unwrap(Class<T> iface) throws SQLException {
-        if (isWrapperFor(iface))
+        if (isWrapperFor(iface)) {
             return (T) getDelegate();
-        else
-            return null;
+        } else {
+            return getDelegate().unwrap(iface);
+        }
     }
 
     public Array createArrayOf(String typeName, Object[] elements) throws SQLException {

Modified: openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java
URL: http://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java?rev=1713475&r1=1713474&r2=1713475&view=diff
==============================================================================
--- openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java (original)
+++ openjpa/branches/2.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/TestUnwrap.java Mon Nov  9 16:43:26 2015
@@ -18,6 +18,9 @@
  */
 package org.apache.openjpa.persistence;
 
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -25,7 +28,10 @@ import javax.persistence.EntityManager;
 import javax.persistence.EntityTransaction;
 import javax.persistence.Query;
 
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.sql.DerbyDictionary;
 import org.apache.openjpa.kernel.QueryLanguages;
+import org.apache.openjpa.lib.jdbc.DelegatingConnection;
 import org.apache.openjpa.persistence.test.SingleEMFTestCase;
 
 public class TestUnwrap extends SingleEMFTestCase {
@@ -90,6 +96,76 @@ public class TestUnwrap extends SingleEM
         em.close();
     }
     
+    public void testConnectionUnwrap() throws Exception {
+        String dbDict = ((JDBCConfiguration) emf.getConfiguration()).getDBDictionaryInstance().getClass().getName();
+        
+        EntityManager em = emf.createEntityManager();
+        OpenJPAEntityManager oem = em.unwrap(OpenJPAEntityManager.class);
+        try {
+            Connection c = (Connection) oem.getConnection();
+            assertNotNull(c);
+            assertTrue(DelegatingConnection.class.isAssignableFrom(c.getClass()));
+            
+            List<Class> acceptedConnectionClassTypes = new ArrayList<Class>();
+            if (DerbyDictionary.class.getName().equals(dbDict)) {
+                // Connection type can be network or embedded
+                String[] connectionTypes = { 
+                    "org.apache.derby.impl.jdbc.EmbedConnection40",
+                    "org.apache.derby.impl.jdbc.EmbedConnection30",
+                    "org.apache.derby.iapi.jdbc.BrokeredConnection40",
+                    "org.apache.derby.iapi.jdbc.BrokeredConnection30" };
+                for (String ct : connectionTypes) {
+                    try {
+                        Class cls = Class.forName(ct);
+                        acceptedConnectionClassTypes.add(cls);
+                    } catch (ClassNotFoundException cnfe) {
+                        // Swallow
+                    }
+                }
+            }
+            
+            if (!acceptedConnectionClassTypes.isEmpty()) {
+                boolean pass = false;
+                for (Class cls : acceptedConnectionClassTypes) {
+                    try {
+                        Connection castC = (Connection) c.unwrap(cls);
+                        assertNotNull(castC);
+                        assertEquals(cls, castC.getClass());
+                        pass = true;
+                        break;
+                    } catch (Throwable t) {
+                        // Swallow
+                    }
+                    
+                   assertTrue(pass); 
+                }
+            }
+        } finally {
+            em.close();
+        }
+    }
+    
+    public void testNegativeConnectionUnwrap() {
+        EntityManager em = emf.createEntityManager();
+        OpenJPAEntityManager oem = em.unwrap(OpenJPAEntityManager.class);
+        
+        try {
+            Connection c = (Connection) oem.getConnection();
+            assertNotNull(c);
+            assertTrue(DelegatingConnection.class.isAssignableFrom(c.getClass()));
+            
+            // Make a completely bogus unwrap() attempt
+            try {
+                c.unwrap(TestUnwrap.class);
+                fail("Bogus unwrap should have thrown a SQLException.");
+            } catch (java.sql.SQLException se) {
+                // Expected
+            }
+        } finally {
+            em.close();
+        }
+    }
+    
     /**
      * Tests a EntityManager can not be unwrapped as Object class, null or an interface. 
      * And each such failure raises a Persistence Exception and causes an active transaction