1477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit/**
2477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Copyright (C) 2008 Google Inc.
3477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
4477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Licensed under the Apache License, Version 2.0 (the "License");
5477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * you may not use this file except in compliance with the License.
6477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * You may obtain a copy of the License at
7477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
8477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * http://www.apache.org/licenses/LICENSE-2.0
9477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
10477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * Unless required by applicable law or agreed to in writing, software
11477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * distributed under the License is distributed on an "AS IS" BASIS,
12477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * See the License for the specific language governing permissions and
14477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * limitations under the License.
15477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit */
16477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
17477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitpackage com.google.inject.spi;
18477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
19b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport static com.google.common.base.Preconditions.checkArgument;
20ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruberimport static com.google.inject.internal.InternalFlags.getIncludeStackTraceOption;
21b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
22b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableList;
23b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.Lists;
2454da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport com.google.common.collect.Maps;
25b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.Sets;
26477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.AbstractModule;
27477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Binder;
2876c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.Binding;
29477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Key;
3097eac0fa7c42c3ebc409e63156899d3c889cb234limpbizkitimport com.google.inject.MembersInjector;
31477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Module;
32bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkitimport com.google.inject.PrivateBinder;
33fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkitimport com.google.inject.PrivateModule;
34477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Provider;
35477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Scope;
36477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.Stage;
37477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.TypeLiteral;
38477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedBindingBuilder;
39477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.binder.AnnotatedConstantBindingBuilder;
405ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport com.google.inject.binder.AnnotatedElementBuilder;
4176c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.AbstractBindingBuilder;
4276c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.BindingBuilder;
4376c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkitimport com.google.inject.internal.ConstantBindingBuilderImpl;
4472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkitimport com.google.inject.internal.Errors;
459a227bef3b82a045323ef2cf38ec60b2e42cf0felimpbizkit@gmail.comimport com.google.inject.internal.ExposureBuilder;
460910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruberimport com.google.inject.internal.InternalFlags.IncludeStackTraceOption;
47825f8c1df885b9d7643a9e18e336984f0138edafsamebimport com.google.inject.internal.MoreTypes;
48c3f928404a91cf837d809dcc465ba43442bc1198limpbizkitimport com.google.inject.internal.PrivateElementsImpl;
4986cb3bb7d9b662398dc2b71433a9f6c6a6392b5climpbizkitimport com.google.inject.internal.ProviderMethodsModule;
509a227bef3b82a045323ef2cf38ec60b2e42cf0felimpbizkit@gmail.comimport com.google.inject.internal.util.SourceProvider;
51605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruberimport com.google.inject.internal.util.StackTraceElements;
52477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport com.google.inject.matcher.Matcher;
53b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
54477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.annotation.Annotation;
55477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.lang.reflect.Method;
56477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Arrays;
575ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkitimport java.util.Collection;
58477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Collections;
59477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.List;
6054da0e3ca924a5040e88a1c067f9f6760a14b20bsamebimport java.util.Map;
61477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitimport java.util.Set;
62477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
63477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit/**
64aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit * Exposes elements of a module so they can be inspected, validated or {@link
65aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit * Element#applyTo(Binder) rewritten}.
66477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit *
67477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit * @author jessewilson@google.com (Jesse Wilson)
68c489adf4671b41765698d167e13960d998190c5elimpbizkit * @since 2.0
69477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit */
70477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkitpublic final class Elements {
71605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
72afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit  private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
73afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit      = new DefaultBindingTargetVisitor<Object, Object>() {
7403b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    @Override public Object visit(InstanceBinding<?> binding) {
7576c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit      return binding.getInstance();
76477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
77477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
788996e8059681c083744df50c7ad9e007eda1f648limpbizkit    @Override protected Object visitOther(Binding<?> binding) {
79477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      throw new IllegalArgumentException();
80477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
81477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  };
82477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
83477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
84477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
85477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
86477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Module... modules) {
87477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, Arrays.asList(modules));
88477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
89477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
90477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
91477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
92477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
93477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Module... modules) {
94477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(stage, Arrays.asList(modules));
95477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
96477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
97477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
98477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
99477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
100477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Iterable<? extends Module> modules) {
101477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return getElements(Stage.DEVELOPMENT, modules);
102477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
103477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
104477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  /**
105477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   * Records the elements executed by {@code modules}.
106477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit   */
107477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  public static List<Element> getElements(Stage stage, Iterable<? extends Module> modules) {
108477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    RecordingBinder binder = new RecordingBinder(stage);
109477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    for (Module module : modules) {
110477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      binder.install(module);
111477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
11254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    binder.scanForAnnotatedMethods();
11354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    for (RecordingBinder child : binder.privateBinders) {
11454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      child.scanForAnnotatedMethods();
11554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
116ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    // Free the memory consumed by the stack trace elements cache
117ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    StackTraceElements.clearCache();
118477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    return Collections.unmodifiableList(binder.elements);
119477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
1200910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber
1212e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  private static class ElementsAsModule implements Module {
1222e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    private final Iterable<? extends Element> elements;
1232e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber
1242e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    ElementsAsModule(Iterable<? extends Element> elements) {
1252e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      this.elements = elements;
1262e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
1272e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber
1280910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
1292e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    public void configure(Binder binder) {
1302e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      for (Element element : elements) {
1312e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber        element.applyTo(binder);
1322e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber      }
1332e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    }
1342e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber  }
1352e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber
136aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  /**
137aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit   * Returns the module composed of {@code elements}.
138aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit   */
139aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  public static Module getModule(final Iterable<? extends Element> elements) {
1402e39ef748a1c4e4dcab506ccfcdb14ca6e01c9c6Christian Edward Gruber    return new ElementsAsModule(elements);
141aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit  }
142aa07ab09a27d4b83e66fb1666e7c780821ed106dlimpbizkit
143477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  @SuppressWarnings("unchecked")
1447e1e4f7fe3d8e552e3a4bcd4fe7a4ce8a8b07431limpbizkit  static <T> BindingTargetVisitor<T, T> getInstanceVisitor() {
145afa4b5dd2056a8427657186d1804313c3f34fbfelimpbizkit    return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
146477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
147477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
14854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  private static class ModuleInfo {
14954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    private final Binder binder;
15054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    private final ModuleSource moduleSource;
15102c489e4fbddf702c7932b55caab83e6d8cba9cesameb    private final boolean skipScanning;
15254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
15302c489e4fbddf702c7932b55caab83e6d8cba9cesameb    private ModuleInfo(Binder binder, ModuleSource moduleSource, boolean skipScanning) {
15454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.binder = binder;
15554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.moduleSource = moduleSource;
15602c489e4fbddf702c7932b55caab83e6d8cba9cesameb      this.skipScanning = skipScanning;
15754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
15854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb  }
15954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
160c34e0185fcf508a890c6cd13bdafeb505c3e9e8aSam Berlin  private static class RecordingBinder implements Binder, PrivateBinder {
161477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Stage stage;
16254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    private final Map<Module, ModuleInfo> modules;
163477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final List<Element> elements;
164477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final Object source;
165605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    /** The current modules stack */
166605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private ModuleSource moduleSource = null;
167477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private final SourceProvider sourceProvider;
16854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    private final Set<ModuleAnnotatedMethodScanner> scanners;
169fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit
170fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    /** The binder where exposed bindings will be created */
171fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private final RecordingBinder parent;
172c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit    private final PrivateElementsImpl privateElements;
173477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
17454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    /** All children private binders, so we can scan through them. */
17554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    private final List<RecordingBinder> privateBinders;
17654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
177477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    private RecordingBinder(Stage stage) {
178477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.stage = stage;
17954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.modules = Maps.newLinkedHashMap();
18054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.scanners = Sets.newLinkedHashSet();
181477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.elements = Lists.newArrayList();
182477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = null;
1835ae41eb77073b47e75c2dcf3766137f2352fbaf9limpbizkit      this.sourceProvider = SourceProvider.DEFAULT_INSTANCE.plusSkippedClasses(
18476c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit          Elements.class, RecordingBinder.class, AbstractModule.class,
18576c24b172e5c4c4b6d51c10dd5c1f491a4033157limpbizkit          ConstantBindingBuilderImpl.class, AbstractBindingBuilder.class, BindingBuilder.class);
186fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = null;
187c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = null;
18854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.privateBinders = Lists.newArrayList();
189477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
190477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
191fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    /** Creates a recording binder that's backed by {@code prototype}. */
192fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private RecordingBinder(
193fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        RecordingBinder prototype, Object source, SourceProvider sourceProvider) {
194477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      checkArgument(source == null ^ sourceProvider == null);
195477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
196fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.stage = prototype.stage;
197fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.modules = prototype.modules;
198fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.elements = prototype.elements;
19954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.scanners = prototype.scanners;
200477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.source = source;
201605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this.moduleSource = prototype.moduleSource;
202477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      this.sourceProvider = sourceProvider;
203fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = prototype.parent;
204c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = prototype.privateElements;
20554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.privateBinders = prototype.privateBinders;
2065ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
2075ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
2085ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    /** Creates a private recording binder. */
209c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit    private RecordingBinder(RecordingBinder parent, PrivateElementsImpl privateElements) {
2105ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.stage = parent.stage;
21154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.modules = Maps.newLinkedHashMap();
21254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.scanners = Sets.newLinkedHashSet(parent.scanners);
213c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.elements = privateElements.getElementsMutable();
2145ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.source = parent.source;
215605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      this.moduleSource = parent.moduleSource;
2165ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      this.sourceProvider = parent.sourceProvider;
217fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      this.parent = parent;
218c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      this.privateElements = privateElements;
21954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      this.privateBinders = parent.privateBinders;
220477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
221477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
222bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkit    /*if[AOP]*/
2230910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
224477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindInterceptor(
225477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Class<?>> classMatcher,
226477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        Matcher<? super Method> methodMatcher,
2274f6274aa4a306efa727f9b37ad16ea3d331d22f0limpbizkit        org.aopalliance.intercept.MethodInterceptor... interceptors) {
228605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new InterceptorBinding(
229605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          getElementSource(), classMatcher, methodMatcher, interceptors));
230477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
231bf0d876bb767f45c5cfbed3929e2cf6acd7d061alimpbizkit    /*end[AOP]*/
232477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2330910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
234477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void bindScope(Class<? extends Annotation> annotationType, Scope scope) {
235605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new ScopeBinding(getElementSource(), annotationType, scope));
236477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
237477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
2380910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
23903b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    @SuppressWarnings("unchecked") // it is safe to use the type literal for the raw type
24003b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    public void requestInjection(Object instance) {
24196e81ba55441fd11c189d903ee2bd1806a23bd70Christian Edward Gruber      requestInjection((TypeLiteral<Object>) TypeLiteral.get(instance.getClass()), instance);
24203b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    }
24303b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit
2440910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
24503b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    public <T> void requestInjection(TypeLiteral<T> type, T instance) {
246825f8c1df885b9d7643a9e18e336984f0138edafsameb      elements.add(new InjectionRequest<T>(getElementSource(), MoreTypes.canonicalizeForKey(type),
247825f8c1df885b9d7643a9e18e336984f0138edafsameb          instance));
24803b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    }
24903b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit
2500910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
25197eac0fa7c42c3ebc409e63156899d3c889cb234limpbizkit    public <T> MembersInjector<T> getMembersInjector(final TypeLiteral<T> typeLiteral) {
252825f8c1df885b9d7643a9e18e336984f0138edafsameb      final MembersInjectorLookup<T> element = new MembersInjectorLookup<T>(getElementSource(),
253825f8c1df885b9d7643a9e18e336984f0138edafsameb          MoreTypes.canonicalizeForKey(typeLiteral));
25497eac0fa7c42c3ebc409e63156899d3c889cb234limpbizkit      elements.add(element);
2558d62075e136d207b8fb8ea98d3fd7ec051bdee3climpbizkit      return element.getMembersInjector();
25603b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    }
25703b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit
25803b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    public <T> MembersInjector<T> getMembersInjector(Class<T> type) {
25997eac0fa7c42c3ebc409e63156899d3c889cb234limpbizkit      return getMembersInjector(TypeLiteral.get(type));
26003b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit    }
26103b81a6b931a06c7697e422b218e3734a7f262cclimpbizkit
262a843a95d620de9c8046e67a8f51619b3fedf77d3limpbizkit    public void bindListener(Matcher<? super TypeLiteral<?>> typeMatcher, TypeListener listener) {
263605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new TypeListenerBinding(getElementSource(), listener, typeMatcher));
264477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
265ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber
266d51292d5a4a788b1275eb9ad55cf612e68640bbfSam Berlin    public void bindListener(Matcher<? super Binding<?>> bindingMatcher,
267d51292d5a4a788b1275eb9ad55cf612e68640bbfSam Berlin        ProvisionListener... listeners) {
268605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new ProvisionListenerBinding(getElementSource(), bindingMatcher, listeners));
269132a5db7c643b8f367eb5f09024cf13ea37c9831sberlin    }
270477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
271477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void requestStaticInjection(Class<?>... types) {
272b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      for (Class<?> type : types) {
273605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        elements.add(new StaticInjectionRequest(getElementSource(), type));
274b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      }
275477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
276477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
27702c489e4fbddf702c7932b55caab83e6d8cba9cesameb    /**
27802c489e4fbddf702c7932b55caab83e6d8cba9cesameb     * Applies all scanners to the modules we've installed. We skip certain
27902c489e4fbddf702c7932b55caab83e6d8cba9cesameb     * PrivateModules because store them in more than one Modules map and only
28002c489e4fbddf702c7932b55caab83e6d8cba9cesameb     * want to process them through one of the maps.  (They're stored in both
28102c489e4fbddf702c7932b55caab83e6d8cba9cesameb     * maps to prevent a module from being installed more than once.)
28202c489e4fbddf702c7932b55caab83e6d8cba9cesameb     */
28354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    void scanForAnnotatedMethods() {
28454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      for (ModuleAnnotatedMethodScanner scanner : scanners) {
28554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        // Note: we must iterate over a copy of the modules because calling install(..)
28654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        // will mutate modules, otherwise causing a ConcurrentModificationException.
28754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        for (Map.Entry<Module, ModuleInfo> entry : Maps.newLinkedHashMap(modules).entrySet()) {
28854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          Module module = entry.getKey();
28902c489e4fbddf702c7932b55caab83e6d8cba9cesameb          ModuleInfo info = entry.getValue();
29002c489e4fbddf702c7932b55caab83e6d8cba9cesameb          if (info.skipScanning) {
29154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb            continue;
29254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          }
29354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          moduleSource = entry.getValue().moduleSource;
29454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          try {
29502c489e4fbddf702c7932b55caab83e6d8cba9cesameb            info.binder.install(ProviderMethodsModule.forModule(module, scanner));
29654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          } catch(RuntimeException e) {
29754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb            Collection<Message> messages = Errors.getMessagesFromThrowable(e);
29854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb            if (!messages.isEmpty()) {
29954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb              elements.addAll(messages);
30054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb            } else {
30154da0e3ca924a5040e88a1c067f9f6760a14b20bsameb              addError(e);
30254da0e3ca924a5040e88a1c067f9f6760a14b20bsameb            }
30354da0e3ca924a5040e88a1c067f9f6760a14b20bsameb          }
30454da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        }
30554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      }
30654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      moduleSource = null;
30754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
30854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
309477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void install(Module module) {
31054da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      if (!modules.containsKey(module)) {
31102c489e4fbddf702c7932b55caab83e6d8cba9cesameb        RecordingBinder binder = this;
3127445e44ba8acbbfc09116fec71d59066cdae8721sameb        boolean unwrapModuleSource = false;
313605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        // Update the module source for the new module
3140910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber        if (module instanceof ProviderMethodsModule) {
3157445e44ba8acbbfc09116fec71d59066cdae8721sameb          // There are two reason's we'd want to get the module source in a ProviderMethodsModule.
3167445e44ba8acbbfc09116fec71d59066cdae8721sameb          // ModuleAnnotatedMethodScanner lets users scan their own modules for @Provides-like
3177445e44ba8acbbfc09116fec71d59066cdae8721sameb          // bindings.  If they install the module at a top-level, then moduleSource can be null.
3187445e44ba8acbbfc09116fec71d59066cdae8721sameb          // Also, if they pass something other than 'this' to it, we'd have the wrong source.
3190910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          Object delegate = ((ProviderMethodsModule) module).getDelegateModule();
3200910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          if (moduleSource == null
3210910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber              || !moduleSource.getModuleClassName().equals(delegate.getClass().getName())) {
3227445e44ba8acbbfc09116fec71d59066cdae8721sameb            moduleSource = getModuleSource(delegate);
3237445e44ba8acbbfc09116fec71d59066cdae8721sameb            unwrapModuleSource = true;
3247445e44ba8acbbfc09116fec71d59066cdae8721sameb          }
3250910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber        } else {
3260910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          moduleSource = getModuleSource(module);
3270910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          unwrapModuleSource = true;
328605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        }
32902c489e4fbddf702c7932b55caab83e6d8cba9cesameb        boolean skipScanning = false;
330fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        if (module instanceof PrivateModule) {
33102c489e4fbddf702c7932b55caab83e6d8cba9cesameb          binder = (RecordingBinder) binder.newPrivateBinder();
33202c489e4fbddf702c7932b55caab83e6d8cba9cesameb          // Store the module in the private binder too so we scan for it.
33302c489e4fbddf702c7932b55caab83e6d8cba9cesameb          binder.modules.put(module, new ModuleInfo(binder, moduleSource, false));
33402c489e4fbddf702c7932b55caab83e6d8cba9cesameb          skipScanning = true; // don't scan this module in the parent's module set.
3357445e44ba8acbbfc09116fec71d59066cdae8721sameb        }
33654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        // Always store this in the parent binder (even if it was a private module)
33754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb        // so that we know not to process it again, and so that scanners inherit down.
33802c489e4fbddf702c7932b55caab83e6d8cba9cesameb        modules.put(module, new ModuleInfo(binder, moduleSource, skipScanning));
339477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        try {
340fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit          module.configure(binder);
341477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        } catch (RuntimeException e) {
34272d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          Collection<Message> messages = Errors.getMessagesFromThrowable(e);
34372d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          if (!messages.isEmpty()) {
34472d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            elements.addAll(messages);
34572d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          } else {
34672d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit            addError(e);
34772d11dd102eeebf081aa5363469d28b25f9b1384limpbizkit          }
348477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        }
349fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit        binder.install(ProviderMethodsModule.forModule(module));
350605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        // We are done with this module, so undo module source change
3517445e44ba8acbbfc09116fec71d59066cdae8721sameb        if (unwrapModuleSource) {
352605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          moduleSource = moduleSource.getParent();
353605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        }
354477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
355477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
356477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
357477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public Stage currentStage() {
358477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return stage;
359477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
360477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
361477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(String message, Object... arguments) {
362605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new Message(getElementSource(), Errors.format(message, arguments)));
363477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
364477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
365477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Throwable t) {
366b3a8f0bda3259af41e639f1872c42377989704d9limpbizkit      String message = "An exception was caught and reported. Message: " + t.getMessage();
367605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new Message(ImmutableList.of((Object) getElementSource()), message, t));
368477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
369477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
370477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void addError(Message message) {
371477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      elements.add(message);
372477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
373477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
374d1fe130a70a1b881d7b27079954b0e9140ab324climpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Key<T> key) {
375825f8c1df885b9d7643a9e18e336984f0138edafsameb      BindingBuilder<T> builder =
376825f8c1df885b9d7643a9e18e336984f0138edafsameb          new BindingBuilder<T>(this, elements, getElementSource(), MoreTypes.canonicalizeKey(key));
37796e81ba55441fd11c189d903ee2bd1806a23bd70Christian Edward Gruber      return builder;
378477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
379477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
380477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(TypeLiteral<T> typeLiteral) {
381477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(typeLiteral));
382477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
383477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
384477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> AnnotatedBindingBuilder<T> bind(Class<T> type) {
385477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return bind(Key.get(type));
386477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
387477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
388477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public AnnotatedConstantBindingBuilder bindConstant() {
389605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return new ConstantBindingBuilderImpl<Void>(this, elements, getElementSource());
390477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
391477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
392477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(final Key<T> key) {
3939867f9c2142355ae958f9eeb8fb96811082c8812sameb      return getProvider(Dependency.get(key));
3949867f9c2142355ae958f9eeb8fb96811082c8812sameb    }
3959867f9c2142355ae958f9eeb8fb96811082c8812sameb
3969867f9c2142355ae958f9eeb8fb96811082c8812sameb    public <T> Provider<T> getProvider(final Dependency<T> dependency) {
3979867f9c2142355ae958f9eeb8fb96811082c8812sameb      final ProviderLookup<T> element = new ProviderLookup<T>(getElementSource(), dependency);
39897eac0fa7c42c3ebc409e63156899d3c889cb234limpbizkit      elements.add(element);
3998d62075e136d207b8fb8ea98d3fd7ec051bdee3climpbizkit      return element.getProvider();
400477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
401477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
402477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public <T> Provider<T> getProvider(Class<T> type) {
403477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return getProvider(Key.get(type));
404477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
405477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
406477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    public void convertToTypes(Matcher<? super TypeLiteral<?>> typeMatcher,
407477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        TypeConverter converter) {
408605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new TypeConverterBinding(getElementSource(), typeMatcher, converter));
409477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
410477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
411ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber    public RecordingBinder withSource(final Object source) {
412c5848c0b57ad0f3f09acadff4be80c19d0c7d95fSam Berlin      return source == this.source ? this : new RecordingBinder(this, source, null);
413477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
414477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
4155ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public RecordingBinder skipSources(Class... classesToSkip) {
416477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      // if a source is specified explicitly, we don't need to skip sources
417477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      if (source != null) {
418477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit        return this;
419477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      }
420477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
421477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      SourceProvider newSourceProvider = sourceProvider.plusSkippedClasses(classesToSkip);
422477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return new RecordingBinder(this, null, newSourceProvider);
423477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
424477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit
4250910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
4265ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public PrivateBinder newPrivateBinder() {
427605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      PrivateElementsImpl privateElements = new PrivateElementsImpl(getElementSource());
42896e81ba55441fd11c189d903ee2bd1806a23bd70Christian Edward Gruber      RecordingBinder binder = new RecordingBinder(this, privateElements);
42954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      privateBinders.add(binder);
430c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      elements.add(privateElements);
43196e81ba55441fd11c189d903ee2bd1806a23bd70Christian Edward Gruber      return binder;
4325ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
4330910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber
4340910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
4358b64d455b982d5841480a0247c15d68de0759c91sberlin    public void disableCircularProxies() {
436605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new DisableCircularProxiesOption(getElementSource()));
4378b64d455b982d5841480a0247c15d68de0759c91sberlin    }
4380910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber
4390910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
4408b64d455b982d5841480a0247c15d68de0759c91sberlin    public void requireExplicitBindings() {
4410910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber      elements.add(new RequireExplicitBindingsOption(getElementSource()));
4428b64d455b982d5841480a0247c15d68de0759c91sberlin    }
4430910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber
4440910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
445c756777526309dc6c9ff2b5df80a8f811d390c09Sam Berlin    public void requireAtInjectOnConstructors() {
446605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new RequireAtInjectOnConstructorsOption(getElementSource()));
447c756777526309dc6c9ff2b5df80a8f811d390c09Sam Berlin    }
4485ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
4490910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
450e39158525475eca7971966c667494d240be7e242Christian Edward Gruber    public void requireExactBindingAnnotations() {
451605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      elements.add(new RequireExactBindingAnnotationsOption(getElementSource()));
452e39158525475eca7971966c667494d240be7e242Christian Edward Gruber    }
453e39158525475eca7971966c667494d240be7e242Christian Edward Gruber
4540910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
45554da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    public void scanModulesForAnnotatedMethods(ModuleAnnotatedMethodScanner scanner) {
45654da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      scanners.add(scanner);
45754da0e3ca924a5040e88a1c067f9f6760a14b20bsameb      elements.add(new ModuleAnnotatedMethodScannerBinding(getElementSource(), scanner));
45854da0e3ca924a5040e88a1c067f9f6760a14b20bsameb    }
45954da0e3ca924a5040e88a1c067f9f6760a14b20bsameb
4604994bf6a8e9986ca9013a908c340f019084be30flimpbizkit    public void expose(Key<?> key) {
4614994bf6a8e9986ca9013a908c340f019084be30flimpbizkit      exposeInternal(key);
4625ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
4635ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
4640910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
4655ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(Class<?> type) {
4665ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
4675ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
4685ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
4690910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    @Override
4705ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    public AnnotatedElementBuilder expose(TypeLiteral<?> type) {
4715ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      return exposeInternal(Key.get(type));
4725ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
4735ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
474fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit    private <T> AnnotatedElementBuilder exposeInternal(Key<T> key) {
475c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      if (privateElements == null) {
476b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        addError("Cannot expose %s on a standard binder. "
477b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit            + "Exposed bindings are only applicable to private binders.", key);
478b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        return new AnnotatedElementBuilder() {
4790910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          @Override
480b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit          public void annotatedWith(Class<? extends Annotation> annotationType) {}
4810910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          @Override
482b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit          public void annotatedWith(Annotation annotation) {}
483b1f42f5df9c4cd8e157a28c24c4e8eb627a7f052limpbizkit        };
4845ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit      }
4855ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
486825f8c1df885b9d7643a9e18e336984f0138edafsameb      ExposureBuilder<T> builder =
487825f8c1df885b9d7643a9e18e336984f0138edafsameb          new ExposureBuilder<T>(this, getElementSource(), MoreTypes.canonicalizeKey(key));
488c3f928404a91cf837d809dcc465ba43442bc1198limpbizkit      privateElements.addExposureBuilder(builder);
489fcbdf999a15039ecad6157c1bf44a835df826a27limpbizkit      return builder;
4905ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit    }
4915ea4ab2bca518a3ac24dc5c0713326e8699d3fadlimpbizkit
4920910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber    private ModuleSource getModuleSource(Object module) {
493605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      StackTraceElement[] partialCallStack;
494ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      if (getIncludeStackTraceOption() == IncludeStackTraceOption.COMPLETE) {
495605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        partialCallStack = getPartialCallStack(new Throwable().getStackTrace());
496ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      } else {
497ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        partialCallStack = new StackTraceElement[0];
498605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
499605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      if (moduleSource == null) {
500605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        return new ModuleSource(module, partialCallStack);
501605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
502605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return moduleSource.createChild(module, partialCallStack);
503605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
504605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
505605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private ElementSource getElementSource() {
506605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      // Full call stack
507ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      StackTraceElement[] callStack = null;
508605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      // The call stack starts from current top module configure and ends at this method caller
509ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      StackTraceElement[] partialCallStack = new StackTraceElement[0];
510ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      // The element original source
511ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      ElementSource originalSource = null;
512ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      // The element declaring source
513ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      Object declaringSource = source;
514ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      if (declaringSource instanceof ElementSource) {
515ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        originalSource = (ElementSource) declaringSource;
516ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        declaringSource = originalSource.getDeclaringSource();
517ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      }
518ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      IncludeStackTraceOption stackTraceOption = getIncludeStackTraceOption();
519ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      if (stackTraceOption == IncludeStackTraceOption.COMPLETE ||
5200910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber          (stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE
521ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber          && declaringSource == null)) {
522605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        callStack = new Throwable().getStackTrace();
523ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      }
524ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber      if (stackTraceOption == IncludeStackTraceOption.COMPLETE) {
525605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        partialCallStack = getPartialCallStack(callStack);
526605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
527605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      if (declaringSource == null) {
528ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        // So 'source' and 'originalSource' are null otherwise declaringSource has some value
529ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        if (stackTraceOption == IncludeStackTraceOption.COMPLETE ||
530ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber            stackTraceOption == IncludeStackTraceOption.ONLY_FOR_DECLARING_SOURCE) {
531ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber          // With the above conditions and assignments 'callStack' is non-null
532ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber          declaringSource = sourceProvider.get(callStack);
533ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber        } else { // or if (stackTraceOption == IncludeStackTraceOptions.OFF)
534ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber          // As neither 'declaring source' nor 'call stack' is available use 'module source'
535ba5acdf7cf1eef418cfdb463991ff76e7f3ded28Christian Edward Gruber          declaringSource = sourceProvider.getFromClassNames(moduleSource.getModuleClassNames());
536605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        }
537605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
538605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      // Build the binding call stack
539605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return new ElementSource(
540605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber          originalSource, declaringSource, moduleSource, partialCallStack);
541605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    }
542605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
543605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    /**
5440910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber     * Removes the {@link #moduleSource} call stack from the beginning of current call stack. It
5450910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber     * also removes the last two elements in order to make {@link #install(Module)} the last call
5460910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber     * in the call stack.
547605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber     */
548605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber    private StackTraceElement[] getPartialCallStack(StackTraceElement[] callStack) {
549605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      int toSkip = 0;
550605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      if (moduleSource != null) {
551605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber        toSkip = moduleSource.getStackTraceSize();
552605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      }
553605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      // -1 for skipping 'getModuleSource' and 'getElementSource' calls
554605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      int chunkSize = callStack.length - toSkip - 1;
555605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber
556605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      StackTraceElement[] partialCallStack = new StackTraceElement[chunkSize];
557605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      System.arraycopy(callStack, 1, partialCallStack, 0, chunkSize);
558605bd086d3ecc4290ddfa4cf89fd840d22d1894cChristian Edward Gruber      return partialCallStack;
559477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
5600910c1e69ee2b0587f898cb292d4e9f8d9338e28cgruber
561477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    @Override public String toString() {
562477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit      return "Binder";
563477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit    }
564477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit  }
565477f9f9ce3e1077866b579e99cd33ab824f1ee69limpbizkit}
566