1/**
2 * Copyright (C) 2008 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.inject;
18
19import static com.google.common.base.Preconditions.checkState;
20
21import com.google.inject.binder.AnnotatedBindingBuilder;
22import com.google.inject.binder.AnnotatedConstantBindingBuilder;
23import com.google.inject.binder.AnnotatedElementBuilder;
24import com.google.inject.binder.LinkedBindingBuilder;
25import com.google.inject.matcher.Matcher;
26import com.google.inject.spi.Message;
27import com.google.inject.spi.ProvisionListener;
28import com.google.inject.spi.TypeConverter;
29import com.google.inject.spi.TypeListener;
30
31import java.lang.annotation.Annotation;
32import java.lang.reflect.Method;
33
34/**
35 * A module whose configuration information is hidden from its environment by default. Only bindings
36 * that are explicitly exposed will be available to other modules and to the users of the injector.
37 * This module may expose the bindings it creates and the bindings of the modules it installs.
38 *
39 * <p>A private module can be nested within a regular module or within another private module using
40 * {@link Binder#install install()}.  Its bindings live in a new environment that inherits bindings,
41 * type converters, scopes, and interceptors from the surrounding ("parent") environment.  When you
42 * nest multiple private modules, the result is a tree of environments where the injector's
43 * environment is the root.
44 *
45 * <p>Guice EDSL bindings can be exposed with {@link #expose(Class) expose()}. {@literal @}{@link
46 * com.google.inject.Provides Provides} bindings can be exposed with the {@literal @}{@link
47 * Exposed} annotation:
48 *
49 * <pre>
50 * public class FooBarBazModule extends PrivateModule {
51 *   protected void configure() {
52 *     bind(Foo.class).to(RealFoo.class);
53 *     expose(Foo.class);
54 *
55 *     install(new TransactionalBarModule());
56 *     expose(Bar.class).annotatedWith(Transactional.class);
57 *
58 *     bind(SomeImplementationDetail.class);
59 *     install(new MoreImplementationDetailsModule());
60 *   }
61 *
62 *   {@literal @}Provides {@literal @}Exposed
63 *   public Baz provideBaz() {
64 *     return new SuperBaz();
65 *   }
66 * }
67 * </pre>
68 *
69 * <p>Private modules are implemented using {@link Injector#createChildInjector(Module[]) parent
70 * injectors}. When it can satisfy their dependencies, just-in-time bindings will be created in the
71 * root environment. Such bindings are shared among all environments in the tree.
72 *
73 * <p>The scope of a binding is constrained to its environment. A singleton bound in a private
74 * module will be unique to its environment. But a binding for the same type in a different private
75 * module will yield a different instance.
76 *
77 * <p>A shared binding that injects the {@code Injector} gets the root injector, which only has
78 * access to bindings in the root environment. An explicit binding that injects the {@code Injector}
79 * gets access to all bindings in the child environment.
80 *
81 * <p>To promote a just-in-time binding to an explicit binding, bind it:
82 * <pre>
83 *   bind(FooImpl.class);
84 * </pre>
85 *
86 * @author jessewilson@google.com (Jesse Wilson)
87 * @since 2.0
88 */
89public abstract class PrivateModule implements Module {
90
91  /** Like abstract module, the binder of the current private module */
92  private PrivateBinder binder;
93
94  public final synchronized void configure(Binder binder) {
95    checkState(this.binder == null, "Re-entry is not allowed.");
96
97    // Guice treats PrivateModules specially and passes in a PrivateBinder automatically.
98    this.binder = (PrivateBinder) binder.skipSources(PrivateModule.class);
99    try {
100      configure();
101    } finally {
102      this.binder = null;
103    }
104  }
105
106  /**
107   * Creates bindings and other configurations private to this module. Use {@link #expose(Class)
108   * expose()} to make the bindings in this module available externally.
109   */
110  protected abstract void configure();
111
112  /** Makes the binding for {@code key} available to other modules and the injector. */
113  protected final <T> void expose(Key<T> key) {
114    binder().expose(key);
115  }
116
117  /**
118   * Makes a binding for {@code type} available to other modules and the injector. Use {@link
119   * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
120   * binding annotation.
121   */
122  protected final AnnotatedElementBuilder expose(Class<?> type) {
123    return binder().expose(type);
124  }
125
126  /**
127   * Makes a binding for {@code type} available to other modules and the injector. Use {@link
128   * AnnotatedElementBuilder#annotatedWith(Class) annotatedWith()} to expose {@code type} with a
129   * binding annotation.
130   */
131  protected final AnnotatedElementBuilder expose(TypeLiteral<?> type) {
132    return binder().expose(type);
133  }
134
135  // everything below is copied from AbstractModule
136
137  /**
138   * Returns the current binder.
139   */
140  protected final PrivateBinder binder() {
141    checkState(binder != null, "The binder can only be used inside configure()");
142    return binder;
143  }
144
145  /**
146   * @see Binder#bindScope(Class, Scope)
147   */
148  protected final void bindScope(Class<? extends Annotation> scopeAnnotation, Scope scope) {
149    binder().bindScope(scopeAnnotation, scope);
150  }
151
152  /**
153   * @see Binder#bind(Key)
154   */
155  protected final <T> LinkedBindingBuilder<T> bind(Key<T> key) {
156    return binder().bind(key);
157  }
158
159  /**
160   * @see Binder#bind(TypeLiteral)
161   */
162  protected final <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
163    return binder().bind(typeLiteral);
164  }
165
166  /**
167   * @see Binder#bind(Class)
168   */
169  protected final <T> AnnotatedBindingBuilder<T> bind(Class<T> clazz) {
170    return binder().bind(clazz);
171  }
172
173  /**
174   * @see Binder#bindConstant()
175   */
176  protected final AnnotatedConstantBindingBuilder bindConstant() {
177    return binder().bindConstant();
178  }
179
180  /**
181   * @see Binder#install(Module)
182   */
183  protected final void install(Module module) {
184    binder().install(module);
185  }
186
187  /**
188   * @see Binder#addError(String, Object[])
189   */
190  protected final void addError(String message, Object... arguments) {
191    binder().addError(message, arguments);
192  }
193
194  /**
195   * @see Binder#addError(Throwable)
196   */
197  protected final void addError(Throwable t) {
198    binder().addError(t);
199  }
200
201  /**
202   * @see Binder#addError(Message)
203   */
204  protected final void addError(Message message) {
205    binder().addError(message);
206  }
207
208  /**
209   * @see Binder#requestInjection(Object)
210   */
211  protected final void requestInjection(Object instance) {
212    binder().requestInjection(instance);
213  }
214
215  /**
216   * @see Binder#requestStaticInjection(Class[])
217   */
218  protected final void requestStaticInjection(Class<?>... types) {
219    binder().requestStaticInjection(types);
220  }
221
222  /*if[AOP]*/
223  /**
224   * @see Binder#bindInterceptor(com.google.inject.matcher.Matcher, com.google.inject.matcher.Matcher, org.aopalliance.intercept.MethodInterceptor[])
225   */
226  protected final void bindInterceptor(Matcher<? super Class<?>> classMatcher,
227      Matcher<? super Method> methodMatcher,
228      org.aopalliance.intercept.MethodInterceptor... interceptors) {
229    binder().bindInterceptor(classMatcher, methodMatcher, interceptors);
230  }
231  /*end[AOP]*/
232
233  /**
234   * Instructs Guice to require a binding to the given key.
235   */
236  protected final void requireBinding(Key<?> key) {
237    binder().getProvider(key);
238  }
239
240  /**
241   * Instructs Guice to require a binding to the given type.
242   */
243  protected final void requireBinding(Class<?> type) {
244    binder().getProvider(type);
245  }
246
247  /**
248   * @see Binder#getProvider(Key)
249   */
250  protected final <T> Provider<T> getProvider(Key<T> key) {
251    return binder().getProvider(key);
252  }
253
254  /**
255   * @see Binder#getProvider(Class)
256   */
257  protected final <T> Provider<T> getProvider(Class<T> type) {
258    return binder().getProvider(type);
259  }
260
261  /**
262   * @see Binder#convertToTypes(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeConverter)
263   */
264  protected final void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
265      TypeConverter converter) {
266    binder().convertToTypes(typeMatcher, converter);
267  }
268
269  /**
270   * @see Binder#currentStage()
271   */
272  protected final Stage currentStage() {
273    return binder().currentStage();
274  }
275
276  /**
277   * @see Binder#getMembersInjector(Class)
278   */
279  protected <T> MembersInjector<T> getMembersInjector(Class<T> type) {
280    return binder().getMembersInjector(type);
281  }
282
283  /**
284   * @see Binder#getMembersInjector(TypeLiteral)
285   */
286  protected <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> type) {
287    return binder().getMembersInjector(type);
288  }
289
290  /**
291   * @see Binder#bindListener(com.google.inject.matcher.Matcher, com.google.inject.spi.TypeListener)
292   */
293  protected void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher,
294      TypeListener listener) {
295    binder().bindListener(typeMatcher, listener);
296  }
297
298  /**
299   * @see Binder#bindListener(Matcher, ProvisionListener...)
300   * @since 4.0
301   */
302  protected void bindListener(Matcher<? super Binding<?>> bindingMatcher,
303      ProvisionListener... listeners) {
304    binder().bindListener(bindingMatcher, listeners);
305  }
306}
307