From 7e59181e58c61158ac5a933a4624b605142e0fe5 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Fri, 8 Jul 2016 14:57:44 -0700 Subject: [PATCH] Internal: Remove child injectors from guice This change removes the ability for guice to have child injectors (and the entire concept of parent injectors) from our fork of guice. The methodology for removing was simple: I removed createChildInjector, and continued to remove methods and members that were unused until my head was spinning. The motivation for this change is to limit what our fork of guice gives us access to, so we don't regress and start adding back more complicated uses. --- .../elasticsearch/common/inject/Injector.java | 82 ----- .../common/inject/InjectorBuilder.java | 102 ------- .../common/inject/InjectorImpl.java | 73 +---- .../common/inject/InjectorShell.java | 12 +- .../common/inject/Injectors.java | 239 --------------- .../common/inject/ModulesBuilder.java | 14 +- .../common/inject/PrivateModule.java | 69 ----- .../assistedinject/FactoryProvider.java | 111 +------ .../assistedinject/FactoryProvider2.java | 283 ------------------ .../inject/assistedinject/Parameter.java | 28 -- .../inject/spi/ConvertedConstantBinding.java | 3 +- .../common/inject/spi/Element.java | 3 - .../common/inject/spi/Elements.java | 12 - .../common/inject/spi/LinkedKeyBinding.java | 3 +- .../common/inject/spi/ProviderBinding.java | 4 +- .../common/inject/spi/ProviderKeyBinding.java | 4 +- 16 files changed, 15 insertions(+), 1027 deletions(-) delete mode 100644 core/src/main/java/org/elasticsearch/common/inject/Injectors.java delete mode 100644 core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider2.java diff --git a/core/src/main/java/org/elasticsearch/common/inject/Injector.java b/core/src/main/java/org/elasticsearch/common/inject/Injector.java index bfc1fb42db3..2417e3b1411 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/Injector.java +++ b/core/src/main/java/org/elasticsearch/common/inject/Injector.java @@ -38,12 +38,6 @@ import java.util.Map; * An injector can also {@link #injectMembers(Object) inject the dependencies} of * already-constructed instances. This can be used to interoperate with objects created by other * frameworks or services. - *

