Skip to content

Instantly share code, notes, and snippets.

@gissuebot
Created July 7, 2014 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gissuebot/03f0a701bfd0f8a414de to your computer and use it in GitHub Desktop.
Save gissuebot/03f0a701bfd0f8a414de to your computer and use it in GitHub Desktop.
Migrated attachment for Guice issue 259, comment 0
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