Created
July 7, 2014 18:07
-
-
Save gissuebot/03f0a701bfd0f8a414de to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 259, comment 0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: src/com/google/inject/jndi/GuiceInitialContextFactory.java | |
=================================================================== | |
--- src/com/google/inject/jndi/GuiceInitialContextFactory.java Thu Oct 09 12:20:56 BST 2008 | |
+++ src/com/google/inject/jndi/GuiceInitialContextFactory.java Thu Oct 09 12:20:56 BST 2008 | |
@@ -0,0 +1,136 @@ | |
+/** | |
+ * Copyright (C) 2006 Google Inc. | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.common.collect.Lists; | |
+import com.google.inject.AbstractModule; | |
+import com.google.inject.Binding; | |
+import com.google.inject.Guice; | |
+import com.google.inject.Injector; | |
+import com.google.inject.Module; | |
+import com.google.inject.jndi.internal.JndiContext; | |
+import com.google.inject.jndi.internal.Classes; | |
+import com.google.inject.name.Names; | |
+import java.util.Hashtable; | |
+import java.util.List; | |
+import java.util.Map; | |
+import java.util.Properties; | |
+import java.util.Set; | |
+import java.util.StringTokenizer; | |
+import java.util.Map.Entry; | |
+import javax.naming.Context; | |
+import javax.naming.NamingException; | |
+import javax.naming.spi.InitialContextFactory; | |
+ | |
+/** | |
+ * A factory of the Guice JNDI provider which creates an injector from all the available modules | |
+ * specified in the space separated {@link #MODULE_CLASS_NAMES} property. | |
+ * | |
+ * For more details of how this JNDI provider works see | |
+ * <a href="http://code.google.com/p/camel-extra/wiki/GuiceJndi">the wiki documentation</a> | |
+ * | |
+ * @version $Revision: 656978 $ | |
+ */ | |
+public class GuiceInitialContextFactory implements InitialContextFactory { | |
+ public static final String MODULE_CLASS_NAMES = "com.google.inject.modules"; | |
+ public static final String NAME_PREFIX = "com.google.inject.jndi/"; | |
+ | |
+ /** | |
+ * Creates a new context with the given environment. | |
+ * | |
+ * @param environment the environment, must not be <tt>null</tt> | |
+ * @return the created context. | |
+ * @throws NamingException is thrown if creation failed. | |
+ */ | |
+ public Context getInitialContext(final Hashtable environment) throws NamingException { | |
+ try { | |
+ List<Module> modules = Lists.newArrayList(); | |
+ | |
+ // lets bind the properties | |
+ modules.add(new AbstractModule() { | |
+ protected void configure() { | |
+ Names.bindProperties(binder(), environment); | |
+ } | |
+ }); | |
+ | |
+ Object moduleValue = environment.get(MODULE_CLASS_NAMES); | |
+ if (moduleValue instanceof String) { | |
+ String names = (String) moduleValue; | |
+ StringTokenizer iter = new StringTokenizer(names); | |
+ while (iter.hasMoreTokens()) { | |
+ String moduleName = iter.nextToken(); | |
+ Module module = loadModule(moduleName); | |
+ if (module != null) { | |
+ modules.add(module); | |
+ } | |
+ } | |
+ } | |
+ Injector injector = Guice.createInjector(modules); | |
+ Context context = null; | |
+ Binding<Context> binding = null; | |
+ try { | |
+ binding = injector.getBinding(Context.class); | |
+ } | |
+ catch (Exception e) { | |
+ // ignore as there might not be a binding | |
+ } | |
+ if (binding != null) { | |
+ context = binding.getProvider().get(); | |
+ } | |
+ if (context == null) { | |
+ context = new JndiContext(environment); | |
+ } | |
+ Properties jndiNames = createJndiNamesProperties(environment); | |
+ JndiIntegration.bindInjectorAndBindings(context, injector, jndiNames); | |
+ return context; | |
+ } | |
+ catch (NamingException e) { | |
+ throw e; | |
+ } | |
+ catch (Exception e) { | |
+ NamingException exception = new NamingException(e.getMessage()); | |
+ exception.initCause(e); | |
+ throw exception; | |
+ } | |
+ } | |
+ | |
+ /** | |
+ * Creates a properties object containing all of the values whose keys start with | |
+ * {@link #NAME_PREFIX} with the prefix being removed on the key | |
+ * @return a properties object | |
+ */ | |
+ private Properties createJndiNamesProperties(Hashtable environment) { | |
+ Set<Map.Entry> set = environment.entrySet(); | |
+ Properties answer = new Properties(); | |
+ for (Entry entry : set) { | |
+ String key = entry.getKey().toString(); | |
+ if (key.startsWith(NAME_PREFIX)) { | |
+ String name = key.substring(NAME_PREFIX.length()); | |
+ Object value = entry.getValue(); | |
+ answer.put(name, value); | |
+ } | |
+ } | |
+ return answer; | |
+ } | |
+ | |
+ private Module loadModule(String moduleName) | |
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException { | |
+ Class<?> type = Classes.loadClass(moduleName, GuiceInitialContextFactory.class.getClassLoader()); | |
+ return (Module) type.newInstance(); | |
+ } | |
+ | |
+} | |
Index: test/com/google/inject/jndi/AnotherBean.java | |
=================================================================== | |
--- test/com/google/inject/jndi/AnotherBean.java Tue Oct 07 18:27:03 BST 2008 | |
+++ test/com/google/inject/jndi/AnotherBean.java Tue Oct 07 18:27:03 BST 2008 | |
@@ -0,0 +1,36 @@ | |
+/** | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class AnotherBean { | |
+ private final String name; | |
+ | |
+ public AnotherBean(String name) { | |
+ this.name = name; | |
+ } | |
+ | |
+ public String getName() { | |
+ return name; | |
+ } | |
+ | |
+ @Override public String toString() { | |
+ return "AnotherBean[" + name + "]"; | |
+ } | |
+} | |
Index: test/com/google/inject/jndi/JndiProviderTest.java | |
=================================================================== | |
--- test/com/google/inject/jndi/JndiProviderTest.java Thu Oct 09 12:11:27 BST 2008 | |
+++ test/com/google/inject/jndi/JndiProviderTest.java Thu Oct 09 12:11:27 BST 2008 | |
@@ -0,0 +1,85 @@ | |
+/** | |
+ * Copyright (C) 2006 Google Inc. | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.Injector; | |
+import java.io.InputStream; | |
+import java.util.Hashtable; | |
+import java.util.Properties; | |
+import javax.naming.Binding; | |
+import javax.naming.InitialContext; | |
+import javax.naming.NamingEnumeration; | |
+import javax.naming.NamingException; | |
+import junit.framework.TestCase; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class JndiProviderTest extends TestCase { | |
+ protected static final boolean verbose = false; | |
+ | |
+ public void testJndiProvider() throws Exception { | |
+ InputStream in = getClass().getResourceAsStream("jndi-example.properties"); | |
+ assertNotNull("Cannot find jndi-example.properties on the classpath!", in); | |
+ | |
+ Properties properties = new Properties(); | |
+ properties.load(in); | |
+ | |
+ InitialContext context = new InitialContext(new Hashtable(properties)); | |
+ | |
+ if (verbose) { | |
+ NamingEnumeration<Binding> iter = context.listBindings(""); | |
+ while (iter.hasMore()) { | |
+ Binding binding = iter.next(); | |
+ System.out.println(" " + binding.getName() + " -> " + binding.getObject()); | |
+ } | |
+ } | |
+ | |
+ MyBean foo = assertLookup(context, "foo", MyBean.class); | |
+ assertEquals("foo.name", "Foo", foo.getName()); | |
+ | |
+ MyBean blah = assertLookup(context, "blah", MyBean.class); | |
+ assertEquals("blah.name", "Blah", blah.getName()); | |
+ | |
+ // lets check that Cheese has not been instantiated yet | |
+ assertEquals("Cheese instance count", 0, Cheese.instanceCount); | |
+ Cheese cheese = assertLookup(context, "cheese", Cheese.class); | |
+ assertEquals("cheese.type", "Edam", cheese.getType()); | |
+ assertEquals("Cheese instance count", 1, Cheese.instanceCount); | |
+ | |
+ SomeBean someBean = assertLookup(context, "com.google.inject.jndi.SomeBean", SomeBean.class); | |
+ assertEquals("someBean.name", "James", someBean.getName()); | |
+ | |
+ // lets test we can find the injector with the default name | |
+ Injector injector = (Injector) context.lookup("com.google.inject.Injector"); | |
+ assertNotNull("Injector should not be null", injector); | |
+ | |
+ // lets try using the custom name defined in the properties file | |
+ injector = (Injector) context.lookup("myInjector"); | |
+ assertNotNull("Injector should not be null", injector); | |
+ } | |
+ | |
+ protected <T> T assertLookup(InitialContext context, String name, Class<T> type) | |
+ throws NamingException { | |
+ Object value = context.lookup(name); | |
+ if (verbose) { | |
+ System.out.println(name + " = " + value); | |
+ } | |
+ assertNotNull("Should have an entry for '" + name + "' in JNDI", value); | |
+ assertTrue("Should be an instanceof " + type.getName(), type.isInstance(value)); | |
+ return type.cast(value); | |
+ } | |
+ | |
+} | |
Index: test/com/google/inject/jndi/Cheese.java | |
=================================================================== | |
--- test/com/google/inject/jndi/Cheese.java Thu Oct 09 10:58:42 BST 2008 | |
+++ test/com/google/inject/jndi/Cheese.java Thu Oct 09 10:58:42 BST 2008 | |
@@ -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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.Inject; | |
+import com.google.inject.name.Named; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+@JndiBind("cheese") | |
+public class Cheese { | |
+ public static int instanceCount = 0; | |
+ | |
+ private final String type; | |
+ | |
+ @Inject | |
+ public Cheese(@Named("cheese.type") String type) { | |
+ this.type = type; | |
+ ++instanceCount; | |
+ } | |
+ | |
+ public String getType() { | |
+ return type; | |
+ } | |
+ | |
+ @Override public String toString() { | |
+ return "Cheese[" + type + "]"; | |
+ | |
+ } | |
+} | |
Index: src/com/google/inject/jndi/internal/JndiContext.java | |
=================================================================== | |
--- src/com/google/inject/jndi/internal/JndiContext.java Thu Oct 09 10:56:41 BST 2008 | |
+++ src/com/google/inject/jndi/internal/JndiContext.java Thu Oct 09 10:56:41 BST 2008 | |
@@ -0,0 +1,426 @@ | |
+/** | |
+ * 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 com.google.inject.jndi.internal; | |
+ | |
+import com.google.inject.Provider; | |
+import java.io.Serializable; | |
+import java.util.HashMap; | |
+import java.util.Hashtable; | |
+import java.util.Iterator; | |
+import java.util.Map; | |
+import javax.naming.Binding; | |
+import javax.naming.CompositeName; | |
+import javax.naming.Context; | |
+import javax.naming.LinkRef; | |
+import javax.naming.Name; | |
+import javax.naming.NameClassPair; | |
+import javax.naming.NameNotFoundException; | |
+import javax.naming.NameParser; | |
+import javax.naming.NamingEnumeration; | |
+import javax.naming.NamingException; | |
+import javax.naming.NotContextException; | |
+import javax.naming.OperationNotSupportedException; | |
+import javax.naming.Reference; | |
+import javax.naming.spi.NamingManager; | |
+ | |
+/** | |
+ * A default JNDI context | |
+ * | |
+ * @version $Revision:$ | |
+ */ | |
+public class JndiContext implements Context, Serializable { | |
+ public static final String SEPARATOR = "/"; | |
+ protected static final NameParser NAME_PARSER = new NameParser() { | |
+ public Name parse(String name) throws NamingException { | |
+ return new CompositeName(name); | |
+ } | |
+ }; | |
+ private static final long serialVersionUID = -5754338187296859149L; | |
+ | |
+ private final Hashtable environment; // environment for this context | |
+ private final Map bindings; // bindings at my level | |
+ private final Map treeBindings; // all bindings under me | |
+ private boolean frozen; | |
+ private String nameInNamespace = ""; | |
+ | |
+ public JndiContext() throws Exception { | |
+ this(new Hashtable(), new HashMap()); | |
+ } | |
+ | |
+ public JndiContext(Hashtable environment) { | |
+ this(environment, new HashMap()); | |
+ } | |
+ | |
+ public JndiContext(Hashtable environment, Map bindings) { | |
+ if (environment == null) { | |
+ this.environment = new Hashtable(); | |
+ } | |
+ else { | |
+ this.environment = new Hashtable(environment); | |
+ } | |
+ this.bindings = bindings; | |
+ treeBindings = new HashMap(); | |
+ } | |
+ | |
+ public JndiContext(Hashtable environment, Map bindings, String nameInNamespace) { | |
+ this(environment, bindings); | |
+ this.nameInNamespace = nameInNamespace; | |
+ } | |
+ | |
+ protected JndiContext(JndiContext clone, Hashtable env) { | |
+ this.bindings = clone.bindings; | |
+ this.treeBindings = clone.treeBindings; | |
+ this.environment = new Hashtable(env); | |
+ } | |
+ | |
+ protected JndiContext(JndiContext clone, Hashtable env, String nameInNamespace) { | |
+ this(clone, env); | |
+ this.nameInNamespace = nameInNamespace; | |
+ } | |
+ | |
+ public void freeze() { | |
+ frozen = true; | |
+ } | |
+ | |
+ boolean isFrozen() { | |
+ return frozen; | |
+ } | |
+ | |
+ /** | |
+ * internalBind is intended for use only during setup or possibly by suitably synchronized | |
+ * superclasses. It binds every possible lookup into a map in each context. To do this, each | |
+ * context strips off one name segment and if necessary creates a new context for it. Then it asks | |
+ * that context to bind the remaining name. It returns a map containing all the bindings from the | |
+ * next context, plus the context it just created (if it in fact created it). (the names are | |
+ * suitably extended by the segment originally lopped off). | |
+ */ | |
+ protected Map internalBind(String name, Object value) throws NamingException { | |
+/* | |
+ // lets wrap the value in a Provider | |
+ final Object originalValue = value; | |
+ value = new Provider() { | |
+ public Object get() { | |
+ return originalValue; | |
+ } | |
+ }; | |
+*/ | |
+ assert name != null && name.length() > 0; | |
+ assert !frozen; | |
+ | |
+ Map newBindings = new HashMap(); | |
+ int pos = name.indexOf('/'); | |
+ if (pos == -1) { | |
+ if (treeBindings.put(name, value) != null) { | |
+ throw new NamingException("Something already bound at " + name); | |
+ } | |
+ bindings.put(name, value); | |
+ newBindings.put(name, value); | |
+ } | |
+ else { | |
+ String segment = name.substring(0, pos); | |
+ assert segment != null; | |
+ assert !segment.equals(""); | |
+ Object o = treeBindings.get(segment); | |
+ if (o == null) { | |
+ o = newContext(); | |
+ treeBindings.put(segment, o); | |
+ bindings.put(segment, o); | |
+ newBindings.put(segment, o); | |
+ } | |
+ else if (!(o instanceof JndiContext)) { | |
+ throw new NamingException("Something already bound where a subcontext should go"); | |
+ } | |
+ JndiContext defaultContext = (JndiContext) o; | |
+ String remainder = name.substring(pos + 1); | |
+ Map subBindings = defaultContext.internalBind(remainder, value); | |
+ for (Iterator iterator = subBindings.entrySet().iterator(); iterator.hasNext();) { | |
+ Map.Entry entry = (Map.Entry) iterator.next(); | |
+ String subName = segment + "/" + (String) entry.getKey(); | |
+ Object bound = entry.getValue(); | |
+ treeBindings.put(subName, bound); | |
+ newBindings.put(subName, bound); | |
+ } | |
+ } | |
+ return newBindings; | |
+ } | |
+ | |
+ protected JndiContext newContext() { | |
+ try { | |
+ return new JndiContext(); | |
+ } | |
+ catch (Exception e) { | |
+ throw new IllegalArgumentException(e); | |
+ } | |
+ } | |
+ | |
+ public Object addToEnvironment(String propName, Object propVal) throws NamingException { | |
+ return environment.put(propName, propVal); | |
+ } | |
+ | |
+ public Hashtable getEnvironment() throws NamingException { | |
+ return (Hashtable) environment.clone(); | |
+ } | |
+ | |
+ public Object removeFromEnvironment(String propName) throws NamingException { | |
+ return environment.remove(propName); | |
+ } | |
+ | |
+ public Object lookup(String name) throws NamingException { | |
+ if (name.length() == 0) { | |
+ return this; | |
+ } | |
+ Object result = treeBindings.get(name); | |
+ if (result == null) { | |
+ result = bindings.get(name); | |
+ } | |
+ if (result == null) { | |
+ int pos = name.indexOf(':'); | |
+ if (pos > 0) { | |
+ String scheme = name.substring(0, pos); | |
+ Context ctx = NamingManager.getURLContext(scheme, environment); | |
+ if (ctx == null) { | |
+ throw new NamingException("scheme " + scheme + " not recognized"); | |
+ } | |
+ return ctx.lookup(name); | |
+ } | |
+ else { | |
+ // Split out the first name of the path | |
+ // and look for it in the bindings map. | |
+ CompositeName path = new CompositeName(name); | |
+ | |
+ if (path.size() == 0) { | |
+ return this; | |
+ } | |
+ else { | |
+ String first = path.get(0); | |
+ Object value = bindings.get(first); | |
+ if (value == null) { | |
+ throw new NameNotFoundException(name); | |
+ } | |
+ else if (value instanceof Context && path.size() > 1) { | |
+ Context subContext = (Context) value; | |
+ value = subContext.lookup(path.getSuffix(1)); | |
+ } | |
+ return value; | |
+ } | |
+ } | |
+ } | |
+ if (result instanceof Provider) { | |
+ Provider provider = (Provider) result; | |
+ result = provider.get(); | |
+ } | |
+ if (result instanceof LinkRef) { | |
+ LinkRef ref = (LinkRef) result; | |
+ result = lookup(ref.getLinkName()); | |
+ } | |
+ if (result instanceof Reference) { | |
+ try { | |
+ result = NamingManager.getObjectInstance(result, null, null, this.environment); | |
+ } | |
+ catch (NamingException e) { | |
+ throw e; | |
+ } | |
+ catch (Exception e) { | |
+ throw (NamingException) new NamingException("could not look up : " + name).initCause(e); | |
+ } | |
+ } | |
+ if (result instanceof JndiContext) { | |
+ String prefix = getNameInNamespace(); | |
+ if (prefix.length() > 0) { | |
+ prefix = prefix + SEPARATOR; | |
+ } | |
+ result = new JndiContext((JndiContext) result, environment, prefix + name); | |
+ } | |
+ return result; | |
+ } | |
+ | |
+ public Object lookup(Name name) throws NamingException { | |
+ return lookup(name.toString()); | |
+ } | |
+ | |
+ public Object lookupLink(String name) throws NamingException { | |
+ return lookup(name); | |
+ } | |
+ | |
+ public Name composeName(Name name, Name prefix) throws NamingException { | |
+ Name result = (Name) prefix.clone(); | |
+ result.addAll(name); | |
+ return result; | |
+ } | |
+ | |
+ public String composeName(String name, String prefix) throws NamingException { | |
+ CompositeName result = new CompositeName(prefix); | |
+ result.addAll(new CompositeName(name)); | |
+ return result.toString(); | |
+ } | |
+ | |
+ public NamingEnumeration list(String name) throws NamingException { | |
+ Object o = lookup(name); | |
+ if (o == this) { | |
+ return new ListEnumeration(); | |
+ } | |
+ else if (o instanceof Context) { | |
+ return ((Context) o).list(""); | |
+ } | |
+ else { | |
+ throw new NotContextException(); | |
+ } | |
+ } | |
+ | |
+ public NamingEnumeration listBindings(String name) throws NamingException { | |
+ Object o = lookup(name); | |
+ if (o == this) { | |
+ return new ListBindingEnumeration(); | |
+ } | |
+ else if (o instanceof Context) { | |
+ return ((Context) o).listBindings(""); | |
+ } | |
+ else { | |
+ throw new NotContextException(); | |
+ } | |
+ } | |
+ | |
+ public Object lookupLink(Name name) throws NamingException { | |
+ return lookupLink(name.toString()); | |
+ } | |
+ | |
+ public NamingEnumeration list(Name name) throws NamingException { | |
+ return list(name.toString()); | |
+ } | |
+ | |
+ public NamingEnumeration listBindings(Name name) throws NamingException { | |
+ return listBindings(name.toString()); | |
+ } | |
+ | |
+ public void bind(Name name, Object value) throws NamingException { | |
+ bind(name.toString(), value); | |
+ } | |
+ | |
+ public void bind(String name, Object value) throws NamingException { | |
+ if (isFrozen()) { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ else { | |
+ internalBind(name, value); | |
+ } | |
+ } | |
+ | |
+ public void close() throws NamingException { | |
+ // ignore | |
+ } | |
+ | |
+ public Context createSubcontext(Name name) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public Context createSubcontext(String name) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public void destroySubcontext(Name name) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public void destroySubcontext(String name) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public String getNameInNamespace() throws NamingException { | |
+ return nameInNamespace; | |
+ } | |
+ | |
+ public NameParser getNameParser(Name name) throws NamingException { | |
+ return NAME_PARSER; | |
+ } | |
+ | |
+ public NameParser getNameParser(String name) throws NamingException { | |
+ return NAME_PARSER; | |
+ } | |
+ | |
+ public void rebind(Name name, Object value) throws NamingException { | |
+ bind(name, value); | |
+ } | |
+ | |
+ public void rebind(String name, Object value) throws NamingException { | |
+ bind(name, value); | |
+ } | |
+ | |
+ public void rename(Name oldName, Name newName) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public void rename(String oldName, String newName) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public void unbind(Name name) throws NamingException { | |
+ throw new OperationNotSupportedException(); | |
+ } | |
+ | |
+ public void unbind(String name) throws NamingException { | |
+ bindings.remove(name); | |
+ treeBindings.remove(name); | |
+ } | |
+ | |
+ private abstract class LocalNamingEnumeration implements NamingEnumeration { | |
+ private Iterator i = bindings.entrySet().iterator(); | |
+ | |
+ public boolean hasMore() throws NamingException { | |
+ return i.hasNext(); | |
+ } | |
+ | |
+ public boolean hasMoreElements() { | |
+ return i.hasNext(); | |
+ } | |
+ | |
+ protected Map.Entry getNext() { | |
+ return (Map.Entry) i.next(); | |
+ } | |
+ | |
+ public void close() throws NamingException { | |
+ } | |
+ } | |
+ | |
+ private class ListEnumeration extends LocalNamingEnumeration { | |
+ ListEnumeration() { | |
+ } | |
+ | |
+ public Object next() throws NamingException { | |
+ return nextElement(); | |
+ } | |
+ | |
+ public Object nextElement() { | |
+ Map.Entry entry = getNext(); | |
+ return new NameClassPair((String) entry.getKey(), entry.getValue().getClass().getName()); | |
+ } | |
+ } | |
+ | |
+ private class ListBindingEnumeration extends LocalNamingEnumeration { | |
+ ListBindingEnumeration() { | |
+ } | |
+ | |
+ public Object next() throws NamingException { | |
+ return nextElement(); | |
+ } | |
+ | |
+ public Object nextElement() { | |
+ Map.Entry entry = getNext(); | |
+ return new Binding((String) entry.getKey(), entry.getValue()); | |
+ } | |
+ } | |
+} | |
Index: test/com/google/inject/jndi/jndi-example.properties | |
=================================================================== | |
--- test/com/google/inject/jndi/jndi-example.properties Thu Oct 09 12:11:12 BST 2008 | |
+++ test/com/google/inject/jndi/jndi-example.properties Thu Oct 09 12:11:12 BST 2008 | |
@@ -0,0 +1,22 @@ | |
+# Guice JNDI provider | |
+java.naming.factory.initial = com.google.inject.jndi.GuiceInitialContextFactory | |
+ | |
+# list of guice modules to boot up (space separated) | |
+com.google.inject.modules = com.google.inject.jndi.ExampleModule | |
+ | |
+# guice injection properties | |
+#---------------------------------------------------------------------------- | |
+cheese.type = Edam | |
+someBean.name = James | |
+ | |
+# JNDI entries to create from bindings in the Guice Injector | |
+#---------------------------------------------------------------------------- | |
+# | |
+# use the following naming convention to expose Guice resources in JNDI | |
+# | |
+# com.google.inject.jndi/someJndiName = someClassName | |
+# | |
+com.google.inject.jndi/myInjector = com.google.inject.Injector | |
+ | |
+ | |
+ | |
Index: test/com/google/inject/jndi/MyBean.java | |
=================================================================== | |
--- test/com/google/inject/jndi/MyBean.java Tue Oct 07 18:27:03 BST 2008 | |
+++ test/com/google/inject/jndi/MyBean.java Tue Oct 07 18:27:03 BST 2008 | |
@@ -0,0 +1,44 @@ | |
+/** | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.Inject; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class MyBean { | |
+ @Inject String name; | |
+ @Inject AnotherBean another; | |
+ | |
+ public MyBean(AnotherBean another, String name) { | |
+ this.another = another; | |
+ this.name = name; | |
+ } | |
+ | |
+ public AnotherBean getAnother() { | |
+ return another; | |
+ } | |
+ | |
+ public String getName() { | |
+ return name; | |
+ } | |
+ | |
+ @Override public String toString() { | |
+ return "MyBean[" + name + "; another=" + another + "]"; | |
+ } | |
+} | |
Index: test/com/google/inject/jndi/SomeBean.java | |
=================================================================== | |
--- test/com/google/inject/jndi/SomeBean.java Wed Oct 08 17:49:32 BST 2008 | |
+++ test/com/google/inject/jndi/SomeBean.java Wed Oct 08 17:49:32 BST 2008 | |
@@ -0,0 +1,36 @@ | |
+/** | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.Inject; | |
+import com.google.inject.name.Named; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class SomeBean { | |
+ @Inject @Named("someBean.name") | |
+ String name; | |
+ | |
+ public String getName() { | |
+ return name; | |
+ } | |
+ | |
+ @Override public String toString() { | |
+ return "SomeBean[" + name + "]"; | |
+ } | |
+} | |
\ No newline at end of file | |
Index: test/com/google/inject/jndi/ExampleModule.java | |
=================================================================== | |
--- test/com/google/inject/jndi/ExampleModule.java Wed Oct 08 17:50:10 BST 2008 | |
+++ test/com/google/inject/jndi/ExampleModule.java Wed Oct 08 17:50:10 BST 2008 | |
@@ -0,0 +1,42 @@ | |
+/** | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.AbstractModule; | |
+import com.google.inject.Provides; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class ExampleModule extends AbstractModule { | |
+ protected void configure() { | |
+ bind(Cheese.class); | |
+ bind(SomeBean.class); | |
+ } | |
+ | |
+ @Provides | |
+ @JndiBind("blah") | |
+ public MyBean blah() { | |
+ return new MyBean(new AnotherBean("Blah.another"), "Blah"); | |
+ } | |
+ | |
+ @Provides | |
+ @JndiBind("foo") | |
+ public MyBean foo() { | |
+ return new MyBean(new AnotherBean("Foo.another"), "Foo"); | |
+ } | |
+} | |
Index: src/com/google/inject/jndi/internal/Classes.java | |
=================================================================== | |
--- src/com/google/inject/jndi/internal/Classes.java Thu Oct 09 12:11:12 BST 2008 | |
+++ src/com/google/inject/jndi/internal/Classes.java Thu Oct 09 12:11:12 BST 2008 | |
@@ -0,0 +1,50 @@ | |
+/** | |
+ * | |
+ * 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 com.google.inject.jndi.internal; | |
+ | |
+/** @version $Revision: 1.1 $ */ | |
+public class Classes { | |
+ | |
+ /** | |
+ * Attempts to load the class of the given name from the thread context class loader first | |
+ * then the given class loader second | |
+ * | |
+ * @param name the name of the class | |
+ * @param loader the class loader to use if the thread context class loader cannot find the class | |
+ * @return the class loaded | |
+ * @throws ClassNotFoundException if the class could not be found | |
+ */ | |
+ public static Class<?> loadClass(String name, ClassLoader loader) throws ClassNotFoundException { | |
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); | |
+ if (contextClassLoader != null) { | |
+ try { | |
+ return contextClassLoader.loadClass(name); | |
+ } | |
+ catch (ClassNotFoundException e) { | |
+ try { | |
+ return loader.loadClass(name); | |
+ } | |
+ catch (ClassNotFoundException e1) { | |
+ throw e; | |
+ } | |
+ } | |
+ } | |
+ return null; | |
+ } | |
+} | |
Index: src/com/google/inject/jndi/JndiIntegration.java | |
=================================================================== | |
--- src/com/google/inject/jndi/JndiIntegration.java (revision 627) | |
+++ src/com/google/inject/jndi/JndiIntegration.java Thu Oct 09 12:20:56 BST 2008 | |
@@ -16,24 +16,33 @@ | |
package com.google.inject.jndi; | |
+import com.google.inject.Binding; | |
import com.google.inject.Inject; | |
+import com.google.inject.Injector; | |
+import com.google.inject.Key; | |
import com.google.inject.Provider; | |
+import com.google.inject.jndi.internal.Classes; | |
+import com.google.inject.name.Named; | |
+import java.lang.annotation.Annotation; | |
+import java.lang.reflect.Type; | |
+import java.util.Map.Entry; | |
+import java.util.Properties; | |
+import java.util.Set; | |
import javax.naming.Context; | |
import javax.naming.NamingException; | |
/** | |
- * Integrates Guice with JNDI. Requires a binding to | |
- * {@link javax.naming.Context}. | |
+ * Integrates Guice with JNDI. Requires a binding to {@link javax.naming.Context}. | |
* | |
* @author crazybob@google.com (Bob Lee) | |
*/ | |
public class JndiIntegration { | |
- private JndiIntegration() {} | |
+ private JndiIntegration() { | |
+ } | |
/** | |
- * Creates a provider which looks up objects in JNDI using the given name. | |
- * Example usage: | |
+ * Creates a provider which looks up objects in JNDI using the given name. Example usage: | |
* | |
* <pre> | |
* bind(DataSource.class).toProvider(fromJndi(DataSource.class, "java:...")); | |
@@ -43,6 +52,87 @@ | |
return new JndiProvider<T>(type, name); | |
} | |
+ /** | |
+ * Binds the given injector and its binding providers to the given JNDI context using | |
+ * <a href="http://code.google.com/p/camel-extra/wiki/GuiceJndi">this mapping mechanism</a>. | |
+ * | |
+ * This will expose all of the bindings providers to JNDI along with | |
+ * any bindings which are annotated with {@link JndiBind} or | |
+ * {@link @Named} to the given JNDI context. | |
+ * | |
+ * @param context the context to export objects to | |
+ * @param injector the injector used to find the bindings | |
+ */ | |
+ public static void bindInjectorAndBindings(Context context, Injector injector, | |
+ Properties jndiNames) throws NamingException { | |
+ // lets find all the exported bindings | |
+ Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings().entrySet(); | |
+ for (Entry<Key<?>, com.google.inject.Binding<?>> entry : entries) { | |
+ Key<?> key = entry.getKey(); | |
+ Binding<?> binding = entry.getValue(); | |
+ Annotation annotation = key.getAnnotation(); | |
+ Type type = key.getTypeLiteral().getType(); | |
+ JndiBind jndiBind = null; | |
+ if (type instanceof Class) { | |
+ Class<?> aClass = (Class<?>) type; | |
+ jndiBind = aClass.getAnnotation(JndiBind.class); | |
+ } | |
+ | |
+ if (annotation instanceof JndiBind) { | |
+ jndiBind = (JndiBind) annotation; | |
+ } | |
+ String jndiName = null; | |
+ if (jndiBind != null) { | |
+ jndiName = jndiBind.value(); | |
+ } | |
+ if (jndiName == null) { | |
+ if (annotation instanceof Named) { | |
+ Named named = (Named) annotation; | |
+ String name = named.value(); | |
+ jndiName = type.toString() + "/" + name; | |
+ } | |
+ else if (type instanceof Class<?>) { | |
+ Class<?> aClass = (Class<?>) type; | |
+ if (annotation == null) { | |
+ jndiName = aClass.getName(); | |
+ } | |
+ else { | |
+ jndiName = aClass.getName() + annotation; | |
+ } | |
+ } | |
+ } | |
+ if (jndiName != null) { | |
+ Object value = binding.getProvider(); | |
+ if (value != null) { | |
+ context.bind(jndiName, value); | |
+ } | |
+ } | |
+ } | |
+ | |
+ for (Entry entry : jndiNames.entrySet()) { | |
+ String jndiName = entry.getKey().toString(); | |
+ String expression = entry.getValue().toString(); | |
+ | |
+ Provider provider = getProviderForExpression(injector, expression); | |
+ if (provider != null) { | |
+ context.bind(jndiName, provider); | |
+ } | |
+ } | |
+ } | |
+ | |
+ private static Provider getProviderForExpression(Injector injector, String expression) { | |
+ // TODO we could support more complex expressions | |
+ // like 'className/name' to map to @Named annotations | |
+ // or even 'className@annotationType(values) etc | |
+ try { | |
+ Class<?> type = Classes.loadClass(expression, JndiIntegration.class.getClassLoader()); | |
+ return injector.getProvider(type); | |
+ } | |
+ catch (ClassNotFoundException e) { | |
+ return null; | |
+ } | |
+ } | |
+ | |
static class JndiProvider<T> implements Provider<T> { | |
@Inject Context context; | |
Index: src/com/google/inject/jndi/JndiBind.java | |
=================================================================== | |
--- src/com/google/inject/jndi/JndiBind.java Wed Oct 08 17:27:17 BST 2008 | |
+++ src/com/google/inject/jndi/JndiBind.java Wed Oct 08 17:27:17 BST 2008 | |
@@ -0,0 +1,46 @@ | |
+/** | |
+ * Copyright (C) 2008 Google Inc. | |
+ * | |
+ * 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 com.google.inject.jndi; | |
+ | |
+import com.google.inject.BindingAnnotation; | |
+import java.lang.annotation.Documented; | |
+import static java.lang.annotation.ElementType.CONSTRUCTOR; | |
+import static java.lang.annotation.ElementType.FIELD; | |
+import static java.lang.annotation.ElementType.METHOD; | |
+import static java.lang.annotation.ElementType.TYPE; | |
+import java.lang.annotation.Retention; | |
+import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
+import java.lang.annotation.Target; | |
+ | |
+/** | |
+ * Marks an injection point so that it is bound to the current JNDI context with some JNDI name | |
+ * | |
+ * @version $Revision: 1.1 $ */ | |
+@Target({ METHOD, CONSTRUCTOR, FIELD, TYPE}) | |
+@Retention(RUNTIME) | |
+@Documented | |
+@BindingAnnotation | |
+public @interface JndiBind { | |
+ | |
+ /** | |
+ * The JNDI name to bind the value to | |
+ * | |
+ * @return the name to bind the value to in JNDI | |
+ */ | |
+ public String value(); | |
+} | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment