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 2011/07/24 19:50:41 UTC

svn commit: r1150445 - in /openejb/branches/openejb-3.2.x/container/openejb-core/src: main/java/org/apache/openejb/resource/jdbc/ main/resources/META-INF/org.apache.openejb.embedded/ main/resources/META-INF/org.apache.openejb/ test/java/org/apache/open...

Author: rmannibucau
Date: Sun Jul 24 17:50:40 2011
New Revision: 1150445

URL: http://svn.apache.org/viewvc?rev=1150445&view=rev
Log:
adding dynamlic data source to 3.2.x

Added:
    openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/AbstractRouter.java
    openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java
    openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/Router.java
    openejb/branches/openejb-3.2.x/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DynamicDataSourceTest.java
    openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/
    openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/service-jar.xml
Modified:
    openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
    openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml

Added: openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/AbstractRouter.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/AbstractRouter.java?rev=1150445&view=auto
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/AbstractRouter.java (added)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/AbstractRouter.java Sun Jul 24 17:50:40 2011
@@ -0,0 +1,45 @@
+/**
+ *
+ * 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.openejb.resource.jdbc;
+
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+/**
+ * @author Romain Manni-Bucau
+ */
+public abstract class AbstractRouter implements Router {
+    private static final String OPENEJB_RESOURCE = "openejb:Resource/";
+    private Context ctx;
+
+    public AbstractRouter() {
+        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+        ctx = containerSystem.getJNDIContext();
+    }
+
+    public Object getJndiResource(String name) throws NamingException {
+        return ctx.lookup(name);
+    }
+
+    public Object getOpenEJBResource(String name) throws NamingException {
+        return getJndiResource(OPENEJB_RESOURCE + name);
+    }
+}