- * Injectors can be {@link #createChildInjector(Iterable) hierarchical}. Child injectors inherit - * the configuration of their parent injectors, but the converse does not hold. - *

- * The injector's {@link #getBindings() internal bindings} are available for introspection. This - * enables tools and extensions to operate on an injector reflectively. * * @author crazybob@google.com (Bob Lee) * @author jessewilson@google.com (Jesse Wilson) @@ -87,41 +81,6 @@ public interface Injector { */ MembersInjector getMembersInjector(Class type); - /** - * Returns all explicit bindings. - *

- * The returned map does not include bindings inherited from a {@link #getParent() parent - * injector}, should one exist. The returned map is guaranteed to iterate (for example, with - * its {@link java.util.Map#entrySet()} iterator) in the order of insertion. In other words, - * the order in which bindings appear in user Modules. - *

- * This method is part of the Guice SPI and is intended for use by tools and extensions. - */ - Map, Binding> getBindings(); - - /** - * Returns the binding for the given injection key. This will be an explicit bindings if the key - * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will - * be created if necessary. - *

- * This method is part of the Guice SPI and is intended for use by tools and extensions. - * - * @throws ConfigurationException if this injector cannot find or create the binding. - */ - Binding getBinding(Key key); - - /** - * Returns the binding for the given type. This will be an explicit bindings if the injection key - * was bound explicitly by a module, or an implicit binding otherwise. The implicit binding will - * be created if necessary. - *

- * This method is part of the Guice SPI and is intended for use by tools and extensions. - * - * @throws ConfigurationException if this injector cannot find or create the binding. - * @since 2.0 - */ - Binding getBinding(Class type); - /** * Returns all explicit bindings for {@code type}. *

@@ -166,45 +125,4 @@ public interface Injector { * @throws ProvisionException if there was a runtime failure while providing an instance. */ T getInstance(Class type); - - /** - * Returns this injector's parent, or {@code null} if this is a top-level injector. - * - * @since 2.0 - */ - Injector getParent(); - - /** - * Returns a new injector that inherits all state from this injector. All bindings, scopes, - * interceptors and type converters are inherited -- they are visible to the child injector. - * Elements of the child injector are not visible to its parent. - *

- * Just-in-time bindings created for child injectors will be created in an ancestor injector - * whenever possible. This allows for scoped instances to be shared between injectors. Use - * explicit bindings to prevent bindings from being shared with the parent injector. - *

- * No key may be bound by both an injector and one of its ancestors. This includes just-in-time - * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each - * injector to itself. - * - * @since 2.0 - */ - Injector createChildInjector(Iterable modules); - - /** - * Returns a new injector that inherits all state from this injector. All bindings, scopes, - * interceptors and type converters are inherited -- they are visible to the child injector. - * Elements of the child injector are not visible to its parent. - *

- * Just-in-time bindings created for child injectors will be created in an ancestor injector - * whenever possible. This allows for scoped instances to be shared between injectors. Use - * explicit bindings to prevent bindings from being shared with the parent injector. - *

- * No key may be bound by both an injector and one of its ancestors. This includes just-in-time - * bindings. The lone exception is the key for {@code Injector.class}, which is bound by each - * injector to itself. - * - * @since 2.0 - */ - Injector createChildInjector(Module... modules); } diff --git a/core/src/main/java/org/elasticsearch/common/inject/InjectorBuilder.java b/core/src/main/java/org/elasticsearch/common/inject/InjectorBuilder.java index 2f9a3f1e7cb..93c92d480e2 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/InjectorBuilder.java +++ b/core/src/main/java/org/elasticsearch/common/inject/InjectorBuilder.java @@ -74,15 +74,6 @@ class InjectorBuilder { return this; } - /** - * Sets the parent of the injector to-be-constructed. As a side effect, this sets this injector's - * stage to the stage of {@code parent}. - */ - InjectorBuilder parentInjector(InjectorImpl parent) { - shellBuilder.parent(parent); - return stage(parent.getInstance(Stage.class)); - } - InjectorBuilder addModules(Iterable modules) { shellBuilder.addModules(modules); return this; @@ -102,11 +93,6 @@ class InjectorBuilder { initializeStatically(); } - // If we're in the tool stage, stop here. Don't eagerly inject or load anything. - if (stage == Stage.TOOL) { - return new ToolStageInjector(primaryInjector()); - } - injectDynamically(); return primaryInjector(); @@ -217,92 +203,4 @@ class InjectorBuilder { } } } - - /** - * {@link Injector} exposed to users in {@link Stage#TOOL}. - */ - static class ToolStageInjector implements Injector { - private final Injector delegateInjector; - - ToolStageInjector(Injector delegateInjector) { - this.delegateInjector = delegateInjector; - } - - @Override - public void injectMembers(Object o) { - throw new UnsupportedOperationException( - "Injector.injectMembers(Object) is not supported in Stage.TOOL"); - } - - @Override - public Map, Binding> getBindings() { - return this.delegateInjector.getBindings(); - } - - @Override - public Binding getBinding(Key key) { - return this.delegateInjector.getBinding(key); - } - - @Override - public Binding getBinding(Class type) { - return this.delegateInjector.getBinding(type); - } - - @Override - public List> findBindingsByType(TypeLiteral type) { - return this.delegateInjector.findBindingsByType(type); - } - - @Override - public Injector getParent() { - return delegateInjector.getParent(); - } - - @Override - public Injector createChildInjector(Iterable modules) { - return delegateInjector.createChildInjector(modules); - } - - @Override - public Injector createChildInjector(Module... modules) { - return delegateInjector.createChildInjector(modules); - } - - @Override - public Provider getProvider(Key key) { - throw new UnsupportedOperationException( - "Injector.getProvider(Key) is not supported in Stage.TOOL"); - } - - @Override - public Provider getProvider(Class type) { - throw new UnsupportedOperationException( - "Injector.getProvider(Class) is not supported in Stage.TOOL"); - } - - @Override - public MembersInjector getMembersInjector(TypeLiteral typeLiteral) { - throw new UnsupportedOperationException( - "Injector.getMembersInjector(TypeLiteral) is not supported in Stage.TOOL"); - } - - @Override - public MembersInjector getMembersInjector(Class type) { - throw new UnsupportedOperationException( - "Injector.getMembersInjector(Class) is not supported in Stage.TOOL"); - } - - @Override - public T getInstance(Key key) { - throw new UnsupportedOperationException( - "Injector.getInstance(Key) is not supported in Stage.TOOL"); - } - - @Override - public T getInstance(Class type) { - throw new UnsupportedOperationException( - "Injector.getInstance(Class) is not supported in Stage.TOOL"); - } - } } diff --git a/core/src/main/java/org/elasticsearch/common/inject/InjectorImpl.java b/core/src/main/java/org/elasticsearch/common/inject/InjectorImpl.java index ae4cd744dd0..817d52ea743 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/InjectorImpl.java +++ b/core/src/main/java/org/elasticsearch/common/inject/InjectorImpl.java @@ -64,7 +64,6 @@ import static org.elasticsearch.common.inject.internal.Annotations.findScopeAnno */ class InjectorImpl implements Injector, Lookups { final State state; - final InjectorImpl parent; boolean readOnly; BindingsMultimap bindingsMultimap = new BindingsMultimap(); final Initializer initializer; @@ -76,16 +75,10 @@ class InjectorImpl implements Injector, Lookups { Lookups lookups = new DeferredLookups(this); - InjectorImpl(@Nullable InjectorImpl parent, State state, Initializer initializer) { - this.parent = parent; + InjectorImpl(State state, Initializer initializer) { this.state = state; this.initializer = initializer; - - if (parent != null) { - localContext = parent.localContext; - } else { - localContext = new ThreadLocal<>(); - } + localContext = new ThreadLocal<>(); } /** @@ -106,21 +99,6 @@ class InjectorImpl implements Injector, Lookups { return bindingsMultimap.getAll(type); } - /** - * Returns the binding for {@code key} - */ - @Override - public BindingImpl getBinding(Key key) { - Errors errors = new Errors(key); - try { - BindingImpl result = getBindingOrThrow(key, errors); - errors.throwConfigurationExceptionIfErrorsExist(); - return result; - } catch (ErrorsException e) { - throw new ConfigurationException(errors.merge(e.getErrors()).getMessages()); - } - } - /** * Gets a binding implementation. First, it check to see if the parent has a binding. If the * parent has a binding and the binding is scoped, it will use that binding. Otherwise, this @@ -139,29 +117,6 @@ class InjectorImpl implements Injector, Lookups { return getJustInTimeBinding(key, errors); } - @Override - public Binding getBinding(Class type) { - return getBinding(Key.get(type)); - } - - @Override - public Injector getParent() { - return parent; - } - - @Override - public Injector createChildInjector(Iterable modules) { - return new InjectorBuilder() - .parentInjector(this) - .addModules(modules) - .build(); - } - - @Override - public Injector createChildInjector(Module... modules) { - return createChildInjector(Arrays.asList(modules)); - } - /** * Returns a just-in-time binding for {@code key}, creating it if necessary. * @@ -171,13 +126,11 @@ class InjectorImpl implements Injector, Lookups { throws ErrorsException { synchronized (state.lock()) { // first try to find a JIT binding that we've already created - for (InjectorImpl injector = this; injector != null; injector = injector.parent) { - @SuppressWarnings("unchecked") // we only store bindings that match their key - BindingImpl binding = (BindingImpl) injector.jitBindings.get(key); + @SuppressWarnings("unchecked") // we only store bindings that match their key + BindingImpl binding = (BindingImpl) jitBindings.get(key); - if (binding != null) { - return binding; - } + if (binding != null) { + return binding; } return createJustInTimeBindingRecursive(key, errors); @@ -600,14 +553,6 @@ class InjectorImpl implements Injector, Lookups { */ private BindingImpl createJustInTimeBindingRecursive(Key key, Errors errors) throws ErrorsException { - // ask the parent to create the JIT binding - if (parent != null && !parent.readOnly /* ES: don't check on parent if its read only, its already created all the bindings it can*/) { - try { - return parent.createJustInTimeBindingRecursive(key, new Errors()); - } catch (ErrorsException ignored) { - } - } - if (state.isBlacklisted(key)) { throw errors.childBindingAlreadySet(key).toException(); } @@ -686,12 +631,6 @@ class InjectorImpl implements Injector, Lookups { return getBindingOrThrow(key, errors).getInternalFactory(); } - // not test-covered - @Override - public Map, Binding> getBindings() { - return state.getExplicitBindingsThisLevel(); - } - private static class BindingsMultimap { final Map, List>> multimap = new HashMap<>(); diff --git a/core/src/main/java/org/elasticsearch/common/inject/InjectorShell.java b/core/src/main/java/org/elasticsearch/common/inject/InjectorShell.java index 7307fb4a6fe..793540aba73 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/InjectorShell.java +++ b/core/src/main/java/org/elasticsearch/common/inject/InjectorShell.java @@ -50,18 +50,12 @@ class InjectorShell { private final List elements; private final InjectorImpl injector; - private final PrivateElements privateElements; - private InjectorShell(Builder builder, List elements, InjectorImpl injector) { - this.privateElements = builder.privateElements; + private InjectorShell(List elements, InjectorImpl injector) { this.elements = elements; this.injector = injector; } - PrivateElements getPrivateElements() { - return privateElements; - } - InjectorImpl getInjector() { return injector; } @@ -134,7 +128,7 @@ class InjectorShell { throw new IllegalStateException("no state. Did you remember to lock() ?"); } - InjectorImpl injector = new InjectorImpl(parent, state, initializer); + InjectorImpl injector = new InjectorImpl(state, initializer); if (privateElements != null) { privateElements.initInjector(injector); } @@ -167,7 +161,7 @@ class InjectorShell { stopwatch.resetAndLog("Binding creation"); List injectorShells = new ArrayList<>(); - injectorShells.add(new InjectorShell(this, elements, injector)); + injectorShells.add(new InjectorShell(elements, injector)); // recursively build child shells PrivateElementProcessor processor = new PrivateElementProcessor(errors, stage); diff --git a/core/src/main/java/org/elasticsearch/common/inject/Injectors.java b/core/src/main/java/org/elasticsearch/common/inject/Injectors.java deleted file mode 100644 index 900d2588b52..00000000000 --- a/core/src/main/java/org/elasticsearch/common/inject/Injectors.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.common.inject; - -import org.elasticsearch.common.inject.matcher.Matcher; -import org.elasticsearch.common.inject.name.Names; -import org.elasticsearch.common.inject.spi.Message; - -import java.lang.reflect.Type; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -/** - * - */ -public class Injectors { - - public static Throwable getFirstErrorFailure(CreationException e) { - if (e.getErrorMessages().isEmpty()) { - return e; - } - // return the first message that has root cause, probably an actual error - for (Message message : e.getErrorMessages()) { - if (message.getCause() != null) { - return message.getCause(); - } - } - return e; - } - - /** - * Returns an instance of the given type with the {@link org.elasticsearch.common.inject.name.Named} - * annotation value. - *

- * This method allows you to switch this code - * injector.getInstance(Key.get(type, Names.named(name))); - *

- * to the more concise - * Injectors.getInstance(injector, type, name); - */ - public static T getInstance(Injector injector, java.lang.Class 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 the base type - * @return a set of objects returned from this injector - */ - public static Set getInstancesOf(Injector injector, Class baseClass) { - Set answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, 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 Set getInstancesOf(Injector injector, Matcher matcher) { - Set answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, 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 Set> getProvidersOf(Injector injector, Matcher matcher) { - Set> answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, Binding> entry : entries) { - Key key = entry.getKey(); - Class keyType = getKeyType(key); - if (keyType != null && matcher.matches(keyType)) { - Binding binding = entry.getValue(); - answer.add((Provider) binding.getProvider()); - } - } - return answer; - } - - /** - * Returns a collection of all providers of the given base type - * - * @param baseClass the base type of objects required - * @param the base type - * @return a set of objects returned from this injector - */ - public static Set> getProvidersOf(Injector injector, Class baseClass) { - Set> answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, Binding> entry : entries) { - Key key = entry.getKey(); - Class keyType = getKeyType(key); - if (keyType != null && baseClass.isAssignableFrom(keyType)) { - Binding binding = entry.getValue(); - answer.add((Provider) binding.getProvider()); - } - } - return answer; - } - - /** - * Returns true if a binding exists for the given matcher - */ - public static boolean hasBinding(Injector injector, Matcher 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, 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> getBindingsOf(Injector injector, Matcher matcher) { - Set> answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, 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> getBindingsOf(Injector injector, Class baseClass) { - Set> answer = new HashSet<>(); - Set, Binding>> entries = injector.getBindings().entrySet(); - for (Entry, 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 Class getKeyType(Key key) { - Class keyType = null; - TypeLiteral typeLiteral = key.getTypeLiteral(); - Type type = typeLiteral.getType(); - if (type instanceof Class) { - keyType = (Class) type; - } - return keyType; - } - - public static void cleanCaches(Injector injector) { - ((InjectorImpl) injector).clearCache(); - if (injector.getParent() != null) { - cleanCaches(injector.getParent()); - } - } -} diff --git a/core/src/main/java/org/elasticsearch/common/inject/ModulesBuilder.java b/core/src/main/java/org/elasticsearch/common/inject/ModulesBuilder.java index 41cdecfbcad..3321b75f4e5 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/ModulesBuilder.java +++ b/core/src/main/java/org/elasticsearch/common/inject/ModulesBuilder.java @@ -23,9 +23,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -/** - * - */ public class ModulesBuilder implements Iterable { private final List modules = new ArrayList<>(); @@ -44,19 +41,10 @@ public class ModulesBuilder implements Iterable { public Injector createInjector() { Injector injector = Guice.createInjector(modules); - Injectors.cleanCaches(injector); + ((InjectorImpl) injector).clearCache(); // in ES, we always create all instances as if they are eager singletons // this allows for considerable memory savings (no need to store construction info) as well as cycles ((InjectorImpl) injector).readOnlyAllSingletons(); return injector; } - - public Injector createChildInjector(Injector injector) { - Injector childInjector = injector.createChildInjector(modules); - Injectors.cleanCaches(childInjector); - // in ES, we always create all instances as if they are eager singletons - // this allows for considerable memory savings (no need to store construction info) as well as cycles - ((InjectorImpl) childInjector).readOnlyAllSingletons(); - return childInjector; - } } diff --git a/core/src/main/java/org/elasticsearch/common/inject/PrivateModule.java b/core/src/main/java/org/elasticsearch/common/inject/PrivateModule.java index 4413028f908..b56c0e11ab1 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/PrivateModule.java +++ b/core/src/main/java/org/elasticsearch/common/inject/PrivateModule.java @@ -61,10 +61,6 @@ import java.lang.annotation.Annotation; * } * *

- * Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent - * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the - * root environment. Such bindings are shared among all environments in the tree. - *

* The scope of a binding is constrained to its environment. A singleton bound in a private * module will be unique to its environment. But a binding for the same type in a different private * module will yield a different instance. @@ -143,13 +139,6 @@ public abstract class PrivateModule implements Module { return binder; } - /** - * @see Binder#bindScope(Class, Scope) - */ - protected final void bindScope(Class scopeAnnotation, Scope scope) { - binder.bindScope(scopeAnnotation, scope); - } - /** * @see Binder#bind(Key) */ @@ -171,13 +160,6 @@ public abstract class PrivateModule implements Module { return binder.bind(clazz); } - /** - * @see Binder#bindConstant() - */ - protected final AnnotatedConstantBindingBuilder bindConstant() { - return binder.bindConstant(); - } - /** * @see Binder#install(Module) */ @@ -206,34 +188,6 @@ public abstract class PrivateModule implements Module { binder.addError(message); } - /** - * @see Binder#requestInjection(Object) - */ - protected final void requestInjection(Object instance) { - binder.requestInjection(instance); - } - - /** - * @see Binder#requestStaticInjection(Class[]) - */ - protected final void requestStaticInjection(Class... types) { - binder.requestStaticInjection(types); - } - - /** - * Instructs Guice to require a binding to the given key. - */ - protected final void requireBinding(Key key) { - binder.getProvider(key); - } - - /** - * Instructs Guice to require a binding to the given type. - */ - protected final void requireBinding(Class type) { - binder.getProvider(type); - } - /** * @see Binder#getProvider(Key) */ @@ -248,21 +202,6 @@ public abstract class PrivateModule implements Module { return binder.getProvider(type); } - /** - * @see Binder#convertToTypes(org.elasticsearch.common.inject.matcher.Matcher, org.elasticsearch.common.inject.spi.TypeConverter) - */ - protected final void convertToTypes(Matcher> typeMatcher, - TypeConverter converter) { - binder.convertToTypes(typeMatcher, converter); - } - - /** - * @see Binder#currentStage() - */ - protected final Stage currentStage() { - return binder.currentStage(); - } - /** * @see Binder#getMembersInjector(Class) */ @@ -276,12 +215,4 @@ public abstract class PrivateModule implements Module { protected MembersInjector getMembersInjector(TypeLiteral type) { return binder.getMembersInjector(type); } - - /** - * @see Binder#bindListener(org.elasticsearch.common.inject.matcher.Matcher, org.elasticsearch.common.inject.spi.TypeListener) - */ - protected void bindListener(Matcher> typeMatcher, - TypeListener listener) { - binder.bindListener(typeMatcher, listener); - } } diff --git a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider.java b/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider.java index 0def65b9a13..099ff661595 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider.java +++ b/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider.java @@ -134,7 +134,7 @@ public class FactoryProvider implements Provider, HasDependencies { /* * This class implements the old @AssistedInject implementation that manually matches constructors - * to factory methods. The new child injector implementation lives in FactoryProvider2. + * to factory methods. */ private Injector injector; @@ -142,23 +142,6 @@ public class FactoryProvider implements Provider, HasDependencies { private final TypeLiteral factoryType; private final Map> factoryMethodToConstructor; - public static Provider newFactory( - Class factoryType, Class implementationType) { - return newFactory(TypeLiteral.get(factoryType), TypeLiteral.get(implementationType)); - } - - public static Provider newFactory( - TypeLiteral factoryType, TypeLiteral implementationType) { - Map> factoryMethodToConstructor - = createMethodMapping(factoryType, implementationType); - - if (!factoryMethodToConstructor.isEmpty()) { - return new FactoryProvider<>(factoryType, factoryMethodToConstructor); - } else { - return new FactoryProvider2<>(factoryType, Key.get(implementationType)); - } - } - private FactoryProvider(TypeLiteral factoryType, Map> factoryMethodToConstructor) { this.factoryType = factoryType; @@ -166,22 +149,6 @@ public class FactoryProvider implements Provider, HasDependencies { checkDeclaredExceptionsMatch(); } - @Inject - void setInjectorAndCheckUnboundParametersAreInjectable(Injector injector) { - this.injector = injector; - for (AssistedConstructor c : factoryMethodToConstructor.values()) { - for (Parameter p : c.getAllParameters()) { - if (!p.isProvidedByFactory() && !paramCanBeInjected(p, injector)) { - // this is lame - we're not using the proper mechanism to add an - // error to the injector. Throughout this class we throw exceptions - // to add errors, which isn't really the best way in Guice - throw newConfigurationException("Parameter of type '%s' is not injectable or annotated " - + "with @Assisted for Constructor '%s'", p, c); - } - } - } - } - private void checkDeclaredExceptionsMatch() { for (Map.Entry> entry : factoryMethodToConstructor.entrySet()) { for (Class constructorException : entry.getValue().getDeclaredExceptions()) { @@ -204,82 +171,6 @@ public class FactoryProvider implements Provider, HasDependencies { return false; } - private boolean paramCanBeInjected(Parameter parameter, Injector injector) { - return parameter.isBound(injector); - } - - private static Map> createMethodMapping( - TypeLiteral factoryType, TypeLiteral implementationType) { - List> constructors = new ArrayList<>(); - - for (Constructor constructor : implementationType.getRawType().getConstructors()) { - if (constructor.getAnnotation(AssistedInject.class) != null) { - @SuppressWarnings("unchecked") // the constructor type and implementation type agree - AssistedConstructor assistedConstructor = new AssistedConstructor( - constructor, implementationType.getParameterTypes(constructor)); - constructors.add(assistedConstructor); - } - } - - if (constructors.isEmpty()) { - return emptyMap(); - } - - Method[] factoryMethods = factoryType.getRawType().getMethods(); - - if (constructors.size() != factoryMethods.length) { - throw newConfigurationException("Constructor mismatch: %s has %s @AssistedInject " - + "constructors, factory %s has %s creation methods", implementationType, - constructors.size(), factoryType, factoryMethods.length); - } - - Map paramsToConstructor = new HashMap<>(); - - for (AssistedConstructor c : constructors) { - if (paramsToConstructor.containsKey(c.getAssistedParameters())) { - throw new RuntimeException("Duplicate constructor, " + c); - } - paramsToConstructor.put(c.getAssistedParameters(), c); - } - - Map> result = new HashMap<>(); - for (Method method : factoryMethods) { - if (!method.getReturnType().isAssignableFrom(implementationType.getRawType())) { - throw newConfigurationException("Return type of method %s is not assignable from %s", - method, implementationType); - } - - List parameterTypes = new ArrayList<>(); - for (TypeLiteral parameterType : factoryType.getParameterTypes(method)) { - parameterTypes.add(parameterType.getType()); - } - ParameterListKey methodParams = new ParameterListKey(parameterTypes); - - if (!paramsToConstructor.containsKey(methodParams)) { - throw newConfigurationException("%s has no @AssistInject constructor that takes the " - + "@Assisted parameters %s in that order. @AssistInject constructors are %s", - implementationType, methodParams, paramsToConstructor.values()); - } - - method.getParameterAnnotations(); - for (Annotation[] parameterAnnotations : method.getParameterAnnotations()) { - for (Annotation parameterAnnotation : parameterAnnotations) { - if (parameterAnnotation.annotationType() == Assisted.class) { - throw newConfigurationException("Factory method %s has an @Assisted parameter, which " - + "is incompatible with the deprecated @AssistedInject annotation. Please replace " - + "@AssistedInject with @Inject on the %s constructor.", - method, implementationType); - } - } - } - - AssistedConstructor matchingConstructor = paramsToConstructor.remove(methodParams); - - result.put(method, matchingConstructor); - } - return result; - } - @Override public Set> getDependencies() { Set> dependencies = new HashSet<>(); diff --git a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider2.java b/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider2.java deleted file mode 100644 index 29863527202..00000000000 --- a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/FactoryProvider2.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * 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 org.elasticsearch.common.inject.assistedinject; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.common.inject.Binder; -import org.elasticsearch.common.inject.Binding; -import org.elasticsearch.common.inject.ConfigurationException; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.inject.Injector; -import org.elasticsearch.common.inject.Key; -import org.elasticsearch.common.inject.Module; -import org.elasticsearch.common.inject.Provider; -import org.elasticsearch.common.inject.ProvisionException; -import org.elasticsearch.common.inject.TypeLiteral; -import org.elasticsearch.common.inject.internal.Errors; -import org.elasticsearch.common.inject.internal.ErrorsException; -import org.elasticsearch.common.inject.spi.Message; -import org.elasticsearch.common.inject.util.Providers; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static java.util.Collections.unmodifiableMap; -import static org.elasticsearch.common.inject.internal.Annotations.getKey; - -/** - * The newer implementation of factory provider. This implementation uses a child injector to - * create values. - * - * @author jessewilson@google.com (Jesse Wilson) - * @author dtm@google.com (Daniel Martin) - */ -public final class FactoryProvider2 implements InvocationHandler, Provider { - - /** - * if a factory method parameter isn't annotated, it gets this annotation. - */ - static final Assisted DEFAULT_ANNOTATION = new Assisted() { - @Override - public String value() { - return ""; - } - - @Override - public Class annotationType() { - return Assisted.class; - } - - @Override - public boolean equals(Object o) { - return o instanceof Assisted - && ((Assisted) o).value().equals(""); - } - - @Override - public int hashCode() { - return 127 * "value".hashCode() ^ "".hashCode(); - } - - @Override - public String toString() { - return "@" + Assisted.class.getName() + "(value=)"; - } - }; - - /** - * the produced type, or null if all methods return concrete types - */ - private final Key producedType; - private final Map> returnTypesByMethod; - private final Map>> paramTypes; - - /** - * the hosting injector, or null if we haven't been initialized yet - */ - private Injector injector; - - /** - * the factory interface, implemented and provided - */ - private final F factory; - - /** - * @param factoryType a Java interface that defines one or more create methods. - * @param producedType a concrete type that is assignable to the return types of all factory - * methods. - */ - FactoryProvider2(TypeLiteral factoryType, Key producedType) { - this.producedType = producedType; - - Errors errors = new Errors(); - - @SuppressWarnings("unchecked") // we imprecisely treat the class literal of T as a Class - Class factoryRawType = (Class) factoryType.getRawType(); - - try { - Map> returnTypesBuilder = new HashMap<>(); - Map>> paramTypesBuilder = new HashMap<>(); - // TODO: also grab methods from superinterfaces - for (Method method : factoryRawType.getMethods()) { - Key returnType = getKey( - factoryType.getReturnType(method), method, method.getAnnotations(), errors); - returnTypesBuilder.put(method, returnType); - List> params = factoryType.getParameterTypes(method); - Annotation[][] paramAnnotations = method.getParameterAnnotations(); - int p = 0; - List> keys = new ArrayList<>(); - for (TypeLiteral param : params) { - Key paramKey = getKey(param, method, paramAnnotations[p++], errors); - keys.add(assistKey(method, paramKey, errors)); - } - paramTypesBuilder.put(method, Collections.unmodifiableList(keys)); - } - returnTypesByMethod = unmodifiableMap(returnTypesBuilder); - paramTypes = unmodifiableMap(paramTypesBuilder); - } catch (ErrorsException e) { - throw new ConfigurationException(e.getErrors().getMessages()); - } - - factory = factoryRawType.cast(Proxy.newProxyInstance(factoryRawType.getClassLoader(), - new Class[]{factoryRawType}, this)); - } - - @Override - public F get() { - return factory; - } - - /** - * Returns a key similar to {@code key}, but with an {@literal @}Assisted binding annotation. - * This fails if another binding annotation is clobbered in the process. If the key already has - * the {@literal @}Assisted annotation, it is returned as-is to preserve any String value. - */ - private Key assistKey(Method method, Key key, Errors errors) throws ErrorsException { - if (key.getAnnotationType() == null) { - return Key.get(key.getTypeLiteral(), DEFAULT_ANNOTATION); - } else if (key.getAnnotationType() == Assisted.class) { - return key; - } else { - errors.withSource(method).addMessage( - "Only @Assisted is allowed for factory parameters, but found @%s", - key.getAnnotationType()); - throw errors.toException(); - } - } - - /** - * At injector-creation time, we initialize the invocation handler. At this time we make sure - * all factory methods will be able to build the target types. - */ - @Inject - public void initialize(Injector injector) { - if (this.injector != null) { - throw new ConfigurationException(Collections.singletonList(new Message(FactoryProvider2.class, - "Factories.create() factories may only be used in one Injector!"))); - } - - this.injector = injector; - - for (Method method : returnTypesByMethod.keySet()) { - Object[] args = new Object[method.getParameterTypes().length]; - Arrays.fill(args, "dummy object for validating Factories"); - getBindingFromNewInjector(method, args); // throws if the binding isn't properly configured - } - } - - /** - * Creates a child injector that binds the args, and returns the binding for the method's result. - */ - public Binding getBindingFromNewInjector(final Method method, final Object[] args) { - if (injector == null) { - throw new IllegalStateException("Factories.create() factories cannot be used until they're initialized by Guice."); - } - - final Key returnType = returnTypesByMethod.get(method); - - Module assistedModule = new AbstractModule() { - @Override - @SuppressWarnings("unchecked") // raw keys are necessary for the args array and return value - protected void configure() { - Binder binder = binder().withSource(method); - - int p = 0; - for (Key paramKey : paramTypes.get(method)) { - // Wrap in a Provider to cover null, and to prevent Guice from injecting the parameter - binder.bind((Key) paramKey).toProvider(Providers.of(args[p++])); - } - - if (producedType != null && !returnType.equals(producedType)) { - binder.bind(returnType).to((Key) producedType); - } else { - binder.bind(returnType); - } - } - }; - - Injector forCreate = injector.createChildInjector(assistedModule); - return forCreate.getBinding(returnType); - } - - /** - * When a factory method is invoked, we create a child injector that binds all parameters, then - * use that to get an instance of the return type. - */ - @Override - public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable { - if (method.getDeclaringClass() == Object.class) { - return method.invoke(this, args); - } - - Provider provider = getBindingFromNewInjector(method, args).getProvider(); - try { - return provider.get(); - } catch (ProvisionException e) { - // if this is an exception declared by the factory method, throw it as-is - if (e.getErrorMessages().size() == 1) { - Message onlyError = e.getErrorMessages().iterator().next(); - Throwable cause = onlyError.getCause(); - if (cause != null && canRethrow(method, cause)) { - throw cause; - } - } - throw e; - } - } - - @Override - public String toString() { - return factory.getClass().getInterfaces()[0].getName() - + " for " + producedType.getTypeLiteral(); - } - - @Override - public boolean equals(Object o) { - return o == this || o == factory; - } - - @Override - public int hashCode() { - // This way both this and its factory hash to the same spot, making hashCode consistent. - return factory.hashCode(); - } - - /** - * Returns true if {@code thrown} can be thrown by {@code invoked} without wrapping. - */ - static boolean canRethrow(Method invoked, Throwable thrown) { - if (thrown instanceof Error || thrown instanceof RuntimeException) { - return true; - } - - for (Class declared : invoked.getExceptionTypes()) { - if (declared.isInstance(thrown)) { - return true; - } - } - - return false; - } -} diff --git a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/Parameter.java b/core/src/main/java/org/elasticsearch/common/inject/assistedinject/Parameter.java index 0fae9dede5b..5ceb086db9f 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/assistedinject/Parameter.java +++ b/core/src/main/java/org/elasticsearch/common/inject/assistedinject/Parameter.java @@ -87,34 +87,6 @@ class Parameter { : injector.getInstance(getPrimaryBindingKey()); } - public boolean isBound(Injector injector) { - return isBound(injector, getPrimaryBindingKey()) - || isBound(injector, fixAnnotations(getPrimaryBindingKey())); - } - - private boolean isBound(Injector injector, Key key) { - // This method is particularly lame - we really need an API that can test - // for any binding, implicit or explicit - try { - return injector.getBinding(key) != null; - } catch (ConfigurationException e) { - return false; - } - } - - /** - * Replace annotation instances with annotation types, this is only - * appropriate for testing if a key is bound and not for injecting. - *

- * See Guice bug 125, - * http://code.google.com/p/google-guice/issues/detail?id=125 - */ - public Key fixAnnotations(Key key) { - return key.getAnnotation() == null - ? key - : Key.get(key.getTypeLiteral(), key.getAnnotation().annotationType()); - } - Key getPrimaryBindingKey() { return isProvider ? getBindingForType(getProvidedType(type)) diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/ConvertedConstantBinding.java b/core/src/main/java/org/elasticsearch/common/inject/spi/ConvertedConstantBinding.java index 3c4ec4d9ed5..1963919c0c5 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/ConvertedConstantBinding.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/ConvertedConstantBinding.java @@ -36,8 +36,7 @@ public interface ConvertedConstantBinding extends Binding, HasDependencies T getValue(); /** - * Returns the key for the source binding. That binding can e retrieved from an injector using - * {@link org.elasticsearch.common.inject.Injector#getBinding(Key) Injector.getBinding(key)}. + * Returns the key for the source binding. */ Key getSourceKey(); diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/Element.java b/core/src/main/java/org/elasticsearch/common/inject/spi/Element.java index f9128d98f56..a2eaf995c70 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/Element.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/Element.java @@ -25,9 +25,6 @@ import org.elasticsearch.common.inject.Binder; * Elements#getElements(org.elasticsearch.common.inject.Module[]) Elements.getElements()} to read the elements * from a module, and {@link Elements#getModule(Iterable) Elements.getModule()} to rewrite them. * This can be used for static analysis and generation of Guice modules. - *

- * The elements of an injector can be inspected and exercised. Use {@link - * org.elasticsearch.common.inject.Injector#getBindings Injector.getBindings()} to reflect on Guice injectors. * * @author jessewilson@google.com (Jesse Wilson) * @author crazybob@google.com (Bob Lee) diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/Elements.java b/core/src/main/java/org/elasticsearch/common/inject/spi/Elements.java index 4b3660fe47a..30911def551 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/Elements.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/Elements.java @@ -80,13 +80,6 @@ public final class Elements { return getElements(Stage.DEVELOPMENT, Arrays.asList(modules)); } - /** - * Records the elements executed by {@code modules}. - */ - public static List getElements(Stage stage, Module... modules) { - return getElements(stage, Arrays.asList(modules)); - } - /** * Records the elements executed by {@code modules}. */ @@ -119,11 +112,6 @@ public final class Elements { }; } - @SuppressWarnings("unchecked") - static BindingTargetVisitor getInstanceVisitor() { - return (BindingTargetVisitor) GET_INSTANCE_VISITOR; - } - private static class RecordingBinder implements Binder, PrivateBinder { private final Stage stage; private final Set modules; diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/LinkedKeyBinding.java b/core/src/main/java/org/elasticsearch/common/inject/spi/LinkedKeyBinding.java index 82c36c7c2e2..60b7adced3e 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/LinkedKeyBinding.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/LinkedKeyBinding.java @@ -28,8 +28,7 @@ import org.elasticsearch.common.inject.Key; public interface LinkedKeyBinding extends Binding { /** - * Returns the linked key used to resolve injections. That binding can be retrieved from an - * injector using {@link org.elasticsearch.common.inject.Injector#getBinding(Key) Injector.getBinding(key)}. + * Returns the linked key used to resolve injections. */ Key getLinkedKey(); diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderBinding.java b/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderBinding.java index 04fb78d0288..c6ac377c051 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderBinding.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderBinding.java @@ -30,9 +30,7 @@ import org.elasticsearch.common.inject.Provider; public interface ProviderBinding> extends Binding { /** - * Returns the key whose binding is used to {@link Provider#get provide instances}. That binding - * can be retrieved from an injector using {@link org.elasticsearch.common.inject.Injector#getBinding(Key) - * Injector.getBinding(providedKey)} + * Returns the key whose binding is used to {@link Provider#get provide instances}. */ Key getProvidedKey(); } \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderKeyBinding.java b/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderKeyBinding.java index 15aa751f4a6..78191621561 100644 --- a/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderKeyBinding.java +++ b/core/src/main/java/org/elasticsearch/common/inject/spi/ProviderKeyBinding.java @@ -30,9 +30,7 @@ import org.elasticsearch.common.inject.Provider; public interface ProviderKeyBinding extends Binding { /** - * Returns the key used to resolve the provider's binding. That binding can be retrieved from an - * injector using {@link org.elasticsearch.common.inject.Injector#getBinding(Key) - * Injector.getBinding(providerKey)} + * Returns the key used to resolve the provider's binding. */ Key> getProviderKey();