Return-Path: Delivered-To: apmail-geronimo-scm-archive@www.apache.org Received: (qmail 44138 invoked from network); 29 Sep 2006 20:15:30 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 29 Sep 2006 20:15:30 -0000 Received: (qmail 51543 invoked by uid 500); 29 Sep 2006 20:15:30 -0000 Delivered-To: apmail-geronimo-scm-archive@geronimo.apache.org Received: (qmail 51401 invoked by uid 500); 29 Sep 2006 20:15:29 -0000 Mailing-List: contact scm-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list scm@geronimo.apache.org Received: (qmail 51370 invoked by uid 99); 29 Sep 2006 20:15:29 -0000 Received: from idunn.apache.osuosl.org (HELO idunn.apache.osuosl.org) (140.211.166.84) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 29 Sep 2006 13:15:29 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=5.0 tests=ALL_TRUSTED,NO_REAL_NAME Received: from [140.211.166.113] ([140.211.166.113:61000] helo=eris.apache.org) by idunn.apache.osuosl.org (ecelerity 2.1.1.8 r(12930)) with ESMTP id 9F/BC-13110-BBE7D154 for ; Fri, 29 Sep 2006 13:15:07 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id D255B1A984A; Fri, 29 Sep 2006 13:14:00 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r451419 - in /geronimo/sandbox/plugins/global-jndi: ./ src/java/org/apache/geronimo/gjndi/ src/java/org/apache/geronimo/gjndi/binding/ src/test/org/apache/geronimo/gjndi/binding/ Date: Fri, 29 Sep 2006 20:14:00 -0000 To: scm@geronimo.apache.org From: dain@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20060929201400.D255B1A984A@eris.apache.org> X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: dain Date: Fri Sep 29 13:13:59 2006 New Revision: 451419 URL: http://svn.apache.org/viewvc?view=rev&rev=451419 Log: Added ResourceBindings and EjbBindings. Added support for duplicate bindings to the same name - basically we create a wating queue and when the current binding unregisters the next in the queue gets registered. Fixed several bugs in cleanup code. Added: geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/EjbBindings.java geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ResourceBindings.java geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ResourceBindingsTest.java Modified: geronimo/sandbox/plugins/global-jndi/pom.xml geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/KernelContextGBean.java Modified: geronimo/sandbox/plugins/global-jndi/pom.xml URL: http://svn.apache.org/viewvc/geronimo/sandbox/plugins/global-jndi/pom.xml?view=diff&rev=451419&r1=451418&r2=451419 ============================================================================== --- geronimo/sandbox/plugins/global-jndi/pom.xml (original) +++ geronimo/sandbox/plugins/global-jndi/pom.xml Fri Sep 29 13:13:59 2006 @@ -36,7 +36,7 @@ org.apache.xbean xbean-naming - COL-SNAPSHOT + 2.7-SNAPSHOT org.apache.geronimo.modules @@ -47,6 +47,17 @@ backport-util-concurrent backport-util-concurrent + + org.apache.geronimo.modules + geronimo-connector + ${pom.version} + true + + + + + + Modified: geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/KernelContextGBean.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/KernelContextGBean.java?view=diff&rev=451419&r1=451418&r2=451419 ============================================================================== --- geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/KernelContextGBean.java (original) +++ geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/KernelContextGBean.java Fri Sep 29 13:13:59 2006 @@ -34,7 +34,9 @@ import javax.naming.NamingException; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -81,12 +83,10 @@ private synchronized void destroy() { kernel.getLifecycleMonitor().removeLifecycleListener(listener); - for (Iterator iterator = bindingsByAbstractName.values().iterator(); iterator.hasNext();) { - try { - Name name = (Name) iterator.next(); - removeDeepBinding(name, true); - } catch (NamingException ignored) { - } + Set abstractNames = new HashSet(bindingsByAbstractName.keySet()); + for (Iterator iterator = abstractNames.iterator(); iterator.hasNext();) { + AbstractName abstractName = (AbstractName) iterator.next(); + removeBinding(abstractName); } bindingsByAbstractName.clear(); } @@ -119,53 +119,128 @@ /** * Binds the specified gbean. This method uses createBindingName and preprocessValue before binding the object. + * * @param abstractName the abstract name of the gbean to bind * @throws NamingException if an error occurs during binding */ protected synchronized void addBinding(AbstractName abstractName) throws NamingException { + if (bindingsByAbstractName.containsKey(abstractName)) { + // previously bound + return; + } + // get the gbean - Object value = null; + Object instance = null; try { - value = kernel.getGBean(abstractName); + instance = kernel.getGBean(abstractName); } catch (GBeanNotFoundException e) { throw new NamingException("GBean not found: " + abstractName); } - // generate a name for this binding - Name name = createBindingName(abstractName, value); - if (name == null) return; - - // give sub classes a chance to preprocess the value - value = preprocessVaue(abstractName, name, value); - if (value == null) return; + // create the bindings for this object + Map bindings = createBindings(abstractName, instance); + if (bindings == null || bindings.isEmpty()) { + return; + } // bind the value - - addDeepBinding(name, value, true, true); + for (Iterator iterator = bindings.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + Name name = (Name) entry.getKey(); + Object value = entry.getValue(); + addBinding(abstractName, name, value); + } // remember where we bound this value - bindingsByAbstractName.put(abstractName, name); + bindingsByAbstractName.put(abstractName, bindings.keySet()); + } + + private Map bindingsByName = new HashMap(); + + private synchronized void addBinding(AbstractName abstractName, Name name, Object value) throws NamingException { + LinkedHashMap bindings = (LinkedHashMap) bindingsByName.get(name); + if (bindings == null) { + addDeepBinding(name, value, true, true); + + bindings = new LinkedHashMap(); + bindings.put(abstractName, value); + bindingsByName.put(name, bindings); + } else { + bindings.put(abstractName, value); + } } /** * Unbinds the specified gbean. + * * @param abstractName the abstract name of the gbean to unbind */ protected synchronized void removeBinding(AbstractName abstractName) { - Name name = (Name) bindingsByAbstractName.remove(abstractName); - if (name != null) { - try { - removeDeepBinding(name, true); - } catch (NamingException ignored) { + Set bindingNames = (Set) bindingsByAbstractName.remove(abstractName); + if (bindingNames == null) return; + + for (Iterator iterator = bindingNames.iterator(); iterator.hasNext();) { + Name name = (Name) iterator.next(); + + LinkedHashMap bindings = (LinkedHashMap) bindingsByName.get(name); + if (bindings == null) continue; + + if (first(bindings).getKey().equals(abstractName)) { + bindings.remove(abstractName); + Map.Entry newEntry = first(bindings); + if (newEntry != null) { + Object newAbstractName = newEntry.getValue(); + Object newValue = newEntry.getValue(); + try { + addDeepBinding(name, newValue, true, true); + } catch (NamingException e) { + boolean logged = false; + try { + removeDeepBinding(name, true); + } catch (NamingException e1) { + logged = true; + log.error("Unable to remove binding " + name + " to " + abstractName, e); + } + if (!logged) log.error("Unable to rebind binding " + name + " to " + newAbstractName); + } + } else { + bindingsByName.remove(name); + try { + removeDeepBinding(name, true, true); + } catch (NamingException e) { + log.error("Unable to remove binding " + name + " to " + abstractName, e); + } + } + } else { + bindings.remove(abstractName); } } } + private static Map.Entry first(LinkedHashMap map) { + if (map.isEmpty()) return null; + return (Map.Entry) map.entrySet().iterator().next(); + } + + protected Map createBindings(AbstractName abstractName, Object value) throws NamingException { + // generate a name for this binding + Name name = createBindingName(abstractName, value); + if (name == null) return null; + + // give sub classes a chance to preprocess the value + value = preprocessVaue(abstractName, name, value); + if (value == null) return null; + + Map bindings = Collections.singletonMap(name, value); + return bindings; + } + /** * Create a name under which we will bind the specified gbean with the specified value. * By default, this method simply returns the "name" element of the abstract name + * * @param abstractName the abstract name of the gbean to bind - * @param value the gbean instance + * @param value the gbean instance * @return the name under which the gbean should be bound */ protected Name createBindingName(AbstractName abstractName, Object value) throws NamingException { @@ -176,9 +251,10 @@ /** * Preprocess the value before it is bound. This is usefult for wrapping values with reference objects. * By default, this method simply return the value. + * * @param abstractName the abstract name of the gbean to bind - * @param name the name under which the gbean will be bound - * @param value the gbean instance + * @param name the name under which the gbean will be bound + * @param value the gbean instance * @return the value to bind */ protected Object preprocessVaue(AbstractName abstractName, Name name, Object value) throws NamingException { Added: geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/EjbBindings.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/EjbBindings.java?view=auto&rev=451419 ============================================================================== --- geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/EjbBindings.java (added) +++ geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/EjbBindings.java Fri Sep 29 13:13:59 2006 @@ -0,0 +1,108 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed 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.geronimo.gjndi.binding; + +import org.apache.geronimo.gbean.AbstractName; +import org.apache.geronimo.gbean.AbstractNameQuery; +import org.apache.geronimo.gbean.GBeanInfo; +import org.apache.geronimo.gbean.GBeanInfoBuilder; +import org.apache.geronimo.gbean.GBeanLifecycle; +import org.apache.geronimo.gjndi.KernelContextGBean; +import org.apache.geronimo.kernel.Kernel; +import org.openejb.RpcEjbDeployment; + +import javax.ejb.EJBHome; +import javax.ejb.EJBLocalHome; +import javax.naming.Name; +import javax.naming.NameParser; +import javax.naming.NamingException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * @version $Rev$ $Date$ + */ +public class EjbBindings extends KernelContextGBean implements GBeanLifecycle { + private final Name homeContext; + private final Name localHomeContext; + + public EjbBindings(Kernel kernel, String homeContext, String localHomeContext) throws NamingException { + super("", new AbstractNameQuery(null, Collections.EMPTY_MAP, RpcEjbDeployment.class.getName()), kernel); + NameParser parser = getNameParser(); + this.homeContext = parser.parse(homeContext); + this.localHomeContext = parser.parse(localHomeContext); + } + + protected Map createBindings(AbstractName abstractName, Object value) throws NamingException { + if (value instanceof RpcEjbDeployment) { + RpcEjbDeployment deployment = (RpcEjbDeployment) value; + + NameParser parser = getNameParser(); + Name ejbName = parser.parse(deployment.getEjbName()); + + Map bindings = new LinkedHashMap(); + + // create home binding + if (deployment.getProxyInfo().getHomeInterface() != null) { + EJBHome ejbHome = deployment.getEjbHome(); + + String[] jndiNames = deployment.getJndiNames(); + for (int i = 0; i < jndiNames.length; i++) { + String jndiName = jndiNames[i]; + Name name = parser.parse(jndiName); + bindings.put(name, ejbHome); + } + + Name homeName = ((Name) homeContext.clone()); + homeName.addAll(ejbName); + bindings.put(homeName, ejbHome); + } + + // create local home binding + if (deployment.getProxyInfo().getLocalHomeInterface() != null) { + EJBLocalHome ejbLocalHome = deployment.getEjbLocalHome(); + + String[] localJndiNames = deployment.getLocalJndiNames(); + for (int i = 0; i < localJndiNames.length; i++) { + String localJndiName = localJndiNames[i]; + Name name = parser.parse(localJndiName); + bindings.put(name, ejbLocalHome); + } + + Name localHomeName = ((Name) localHomeContext.clone()); + localHomeName.addAll(ejbName); + bindings.put(localHomeName, ejbLocalHome); + } + + return bindings; + } + throw new NamingException("value is not a RpcEjbDeployment: abstractName=" + abstractName + " valueType=" + value.getClass().getName()); + } + + public static final GBeanInfo GBEAN_INFO; + + public static GBeanInfo getGBeanInfo() { + return EjbBindings.GBEAN_INFO; + } + + static { + GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(EjbBindings.class, "EjbBindings"); + builder.setConstructor(new String[]{"kernel", "homeContext", "localHomeContext"}); + GBEAN_INFO = builder.getBeanInfo(); + } +} Added: geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ResourceBindings.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ResourceBindings.java?view=auto&rev=451419 ============================================================================== --- geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ResourceBindings.java (added) +++ geronimo/sandbox/plugins/global-jndi/src/java/org/apache/geronimo/gjndi/binding/ResourceBindings.java Fri Sep 29 13:13:59 2006 @@ -0,0 +1,80 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed 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.geronimo.gjndi.binding; + +import org.apache.geronimo.connector.outbound.ConnectionFactorySource; +import org.apache.geronimo.gbean.AbstractName; +import org.apache.geronimo.gbean.AbstractNameQuery; +import org.apache.geronimo.gbean.GBeanInfo; +import org.apache.geronimo.gbean.GBeanInfoBuilder; +import org.apache.geronimo.gbean.GBeanLifecycle; +import org.apache.geronimo.gjndi.KernelContextGBean; +import org.apache.geronimo.kernel.Kernel; + +import javax.naming.Name; +import javax.naming.NameParser; +import javax.naming.NamingException; +import java.util.Collections; +import java.util.Map; + +/** + * @version $Rev$ $Date$ + */ +public class ResourceBindings extends KernelContextGBean implements GBeanLifecycle { + private final Class type; + + public ResourceBindings(Kernel kernel, String nameInNamespace, Class type) throws NamingException { + super(nameInNamespace, new AbstractNameQuery(null, Collections.EMPTY_MAP, ConnectionFactorySource.class.getName()), kernel); + this.type = type; + } + + public ResourceBindings(Kernel kernel, String nameInNamespace, ClassLoader classLoader, String type) throws NamingException, ClassNotFoundException { + super(nameInNamespace, new AbstractNameQuery(null, Collections.EMPTY_MAP, ConnectionFactorySource.class.getName()), kernel); + this.type = classLoader.loadClass(type); + } + + protected Map createBindings(AbstractName abstractName, Object value) throws NamingException { + if (value instanceof ConnectionFactorySource) { + ConnectionFactorySource connectionFactorySource = (ConnectionFactorySource) value; + + String name = (String) abstractName.getName().get("name"); + if (name == null) return null; + + Object resource = connectionFactorySource.$getResource(); + if (!type.isInstance(resource)) return null; + + NameParser parser = getNameParser(); + Name jndiName = parser.parse(name); + + return Collections.singletonMap(jndiName, resource); + } + throw new NamingException("value is not a ConnectionFactorySource: abstractName=" + abstractName + " valueType=" + value.getClass().getName()); + } + + public static final GBeanInfo GBEAN_INFO; + + public static GBeanInfo getGBeanInfo() { + return ResourceBindings.GBEAN_INFO; + } + + static { + GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(ResourceBindings.class, "JdbcBindings"); + builder.addAttribute("type", String.class, true); + builder.setConstructor(new String[]{"kernel", "nameInNamespace", "classLoader", "type"}); + GBEAN_INFO = builder.getBeanInfo(); + } +} Added: geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ResourceBindingsTest.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ResourceBindingsTest.java?view=auto&rev=451419 ============================================================================== --- geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ResourceBindingsTest.java (added) +++ geronimo/sandbox/plugins/global-jndi/src/test/org/apache/geronimo/gjndi/binding/ResourceBindingsTest.java Fri Sep 29 13:13:59 2006 @@ -0,0 +1,290 @@ +/** + * + * Copyright 2006 The Apache Software Foundation + * + * Licensed 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.geronimo.gjndi.binding; + +import org.apache.geronimo.connector.outbound.ConnectionFactorySource; +import org.apache.geronimo.gbean.AbstractName; +import org.apache.geronimo.gbean.GBeanData; +import org.apache.geronimo.gbean.GBeanInfo; +import org.apache.geronimo.gbean.GBeanInfoBuilder; +import org.apache.geronimo.gbean.GBeanLifecycle; +import org.apache.geronimo.gjndi.AbstractContextTest; +import org.apache.geronimo.gjndi.GlobalContextGBean; +import org.apache.geronimo.kernel.Kernel; +import org.apache.geronimo.kernel.KernelFactory; +import org.apache.geronimo.kernel.config.ConfigurationData; +import org.apache.geronimo.kernel.config.ConfigurationUtil; +import org.apache.geronimo.kernel.config.EditableConfigurationManager; +import org.apache.geronimo.kernel.config.EditableKernelConfigurationManager; +import org.apache.geronimo.kernel.repository.Artifact; +import org.apache.geronimo.kernel.repository.DefaultArtifactManager; +import org.apache.geronimo.kernel.repository.DefaultArtifactResolver; +import org.apache.geronimo.naming.java.RootContext; +import org.apache.xbean.naming.context.ImmutableContext; +import org.apache.xbean.naming.global.GlobalContextManager; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.sql.DataSource; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +/** + * @version $Rev$ $Date$ + */ +public class ResourceBindingsTest extends AbstractContextTest { + private Kernel kernel; + private EditableConfigurationManager configurationManager; + private DataSource ds1 = new MockDataSource(); + private DataSource ds2 = new MockDataSource(); + +// private GBeanInfo immutableContextGBeanInfo; + private Hashtable contextEnv; + private Map globalBindings; + private AbstractName jdbcBindingsName; + private AbstractName ds1Name; + + public void testBasics() throws Exception { + InitialContext ctx = new InitialContext(contextEnv); + assertEq(globalBindings, ctx); + + // + // stop test ds1 + // + kernel.stopGBean(ds1Name); + globalBindings.remove("ds/ds1"); + assertEq(globalBindings, ctx); + + // + // stop ds context + // + kernel.stopGBean(jdbcBindingsName); + + assertEq(Collections.EMPTY_MAP, ctx); + + + // + // restart ds context + // + kernel.startGBean(jdbcBindingsName); + + assertEq(globalBindings, ctx); + + // + // restart test context + // + kernel.startGBean(ds1Name); + globalBindings.put("ds/ds1", ds1); + assertEq(globalBindings, ctx); + } + + public void testDupeName() throws Exception { + Artifact dupeArtifactName = new Artifact("test2", "test2", "", "car"); + ConfigurationData dupeConfigData = new ConfigurationData(dupeArtifactName, kernel.getNaming()); + + // dupe ds1 + DataSource dupeDs1 = new MockDataSource(); + Map nameProps = new HashMap(); + nameProps.put("name", "ds1"); + nameProps.put("foo", "bar"); + AbstractName dupeDs1Name = new AbstractName(dupeArtifactName, nameProps); + GBeanData ds1GBean = new GBeanData(dupeDs1Name, MockConnectionFactorySource.GBEAN_INFO); + dupeConfigData.addGBean(ds1GBean); + ds1GBean.setAttribute("resource", dupeDs1); + + // start the config + configurationManager.loadConfiguration(dupeConfigData); + configurationManager.startConfiguration(dupeConfigData.getId()); + + InitialContext ctx = new InitialContext(contextEnv); + assertEq(globalBindings, ctx); + + // + // stop test ds1 + // + kernel.stopGBean(ds1Name); + globalBindings.put("ds/ds1", dupeDs1); + assertEq(globalBindings, ctx); + + // + // restart test context + // + kernel.startGBean(ds1Name); + assertEq(globalBindings, ctx); + + // + // stop test ds1Dupe + // + kernel.stopGBean(dupeDs1Name); + globalBindings.put("ds/ds1", ds1); + assertEq(globalBindings, ctx); + + // + // stop test ds1 + // + kernel.stopGBean(ds1Name); + globalBindings.remove("ds/ds1"); + assertEq(globalBindings, ctx); + } + + protected Map getNestedBindings(Map globalBindings, String nestedPath) { + HashMap nestedBindings = new HashMap(); + for (Iterator iterator = globalBindings.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String globalName = (String) entry.getKey(); + Object value = entry.getValue(); + + if (globalName.startsWith(nestedPath)) { + String nestedName = globalName.substring(nestedPath.length()); + nestedBindings.put(nestedName, value); + } + } + return nestedBindings; + } + + protected void setUp() throws Exception { + super.setUp(); + + kernel = KernelFactory.newInstance().createKernel("test"); + kernel.boot(); + + ConfigurationData bootstrap = new ConfigurationData(new Artifact("bootstrap", "bootstrap", "", "car"), kernel.getNaming()); + + GBeanData artifactManagerData = bootstrap.addGBean("ArtifactManager", DefaultArtifactManager.GBEAN_INFO); + + GBeanData artifactResolverData = bootstrap.addGBean("ArtifactResolver", DefaultArtifactResolver.GBEAN_INFO); + artifactResolverData.setReferencePattern("ArtifactManager", artifactManagerData.getAbstractName()); + + GBeanData configurationManagerData = bootstrap.addGBean("ConfigurationManager", EditableKernelConfigurationManager.GBEAN_INFO); + configurationManagerData.setReferencePattern("ArtifactManager", artifactManagerData.getAbstractName()); + configurationManagerData.setReferencePattern("ArtifactResolver", artifactResolverData.getAbstractName()); + + ConfigurationUtil.loadBootstrapConfiguration(kernel, bootstrap, getClass().getClassLoader()); + + configurationManager = ConfigurationUtil.getEditableConfigurationManager(kernel); + + ConfigurationData configurationData = new ConfigurationData(new Artifact("test", "test", "", "car"), kernel.getNaming()); + configurationData.addGBean("GlobalContext", GlobalContextGBean.GBEAN_INFO); + + contextEnv = new Hashtable(); + contextEnv.put(Context.INITIAL_CONTEXT_FACTORY, GlobalContextManager.class.getName()); + + // global bindings + globalBindings = new HashMap(); + globalBindings.put("ds/ds1", ds1); + globalBindings.put("ds/ds2", ds2); + + Map javaCompBindings = getNestedBindings(globalBindings, "java:comp/"); + ImmutableContext javaCompContext = new ImmutableContext(javaCompBindings); + RootContext.setComponentContext(javaCompContext); + + // ds constext + GBeanData jdbcBindings = configurationData.addGBean("JdbcBindings", ResourceBindings.GBEAN_INFO); + jdbcBindingsName = jdbcBindings.getAbstractName(); + jdbcBindings.setAttribute("nameInNamespace", "ds"); + jdbcBindings.setAttribute("type", DataSource.class.getName()); + + // resources + GBeanData stringResource = configurationData.addGBean("StringResource", MockConnectionFactorySource.GBEAN_INFO); + stringResource.setAttribute("resource", "SomeString"); + + GBeanData ds1GBean = configurationData.addGBean("ds1", MockConnectionFactorySource.GBEAN_INFO); + ds1Name = ds1GBean.getAbstractName(); + ds1GBean.setAttribute("resource", ds1); + + GBeanData ds2GBean = configurationData.addGBean("ds2", MockConnectionFactorySource.GBEAN_INFO); + ds2GBean.setAttribute("resource", ds2); + + configurationManager.loadConfiguration(configurationData); + configurationManager.startConfiguration(configurationData.getId()); + + } + + protected void tearDown() throws Exception { + kernel.shutdown(); + super.tearDown(); + } + + public static class MockConnectionFactorySource implements ConnectionFactorySource, GBeanLifecycle { + private final Object resource; + private boolean running = false; + + public MockConnectionFactorySource(Object resource) { + this.resource = resource; + } + + public Object $getResource() { + if (!running) throw new IllegalStateException("not running"); + return resource; + } + + public void doStart() throws Exception { + running = true; + } + + public void doStop() throws Exception { + running = false; + } + + public void doFail() { + running = false; + } + + public static final GBeanInfo GBEAN_INFO; + + public static GBeanInfo getGBeanInfo() { + return GBEAN_INFO; + } + + static { + GBeanInfoBuilder builder = GBeanInfoBuilder.createStatic(MockConnectionFactorySource.class, "MockConnectionFactorySource"); + builder.addAttribute("resource", Object.class, true); + builder.setConstructor(new String[]{"resource"}); + GBEAN_INFO = builder.getBeanInfo(); + } + } + + public static class MockDataSource implements DataSource { + public Connection getConnection() throws SQLException { + return null; + } + + public Connection getConnection(String username, String password) throws SQLException { + return null; + } + + public PrintWriter getLogWriter() throws SQLException { + return null; + } + + public void setLogWriter(PrintWriter out) throws SQLException { + } + + public void setLoginTimeout(int seconds) throws SQLException { + } + + public int getLoginTimeout() throws SQLException { + return 0; + } + } +}