Added: openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java?rev=1150445&view=auto
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java (added)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/RoutedDataSource.java Sun Jul 24 17:50:40 2011
@@ -0,0 +1,148 @@
+/**
+ *
+ * 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.openejb.resource.jdbc;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+
+public class RoutedDataSource implements DataSource {
+    private static final String OPENEJB_RESOURCE_PREFIX = "openejb:Resource/";
+
+    private Router delegate;
+
+    public RoutedDataSource() {
+        // no-op
+    }
+
+    public RoutedDataSource(String router) {
+        setRouter(router);
+    }
+
+    public void setRouter(String router) {
+        ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+
+        Object o = null;
+        Context ctx = containerSystem.getJNDIContext();
+        try {
+            o = ctx.lookup(OPENEJB_RESOURCE_PREFIX + router);
+
+        } catch (NamingException e) {
+            throw new IllegalArgumentException("Can't find router [" + router + "]", e);
+        }
+
+        if (o instanceof Router) {
+            delegate = (Router) o;
+
+        } else {
+            throw new IllegalArgumentException(o + " is not a router");
+        }
+    }
+
+    public PrintWriter getLogWriter() throws SQLException {
+        if (getTargetDataSource() == null) {
+            return null;
+        }
+        return getTargetDataSource().getLogWriter();
+    }
+
+    public void setLogWriter(PrintWriter out) throws SQLException {
+        if (getTargetDataSource() != null) {
+            getTargetDataSource().setLogWriter(out);
+        }
+    }
+
+    public void setLoginTimeout(int seconds) throws SQLException {
+        if (getTargetDataSource() != null) {
+            getTargetDataSource().setLoginTimeout(seconds);
+        }
+    }
+
+    public int getLoginTimeout() throws SQLException {
+        if (getTargetDataSource() == null) {
+            return -1;
+        }
+        return getTargetDataSource().getLoginTimeout();
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T unwrap(Class<T> iface) throws SQLException {
+        if (getTargetDataSource() == null) {
+            return null;
+        }
+        return (T) callByReflection(getTargetDataSource(), "unwrap",
+                new Class<?>[]{Class.class}, new Object[]{iface});
+    }
+
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        if (getTargetDataSource() == null) {
+            return false;
+        }
+        return (Boolean) callByReflection(getTargetDataSource(), "isWrapperFor",
+                new Class<?>[]{Class.class}, new Object[]{iface});
+    }
+
+    public Connection getConnection() throws SQLException {
+        return getTargetDataSource().getConnection();
+    }
+
+    public Connection getConnection(String username, String password)
+            throws SQLException {
+        return getTargetDataSource().getConnection(username, password);
+    }
+
+    public Router getDelegate() {
+        if (delegate == null) {
+            throw new IllegalStateException("a router has to be defined");
+        }
+        return delegate;
+    }
+
+    private DataSource getTargetDataSource() {
+        return getDelegate().getDataSource();
+    }
+
+    /**
+     * This method is used to avoir to fork two projects to implement
+     * datasource of the jre5 and jre6
+     *
+     * @param ds         the wrapped datasource
+     * @param mtdName    the method to call
+     * @param paramTypes the parameter type
+     * @param args       the arguments
+     * @return the return value of the method
+     */
+    private Object callByReflection(DataSource ds, String mtdName, Class<?>[] paramTypes, Object[] args) {
+        Method mtd;
+        try {
+            mtd = ds.getClass().getDeclaredMethod(mtdName, paramTypes);
+            return mtd.invoke(ds, args);
+
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+}

Added: openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/Router.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/Router.java?rev=1150445&view=auto
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/Router.java (added)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/Router.java Sun Jul 24 17:50:40 2011
@@ -0,0 +1,34 @@
+/**
+ *
+ * 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.openejb.resource.jdbc;
+
+import javax.sql.DataSource;
+
+/**
+ * The Router interface is responsible for providing the target data source to the ${@link RoutedDataSource}}.
+ *
+ * $Rev:$
+ */
+public interface Router {
+
+    /**
+     * Used by ${@link RoutedDataSource} to get the active data source.
+     * @return the data source to delegate to
+     */
+    DataSource getDataSource();
+}

Modified: openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml?rev=1150445&r1=1150444&r2=1150445&view=diff
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml (original)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml Sun Jul 24 17:50:40 2011
@@ -983,4 +983,13 @@
   </ServiceProvider>
 
 
+  <!--
+  # dynamic routing datasource
+  -->
+  <ServiceProvider
+          id="RoutedDataSource"
+          service="Resource" types="DataSource"
+          class-name="org.apache.openejb.resource.jdbc.RoutedDataSource">
+    Router
+  </ServiceProvider>
 </ServiceJar>

Modified: openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml?rev=1150445&r1=1150444&r2=1150445&view=diff
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml (original)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml Sun Jul 24 17:50:40 2011
@@ -987,4 +987,13 @@
   </ServiceProvider>
 
 
+  <!--
+  # dynamic routing datasource
+  -->
+  <ServiceProvider
+          id="RoutedDataSource"
+          service="Resource" types="DataSource"
+          class-name="org.apache.openejb.resource.jdbc.RoutedDataSource">
+    Router
+  </ServiceProvider>
 </ServiceJar>

Added: openejb/branches/openejb-3.2.x/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DynamicDataSourceTest.java
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DynamicDataSourceTest.java?rev=1150445&view=auto
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DynamicDataSourceTest.java (added)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/DynamicDataSourceTest.java Sun Jul 24 17:50:40 2011
@@ -0,0 +1,319 @@
+/*
+ * 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.openejb.resource.jdbc;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.ejb.Local;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.Id;
+import javax.persistence.PersistenceContext;
+import javax.sql.DataSource;
+
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.ResourceInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.client.LocalInitialContextFactory;
+import org.apache.openejb.config.AppModule;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.config.EjbModule;
+import org.apache.openejb.config.PersistenceModule;
+import org.apache.openejb.config.sys.Resource;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+import org.apache.openejb.jee.jpa.unit.Persistence;
+import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
+import org.apache.openejb.jee.jpa.unit.TransactionType;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.ContainerSystem;
+import org.junit.Test;
+
+public class DynamicDataSourceTest {
+
+    @Test
+    public void route() throws Exception {
+        System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, LocalInitialContextFactory.class.getName());
+
+        ConfigurationFactory config = new ConfigurationFactory();
+
+        Assembler assembler = new Assembler();
+        assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+        assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+        assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+        // resources
+        for (int i = 1; i <= 3; i++) {
+            String dbName = "database" + i;
+            Resource resourceDs = new Resource(dbName, "DataSource");
+            Properties p = resourceDs.getProperties();
+            p.put("JdbcDriver", "org.hsqldb.jdbcDriver");
+            p.put("JdbcUrl", "jdbc:hsqldb:mem:db" + i);
+            p.put("UserName", "sa");
+            p.put("Password", "");
+            p.put("JtaManaged", "true");
+            assembler.createResource(config.configureService(resourceDs, ResourceInfo.class));
+        }
+        Resource resourceRouter = new Resource("My Router", "org.apache.openejb.router.test.DynamicDataSourceTest$DeterminedRouter", "org.router:DeterminedRouter");
+        resourceRouter.getProperties().setProperty("DatasourceNames", "database1 database2 database3");
+        resourceRouter.getProperties().setProperty("DefaultDataSourceName", "database1");
+        assembler.createResource(config.configureService(resourceRouter, ResourceInfo.class));
+
+        Resource resourceRoutedDs = new Resource("Routed Datasource", "org.apache.openejb.resource.jdbc.Router", "RoutedDataSource");
+        resourceRoutedDs.getProperties().setProperty("Router", "My Router");
+        assembler.createResource(config.configureService(resourceRoutedDs, ResourceInfo.class));
+
+        // containers
+        StatelessSessionContainerInfo statelessContainerInfo = config.configureService(StatelessSessionContainerInfo.class);
+        assembler.createContainer(statelessContainerInfo);
+
+        EjbJar ejbJar = new EjbJar();
+        ejbJar.addEnterpriseBean(new StatelessBean(RoutedEJBBean.class));
+        ejbJar.addEnterpriseBean(new StatelessBean(UtilityBean.class));
+
+        EjbModule ejbModule = new EjbModule(ejbJar);
+
+        // Create an "ear"
+        AppModule appModule = new AppModule(ejbModule.getClassLoader(), "test-dynamic-data-source");
+        appModule.getEjbModules().add(ejbModule);
+
+        // Create a persistence-units
+        PersistenceUnit unit = new PersistenceUnit("router");
+        unit.addClass(Person.class);
+        unit.getProperties().put("openjpa.jdbc.SynchronizeMappings", "buildSchema");
+        unit.setTransactionType(TransactionType.JTA);
+        unit.setJtaDataSource("Routed Datasource");
+        appModule.getPersistenceModules().add(new PersistenceModule("root", new Persistence(unit)));
+        for (int i = 1; i <= 3; i++) {
+            PersistenceUnit u = new PersistenceUnit("db" + i);
+            u.addClass(Person.class);
+            u.getProperties().put("openjpa.jdbc.SynchronizeMappings", "buildSchema");
+            u.setTransactionType(TransactionType.JTA);
+            u.setJtaDataSource("database" + i);
+            appModule.getPersistenceModules().add(new PersistenceModule("root", new Persistence(u)));
+        }
+
+        assembler.createApplication(config.configureApplication(appModule));
+
+        // context
+        Context ctx = new InitialContext();
+
+        // running persist on all "routed" databases
+        final List<String> databases = new ArrayList<String>();
+        databases.add("database1");
+        databases.add("database2");
+        databases.add("database3");
+
+        // convinient bean to create tables for each persistence unit
+        Utility utility = (Utility) ctx.lookup("UtilityBeanLocal");
+        utility.initDatabase();
+
+        RoutedEJB ejb = (RoutedEJB) ctx.lookup("RoutedEJBBeanLocal");
+        for (int i = 0; i < 18; i++) {
+            String name = "record " + i;
+            String db = databases.get(i % 3);
+            ejb.persist(i, name, db);
+        }
+
+        // assert database records number using jdbc
+        for (int i = 1; i <= 3; i++) {
+            Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:db" + i, "sa", "");
+            Statement st = connection.createStatement();
+            ResultSet rs = st.executeQuery("select count(*) from \"DynamicDataSourceTest$Person\"");
+            rs.next();
+            assertEquals(6, rs.getInt(1));
+            st.close();
+            connection.close();
+        }
+    }
+
+    @Stateless
+    @Local(RoutedEJB.class)
+    public static class RoutedEJBBean implements RoutedEJB {
+        @PersistenceContext(unitName = "router")
+        private EntityManager em;
+
+        @javax.annotation.Resource(name = "My Router", type = DeterminedRouter.class)
+        private DeterminedRouter router;
+
+        public void persist(int id, String name, String ds) {
+            router.setDataSource(ds);
+            em.persist(new Person(id, name));
+        }
+
+    }
+
+    @Stateless
+    @Local(Utility.class)
+    public static class UtilityBean implements Utility {
+
+        @PersistenceContext(unitName = "db1")
+        private EntityManager em1;
+        @PersistenceContext(unitName = "db2")
+        private EntityManager em2;
+        @PersistenceContext(unitName = "db3")
+        private EntityManager em3;
+
+        @TransactionAttribute(TransactionAttributeType.SUPPORTS)
+        public void initDatabase() {
+            em1.find(Person.class, 0);
+            em2.find(Person.class, 0);
+            em3.find(Person.class, 0);
+        }
+    }
+
+    public static interface RoutedEJB {
+        void persist(int id, String name, String ds);
+    }
+
+    public static interface Utility {
+        void initDatabase();
+    }
+
+    @Entity
+    public static class Person {
+        @Id
+        private long id;
+        private String name;
+
+        public Person() {
+            // no-op
+        }
+
+        public Person(int i, String n) {
+            id = i;
+            name = n;
+        }
+
+        public long getId() {
+            return id;
+        }
+
+        public void setId(long id) {
+            this.id = id;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+
+    public static class DeterminedRouter implements Router {
+        private String dataSourceNames;
+        private String defaultDataSourceName;
+        private Map<String, DataSource> dataSources = null;
+        private ThreadLocal<DataSource> currentDataSource = new ThreadLocal<DataSource>();
+
+        /**
+         * @param datasourceList datasource resource name, separator is a space
+         */
+        public void setDataSourceNames(String datasourceList) {
+            dataSourceNames = datasourceList;
+        }
+
+        /**
+         * lookup datasource in openejb resources
+         */
+        private void init() {
+            dataSources = new ConcurrentHashMap<String, DataSource>();
+            for (String ds : dataSourceNames.split(" ")) {
+                ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
+
+                Object o = null;
+                Context ctx = containerSystem.getJNDIContext();
+                try {
+                    o = ctx.lookup("openejb:Resource/" + ds);
+                    if (o instanceof DataSource) {
+                        dataSources.put(ds, (DataSource) o);
+                    }
+                } catch (NamingException e) {
+                }
+            }
+        }
+
+        /**
+         * @return the user selected data source if it is set
+         *         or the default one
+         *  @throws IllegalArgumentException if the data source is not found
+         */
+        public DataSource getDataSource() {
+            // lazy init of routed datasources
+            if (dataSources == null) {
+                init();
+            }
+
+            // if no datasource is selected use the default one
+            if (currentDataSource.get() == null) {
+                if (dataSources.containsKey(defaultDataSourceName)) {
+                    return dataSources.get(defaultDataSourceName);
+
+                } else {
+                    throw new IllegalArgumentException("you have to specify at least one datasource");
+                }
+            }
+
+            // the developper set the datasource to use
+            return currentDataSource.get();
+        }
+
+        /**
+         *
+         * @param datasourceName data source name
+         */
+        public void setDataSource(String datasourceName) {
+            if (dataSources == null) {
+                init();
+            }
+            if (!dataSources.containsKey(datasourceName)) {
+                throw new IllegalArgumentException("data source called " + datasourceName + " can't be found.");
+            }
+            DataSource ds = dataSources.get(datasourceName);
+            currentDataSource.set(ds);
+        }
+
+        /**
+         * reset the data source
+         */
+        public void clear() {
+            currentDataSource.remove();
+        }
+
+        public void setDefaultDataSourceName(String name) {
+            this.defaultDataSourceName = name;
+        }
+    }
+}

Added: openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/service-jar.xml
URL: http://svn.apache.org/viewvc/openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/service-jar.xml?rev=1150445&view=auto
==============================================================================
--- openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/service-jar.xml (added)
+++ openejb/branches/openejb-3.2.x/container/openejb-core/src/test/resources/META-INF/org.router/service-jar.xml Sun Jul 24 17:50:40 2011
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+-->
+
+<!-- $Rev$ -->
+<ServiceJar>
+  <ServiceProvider id="DeterminedRouter" service="Resource"
+    type="org.apache.openejb.resource.jdbc.Router"
+    class-name="org.apache.openejb.resource.jdbc.DynamicDataSourceTest$DeterminedRouter">
+    DataSourceNames
+    DefaultDataSourceName
+  </ServiceProvider>
+</ServiceJar>