You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2013/04/26 08:16:15 UTC

svn commit: r1476058 - in /tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc: RoutedDataSource.java router/ConnectionProvider.java router/FailOverRouter.java

Author: rmannibucau
Date: Fri Apr 26 06:16:15 2013
New Revision: 1476058

URL: http://svn.apache.org/r1476058
Log:
TOMEE-912 reworking FailoverRouter to get rid of ConnectionProvider and better handling set/get

Removed:
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/ConnectionProvider.java
Modified:
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java
    tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/FailOverRouter.java

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java?rev=1476058&r1=1476057&r2=1476058&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java Fri Apr 26 06:16:15 2013
@@ -17,7 +17,6 @@
 package org.apache.openejb.resource.jdbc;
 
 import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.resource.jdbc.router.ConnectionProvider;
 import org.apache.openejb.resource.jdbc.router.Router;
 import org.apache.openejb.spi.ContainerSystem;
 import org.apache.openejb.util.reflection.Reflections;
@@ -108,17 +107,11 @@ public class RoutedDataSource implements
     }
 
     public Connection getConnection() throws SQLException {
-        if (ConnectionProvider.class.isInstance(getDelegate())) {
-            return ConnectionProvider.class.cast(getDelegate()).getConnection();
-        }
         return getTargetDataSource().getConnection();
     }
 
     public Connection getConnection(String username, String password)
             throws SQLException {
-        if (ConnectionProvider.class.isInstance(getDelegate())) {
-            return ConnectionProvider.class.cast(getDelegate()).getConnection(username, password);
-        }
         return getTargetDataSource().getConnection(username, password);
     }
 

Modified: tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/FailOverRouter.java
URL: http://svn.apache.org/viewvc/tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/FailOverRouter.java?rev=1476058&r1=1476057&r2=1476058&view=diff
==============================================================================
--- tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/FailOverRouter.java (original)
+++ tomee/tomee/trunk/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/router/FailOverRouter.java Fri Apr 26 06:16:15 2013
@@ -21,50 +21,26 @@ import org.apache.openejb.util.Logger;
 
 import javax.naming.NamingException;
 import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.SQLException;
+import javax.sql.XADataSource;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.Collection;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 
-public class FailOverRouter extends AbstractRouter implements ConnectionProvider {
+public class FailOverRouter extends AbstractRouter {
     private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_SERVER, FailOverRouter.class);
-
+    private final AtomicReference<DataSource> facade = new AtomicReference<DataSource>();
+    private final Collection<DataSource> dataSources = new CopyOnWriteArrayList<DataSource>();
     private String delimiter = ",";
     private String datasourceNames = "";
 
-    private Collection<DataSource> dataSources = new CopyOnWriteArrayList<DataSource>();
-
     @Override
     public DataSource getDataSource() {
-        for (final DataSource ds : dataSources) {
-            return ds;
-        }
-        throw new IllegalStateException("No datasource configured");
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        for (final DataSource ds : dataSources) {
-            try {
-                return ds.getConnection();
-            } catch (final SQLException e) {
-                // no-op
-            }
-        }
-        throw new SQLException("Can't connect to any datasources of " + dataSources);
-    }
-
-    @Override
-    public Connection getConnection(String user, String pwd) throws SQLException {
-        for (final DataSource ds : dataSources) {
-            try {
-                return ds.getConnection(user, pwd);
-            } catch (final SQLException e) {
-                // no-op
-            }
-        }
-        throw new SQLException("Can't connect to any datasources of " + dataSources);
+        return facade.get();
     }
 
     public void setDatasourceNames(final String datasourceNames) {
@@ -78,6 +54,7 @@ public class FailOverRouter extends Abst
     }
 
     private void initDataSources() {
+        dataSources.clear();
         for (final String ds : datasourceNames.split(Pattern.quote(delimiter))) {
             try {
                 final Object o = getOpenEJBResource(ds.trim());
@@ -89,6 +66,25 @@ public class FailOverRouter extends Abst
                 LOGGER.error("Can't find datasource '" + ds + "'", error);
             }
         }
+
+        initFacade();
+    }
+
+    private void initFacade() {
+        Class<?> clazz = DataSource.class;
+        int xads = 0;
+        for (final DataSource ds : dataSources) {
+            if (XADataSource.class.isInstance(ds)) {
+                xads++;
+            }
+        }
+        if (xads > 0 && xads == dataSources.size()) {
+            clazz = XADataSource.class;
+        }
+
+        facade.set(DataSource.class.cast(Proxy.newProxyInstance(
+                Thread.currentThread().getContextClassLoader(),
+                new Class<?>[]{ clazz }, new FacadeHandler(dataSources))));
     }
 
     public Collection<DataSource> getDataSources() {
@@ -98,5 +94,47 @@ public class FailOverRouter extends Abst
     public void updateDataSources(final Collection<DataSource> ds) {
         dataSources.clear();
         dataSources.addAll(ds);
+        initFacade();
+    }
+
+    private static class FacadeHandler implements InvocationHandler {
+        private final Collection<DataSource> delegates;
+
+        public FacadeHandler(final Collection<DataSource> dataSources) {
+            this.delegates = dataSources;
+        }
+
+        @Override
+        public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+            if (Object.class.equals(method.getDeclaringClass())) {
+                if ("toString".equals(method.getName())) {
+                    return "DataSourceFacade" + delegates;
+                }
+                if ("hashCode".equals(method.getName())) {
+                    return delegates.hashCode();
+                }
+                if ("equals".equals(method.getName())) {
+                    return method.invoke(this, args);
+                }
+            }
+
+            int ex = 0;
+            for (final DataSource ds : delegates) {
+                try {
+                    if (method.getName().startsWith("set")) {
+                        method.invoke(ds, args);
+                    } else if (method.getName().startsWith("get")) {
+                        return method.invoke(ds, args); // return the first one succeeding
+                    }
+                } catch (final InvocationTargetException ite) {
+                    ex++;
+                    if (ex == delegates.size()) { // all failed so throw the exception
+                        throw ite.getCause();
+                    }
+                }
+            }
+
+            return null;
+        }
     }
 }