/components/camel-guice/src/main/java/org/apache/camel/guice/inject/Injectors.java
Java | 457 lines | 286 code | 34 blank | 137 comment | 58 complexity | 532608309008005bbc59c594aa1d1c5e MD5 | raw file
- /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.camel.guice.inject;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Field;
- import java.lang.reflect.Type;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import java.util.Set;
- import java.util.StringTokenizer;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Sets;
- import com.google.inject.AbstractModule;
- import com.google.inject.Binding;
- import com.google.inject.Guice;
- import com.google.inject.Injector;
- import com.google.inject.Key;
- import com.google.inject.Module;
- import com.google.inject.Provider;
- import com.google.inject.Scope;
- import com.google.inject.Singleton;
- import com.google.inject.TypeLiteral;
- import com.google.inject.internal.BindingImpl;
- import com.google.inject.internal.Scoping;
- import com.google.inject.matcher.Matcher;
- import com.google.inject.name.Names;
- import com.google.inject.util.Modules;
- import org.apache.camel.guice.jndi.GuiceInitialContextFactory;
- import org.apache.camel.guice.jndi.internal.Classes;
- import org.apache.camel.guice.support.CloseErrors;
- import org.apache.camel.guice.support.CloseFailedException;
- import org.apache.camel.guice.support.Closer;
- import org.apache.camel.guice.support.Closers;
- import org.apache.camel.guice.support.CompositeCloser;
- import org.apache.camel.guice.support.HasScopeAnnotation;
- import org.apache.camel.guice.support.internal.CloseErrorsImpl;
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public final class Injectors {
- public static final String MODULE_CLASS_NAMES = "org.guiceyfruit.modules";
- private Injectors() {
- //Helper class
- }
- /**
- * Creates an injector from the given properties, loading any modules define
- * by the {@link #MODULE_CLASS_NAMES} property value (space separated) along
- * with any other modules passed as an argument.
- *
- * @param environment
- * the properties used to create the injector
- * @param overridingModules
- * any modules which override the modules referenced in the
- * environment such as to provide the actual JNDI context
- */
- public static Injector createInjector(final Map environment,
- Module... overridingModules) throws ClassNotFoundException,
- IllegalAccessException, InstantiationException {
- 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.override(modules)
- .with(overridingModules));
- return injector;
- }
- /**
- * Returns an instance of the given type with the
- * {@link com.google.inject.name.Named} annotation value.
- *
- * This method allows you to switch this code
- * <code>injector.getInstance(Key.get(type, Names.named(name)));</code>
- *
- * to the more concise
- * <code>Injectors.getInstance(injector, type, name);</code>
- */
- public static <T> T getInstance(Injector injector, java.lang.Class<T> type,
- String name) {
- return injector.getInstance(Key.get(type, Names.named(name)));
- }
- /**
- * Returns a collection of all instances of the given base type
- *
- * @param baseClass
- * the base type of objects required
- * @param <T>
- * the base type
- * @return a set of objects returned from this injector
- */
- public static <T> Set<T> getInstancesOf(Injector injector,
- Class<T> baseClass) {
- Set<T> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && baseClass.isAssignableFrom(keyType)) {
- Binding<?> binding = entry.getValue();
- Object value = binding.getProvider().get();
- if (value != null) {
- T castValue = baseClass.cast(value);
- answer.add(castValue);
- }
- }
- }
- return answer;
- }
- /**
- * Returns a collection of all instances matching the given matcher
- *
- * @param matcher
- * matches the types to return instances
- * @return a set of objects returned from this injector
- */
- public static <T> Set<T> getInstancesOf(Injector injector,
- Matcher<Class> matcher) {
- Set<T> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && matcher.matches(keyType)) {
- Binding<?> binding = entry.getValue();
- Object value = binding.getProvider().get();
- answer.add((T) value);
- }
- }
- return answer;
- }
- /**
- * Returns a collection of all of the providers matching the given matcher
- *
- * @param matcher
- * matches the types to return instances
- * @return a set of objects returned from this injector
- */
- public static <T> Set<Provider<T>> getProvidersOf(Injector injector,
- Matcher<Class> matcher) {
- Set<Provider<T>> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && matcher.matches(keyType)) {
- Binding<?> binding = entry.getValue();
- answer.add((Provider<T>) binding.getProvider());
- }
- }
- return answer;
- }
- /**
- * Returns a collection of all providers of the given base type
- *
- * @param baseClass
- * the base type of objects required
- * @param <T>
- * the base type
- * @return a set of objects returned from this injector
- */
- public static <T> Set<Provider<T>> getProvidersOf(Injector injector,
- Class<T> baseClass) {
- Set<Provider<T>> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && baseClass.isAssignableFrom(keyType)) {
- Binding<?> binding = entry.getValue();
- answer.add((Provider<T>) binding.getProvider());
- }
- }
- return answer;
- }
- /** Returns true if a binding exists for the given matcher */
- public static boolean hasBinding(Injector injector, Matcher<Class> matcher) {
- return !getBindingsOf(injector, matcher).isEmpty();
- }
- /** Returns true if a binding exists for the given base class */
- public static boolean hasBinding(Injector injector, Class<?> baseClass) {
- return !getBindingsOf(injector, baseClass).isEmpty();
- }
- /** Returns true if a binding exists for the given key */
- public static boolean hasBinding(Injector injector, Key<?> key) {
- Binding<?> binding = getBinding(injector, key);
- return binding != null;
- }
- /**
- * Returns the binding for the given key or null if there is no such binding
- */
- public static Binding<?> getBinding(Injector injector, Key<?> key) {
- Map<Key<?>, Binding<?>> bindings = injector.getBindings();
- Binding<?> binding = bindings.get(key);
- return binding;
- }
- /**
- * Returns a collection of all of the bindings matching the given matcher
- *
- * @param matcher
- * matches the types to return instances
- * @return a set of objects returned from this injector
- */
- public static Set<Binding<?>> getBindingsOf(Injector injector,
- Matcher<Class> matcher) {
- Set<Binding<?>> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && matcher.matches(keyType)) {
- answer.add(entry.getValue());
- }
- }
- return answer;
- }
- /**
- * Returns a collection of all bindings of the given base type
- *
- * @param baseClass
- * the base type of objects required
- * @return a set of objects returned from this injector
- */
- public static Set<Binding<?>> getBindingsOf(Injector injector,
- Class<?> baseClass) {
- Set<Binding<?>> answer = Sets.newHashSet();
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Class<?> keyType = getKeyType(key);
- if (keyType != null && baseClass.isAssignableFrom(keyType)) {
- answer.add(entry.getValue());
- }
- }
- return answer;
- }
- /** Returns the key type of the given key */
- public static <T> Class<?> getKeyType(Key<?> key) {
- Class<?> keyType = null;
- TypeLiteral<?> typeLiteral = key.getTypeLiteral();
- Type type = typeLiteral.getType();
- if (type instanceof Class) {
- keyType = (Class<?>) type;
- }
- return keyType;
- }
- protected static Module loadModule(String moduleName)
- throws ClassNotFoundException, IllegalAccessException,
- InstantiationException {
- Class<?> type = Classes.loadClass(moduleName,
- GuiceInitialContextFactory.class.getClassLoader());
- return (Module) type.newInstance();
- }
- /*
- */
- /**
- * Closes the given scope on this injector
- *
- * @param injector
- * the injector on which to close objects
- * @param scopeAnnotation
- * the scope on which to close the objects
- * @throws CloseFailedException
- * the exceptions caused if closing an object fails
- */
- /*
- * public static void close(Injector injector, Annotation scopeAnnotation)
- * throws CloseFailedException { Key<PreDestroyer> key =
- * Key.get(PreDestroyer.class, scopeAnnotation); if (hasBinding(injector,
- * key)) { PreDestroyer destroyer = injector.getInstance(key);
- * destroyer.close(); } }
- */
- /**
- * Closes any singleton objects in the injector using the currently
- * registered {@link Closer} implementations
- */
- public static void close(Injector injector) throws CloseFailedException {
- close(injector, new CloseErrorsImpl(Injectors.class));
- }
- /**
- * Closes objects within the given scope using the currently registered
- * {@link Closer} implementations
- */
- public static void close(Injector injector, CloseErrors errors)
- throws CloseFailedException {
- close(injector, Singleton.class, errors);
- }
- /**
- * Closes objects within the given scope using the currently registered
- * {@link Closer} implementations
- */
- public static void close(Injector injector,
- Class<? extends Annotation> scopeAnnotationToClose)
- throws CloseFailedException {
- close(injector, scopeAnnotationToClose, new CloseErrorsImpl(
- Injectors.class));
- }
- /**
- * Closes objects within the given scope using the currently registered
- * {@link Closer} implementations
- */
- public static void close(Injector injector,
- Class<? extends Annotation> scopeAnnotationToClose,
- CloseErrors errors) throws CloseFailedException {
- Set<Closer> closers = getInstancesOf(injector, Closer.class);
- Closer closer = CompositeCloser.newInstance(closers);
- if (closer == null) {
- return;
- }
- Set<Entry<Key<?>, Binding<?>>> entries = injector.getBindings()
- .entrySet();
- for (Entry<Key<?>, Binding<?>> entry : entries) {
- Key<?> key = entry.getKey();
- Binding<?> binding = entry.getValue();
- closeBinding(key, binding, scopeAnnotationToClose, closer, errors);
- }
- tryCloseJitBindings(closer, injector, scopeAnnotationToClose, errors);
- errors.throwIfNecessary();
- }
- private static void tryCloseJitBindings(Closer closer, Injector injector,
- Class<? extends Annotation> scopeAnnotationToClose,
- CloseErrors errors) {
- Class<? extends Injector> type = injector.getClass();
- Field field;
- try {
- field = type.getDeclaredField("jitBindings");
- field.setAccessible(true);
- Object bindings = field.get(injector);
- if (bindings != null) {
- if (bindings instanceof Map) {
- Map<Key<?>, BindingImpl<?>> map = (Map<Key<?>, BindingImpl<?>>) bindings;
- Set<Entry<Key<?>, BindingImpl<?>>> entries = map.entrySet();
- for (Entry<Key<?>, BindingImpl<?>> entry : entries) {
- closeBinding(entry.getKey(), entry.getValue(),
- scopeAnnotationToClose, closer, errors);
- }
- }
- }
- } catch (NoSuchFieldException e) {
- // ignore - Guice has refactored so we can't access the jit bindings
- // System.out.println("No such field! " + e);
- } catch (IllegalAccessException e) {
- // ignore - Guice has refactored so we can't access the jit bindings
- // System.out.println("Failed to access field: " + field +
- // ". Reason: " + e);
- }
- }
- private static void closeBinding(Key<?> key, Binding<?> binding,
- Class<? extends Annotation> scopeAnnotationToClose, Closer closer,
- CloseErrors errors) {
- Provider<?> provider = binding.getProvider();
- Class<? extends Annotation> scopeAnnotation = getScopeAnnotation(binding);
- if ((scopeAnnotation != null)
- && scopeAnnotation.equals(scopeAnnotationToClose)) {
- Object value = provider.get();
- if (value != null) {
- Closers.close(key, value, closer, errors);
- }
- }
- }
- /**
- * Returns the scope annotation for the given binding or null if there is no
- * scope
- */
- public static Class<? extends Annotation> getScopeAnnotation(
- Binding<?> binding) {
- Class<? extends Annotation> scopeAnnotation = null;
- if (binding instanceof BindingImpl) {
- BindingImpl bindingImpl = (BindingImpl) binding;
- Scoping scoping = bindingImpl.getScoping();
- if (scoping != null) {
- scopeAnnotation = scoping.getScopeAnnotation();
- // TODO not sure why we need this hack???
- if (scopeAnnotation == null) {
- Scope scope = scoping.getScopeInstance();
- if (scope instanceof HasScopeAnnotation) {
- HasScopeAnnotation hasScopeAnnotation = (HasScopeAnnotation) scope;
- scopeAnnotation = hasScopeAnnotation
- .getScopeAnnotation();
- }
- if (scopeAnnotation == null
- && (scoping == Scoping.EAGER_SINGLETON
- || scoping == Scoping.SINGLETON_ANNOTATION || scoping == Scoping.SINGLETON_INSTANCE)) {
- scopeAnnotation = Singleton.class;
- }
- }
- }
- }
- return scopeAnnotation;
- }
- }