14e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/**
24e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Copyright (C) 2011 Google Inc.
34e11457f34addf5d10fe0c31cefd54c75c37b540sberlin *
44e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Licensed under the Apache License, Version 2.0 (the "License");
54e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * you may not use this file except in compliance with the License.
64e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * You may obtain a copy of the License at
74e11457f34addf5d10fe0c31cefd54c75c37b540sberlin *
84e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * http://www.apache.org/licenses/LICENSE-2.0
94e11457f34addf5d10fe0c31cefd54c75c37b540sberlin *
104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Unless required by applicable law or agreed to in writing, software
114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * distributed under the License is distributed on an "AS IS" BASIS,
124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * See the License for the specific language governing permissions and
144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * limitations under the License.
154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */
164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
174e11457f34addf5d10fe0c31cefd54c75c37b540sberlinpackage com.google.inject.internal;
184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
19b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport com.google.common.collect.ImmutableSet;
204e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.AbstractModule;
214e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Binder;
224e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Binding;
234e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Injector;
244e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Key;
254e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.MembersInjector;
264e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Module;
274e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Provider;
284e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.Scope;
29bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruberimport com.google.inject.Stage;
304e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.TypeLiteral;
314e11457f34addf5d10fe0c31cefd54c75c37b540sberlinimport com.google.inject.spi.DefaultBindingTargetVisitor;
324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
33b7a02b02d81c830d148355c90bc309bcd66fb592sberlinimport java.util.Set;
34b7a02b02d81c830d148355c90bc309bcd66fb592sberlin
354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin/**
364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * Guarantees that processing of Binding elements happens in a sane way.
37ec76179f50f9d8c340b311c6b019c00526566b66sberlin *
384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin * @author sameb@google.com (Sam Berlin)
394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin */
404e11457f34addf5d10fe0c31cefd54c75c37b540sberlinabstract class AbstractBindingProcessor extends AbstractProcessor {
414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  // It's unfortunate that we have to maintain a blacklist of specific
434e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  // classes, but we can't easily block the whole package because of
444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  // all our unit tests.
454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  private static final Set<Class<?>> FORBIDDEN_TYPES = ImmutableSet.<Class<?>>of(
464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      AbstractModule.class,
474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Binder.class,
484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Binding.class,
494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Injector.class,
504e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Key.class,
514e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      MembersInjector.class,
524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Module.class,
534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Provider.class,
544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      Scope.class,
55bf2b16c06a5ff7c099fe60f9a46cfb130ce45962Christian Edward Gruber      Stage.class,
564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      TypeLiteral.class);
57ec76179f50f9d8c340b311c6b019c00526566b66sberlin
584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  protected final ProcessedBindingData bindingData;
59ec76179f50f9d8c340b311c6b019c00526566b66sberlin
604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) {
614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    super(errors);
624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    this.bindingData = bindingData;
634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  protected <T> UntargettedBindingImpl<T> invalidBinding(
664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      InjectorImpl injector, Key<T> key, Object source) {
674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    return new UntargettedBindingImpl<T>(injector, key, source);
684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
69ec76179f50f9d8c340b311c6b019c00526566b66sberlin
704e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  protected void putBinding(BindingImpl<?> binding) {
714e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    Key<?> key = binding.getKey();
724e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
734e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    Class<?> rawType = key.getTypeLiteral().getRawType();
744e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    if (FORBIDDEN_TYPES.contains(rawType)) {
754e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      errors.cannotBindToGuiceType(rawType.getSimpleName());
764e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      return;
774e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
784e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
794e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    BindingImpl<?> original = injector.getExistingBinding(key);
804e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    if (original != null) {
814e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      // If it failed because of an explicit duplicate binding...
824e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      if (injector.state.getExplicitBinding(key) != null) {
834e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        try {
844e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          if(!isOkayDuplicate(original, binding, injector.state)) {
854e11457f34addf5d10fe0c31cefd54c75c37b540sberlin            errors.bindingAlreadySet(key, original.getSource());
864e11457f34addf5d10fe0c31cefd54c75c37b540sberlin            return;
874e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          }
884e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        } catch(Throwable t) {
894e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          errors.errorCheckingDuplicateBinding(key, original.getSource(), t);
904e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          return;
914e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        }
924e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      } else {
934e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        // Otherwise, it failed because of a duplicate JIT binding
944e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        // in the parent
954e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        errors.jitBindingAlreadySet(key);
964e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        return;
974e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      }
984e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
994e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
1004e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    // prevent the parent from creating a JIT binding for this key
101d57f8ece5508afc66c4768396c54b412dc9f2cc2Sam Berlin    injector.state.parent().blacklist(key, injector.state, binding.getSource());
1024e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    injector.state.putBinding(key, binding);
1034e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
1044e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
1054e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  /**
1064e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * We tolerate duplicate bindings if one exposes the other or if the two bindings
1074e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}.
1084e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   *
1094e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * @param original the binding in the parent injector (candidate for an exposing binding)
1104e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * @param binding the binding to check (candidate for the exposed binding)
1114e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   */
1124e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  private boolean isOkayDuplicate(BindingImpl<?> original, BindingImpl<?> binding, State state) {
1134e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    if (original instanceof ExposedBindingImpl) {
1144e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      ExposedBindingImpl exposed = (ExposedBindingImpl) original;
1154e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector();
1164e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      return (exposedFrom == binding.getInjector());
1174e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    } else {
1184e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      original = (BindingImpl<?>)state.getExplicitBindingsThisLevel().get(binding.getKey());
1194e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      // If no original at this level, the original was on a parent, and we don't
1204e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      // allow deduplication between parents & children.
1214e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      if(original == null) {
1224e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        return false;
1234e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      } else {
1244e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        return original.equals(binding);
1254e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      }
1264e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
1274e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
128ec76179f50f9d8c340b311c6b019c00526566b66sberlin
1294e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  private <T> void validateKey(Object source, Key<T> key) {
1304e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    Annotations.checkForMisplacedScopeAnnotations(
1314e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        key.getTypeLiteral().getRawType(), source, errors);
1324e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
133ec76179f50f9d8c340b311c6b019c00526566b66sberlin
134ec76179f50f9d8c340b311c6b019c00526566b66sberlin  /**
1354e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * Processor for visiting bindings.  Each overriden method that wants to
1364e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   * actually process the binding should call prepareBinding first.
1374e11457f34addf5d10fe0c31cefd54c75c37b540sberlin   */
1384e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  abstract class Processor<T, V> extends DefaultBindingTargetVisitor<T, V> {
1394e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    final Object source;
1404e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    final Key<T> key;
1414e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    final Class<? super T> rawType;
1424e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    Scoping scoping;
143ec76179f50f9d8c340b311c6b019c00526566b66sberlin
1444e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    Processor(BindingImpl<T> binding) {
1454e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      source = binding.getSource();
1464e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      key = binding.getKey();
1474e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      rawType = key.getTypeLiteral().getRawType();
1484e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      scoping = binding.getScoping();
1494e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
150ec76179f50f9d8c340b311c6b019c00526566b66sberlin
151ec76179f50f9d8c340b311c6b019c00526566b66sberlin    protected void prepareBinding() {
1524e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      validateKey(source, key);
1534e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      scoping = Scoping.makeInjectable(scoping, injector, errors);
1544e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
1554e11457f34addf5d10fe0c31cefd54c75c37b540sberlin
1564e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    protected void scheduleInitialization(final BindingImpl<?> binding) {
1574e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      bindingData.addUninitializedBinding(new Runnable() {
1584e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        public void run() {
1594e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          try {
1604e11457f34addf5d10fe0c31cefd54c75c37b540sberlin            binding.getInjector().initializeBinding(binding, errors.withSource(source));
1614e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          } catch (ErrorsException e) {
1624e11457f34addf5d10fe0c31cefd54c75c37b540sberlin            errors.merge(e.getErrors());
1634e11457f34addf5d10fe0c31cefd54c75c37b540sberlin          }
1644e11457f34addf5d10fe0c31cefd54c75c37b540sberlin        }
1654e11457f34addf5d10fe0c31cefd54c75c37b540sberlin      });
1664e11457f34addf5d10fe0c31cefd54c75c37b540sberlin    }
1674e11457f34addf5d10fe0c31cefd54c75c37b540sberlin  }
1684e11457f34addf5d10fe0c31cefd54c75c37b540sberlin}
169