Home | History | Annotate | Download | only in internal
      1 /**
      2  * Copyright (C) 2011 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 
     17 package com.google.inject.internal;
     18 
     19 import com.google.common.collect.ImmutableSet;
     20 import com.google.inject.AbstractModule;
     21 import com.google.inject.Binder;
     22 import com.google.inject.Binding;
     23 import com.google.inject.Injector;
     24 import com.google.inject.Key;
     25 import com.google.inject.MembersInjector;
     26 import com.google.inject.Module;
     27 import com.google.inject.Provider;
     28 import com.google.inject.Scope;
     29 import com.google.inject.Stage;
     30 import com.google.inject.TypeLiteral;
     31 import com.google.inject.spi.DefaultBindingTargetVisitor;
     32 
     33 import java.util.Set;
     34 
     35 /**
     36  * Guarantees that processing of Binding elements happens in a sane way.
     37  *
     38  * @author sameb (at) google.com (Sam Berlin)
     39  */
     40 abstract class AbstractBindingProcessor extends AbstractProcessor {
     41 
     42   // It's unfortunate that we have to maintain a blacklist of specific
     43   // classes, but we can't easily block the whole package because of
     44   // all our unit tests.
     45   private static final Set<Class<?>> FORBIDDEN_TYPES = ImmutableSet.<Class<?>>of(
     46       AbstractModule.class,
     47       Binder.class,
     48       Binding.class,
     49       Injector.class,
     50       Key.class,
     51       MembersInjector.class,
     52       Module.class,
     53       Provider.class,
     54       Scope.class,
     55       Stage.class,
     56       TypeLiteral.class);
     57 
     58   protected final ProcessedBindingData bindingData;
     59 
     60   AbstractBindingProcessor(Errors errors, ProcessedBindingData bindingData) {
     61     super(errors);
     62     this.bindingData = bindingData;
     63   }
     64 
     65   protected <T> UntargettedBindingImpl<T> invalidBinding(
     66       InjectorImpl injector, Key<T> key, Object source) {
     67     return new UntargettedBindingImpl<T>(injector, key, source);
     68   }
     69 
     70   protected void putBinding(BindingImpl<?> binding) {
     71     Key<?> key = binding.getKey();
     72 
     73     Class<?> rawType = key.getTypeLiteral().getRawType();
     74     if (FORBIDDEN_TYPES.contains(rawType)) {
     75       errors.cannotBindToGuiceType(rawType.getSimpleName());
     76       return;
     77     }
     78 
     79     BindingImpl<?> original = injector.getExistingBinding(key);
     80     if (original != null) {
     81       // If it failed because of an explicit duplicate binding...
     82       if (injector.state.getExplicitBinding(key) != null) {
     83         try {
     84           if(!isOkayDuplicate(original, binding, injector.state)) {
     85             errors.bindingAlreadySet(key, original.getSource());
     86             return;
     87           }
     88         } catch(Throwable t) {
     89           errors.errorCheckingDuplicateBinding(key, original.getSource(), t);
     90           return;
     91         }
     92       } else {
     93         // Otherwise, it failed because of a duplicate JIT binding
     94         // in the parent
     95         errors.jitBindingAlreadySet(key);
     96         return;
     97       }
     98     }
     99 
    100     // prevent the parent from creating a JIT binding for this key
    101     injector.state.parent().blacklist(key, injector.state, binding.getSource());
    102     injector.state.putBinding(key, binding);
    103   }
    104 
    105   /**
    106    * We tolerate duplicate bindings if one exposes the other or if the two bindings
    107    * are considered duplicates (see {@link Bindings#areDuplicates(BindingImpl, BindingImpl)}.
    108    *
    109    * @param original the binding in the parent injector (candidate for an exposing binding)
    110    * @param binding the binding to check (candidate for the exposed binding)
    111    */
    112   private boolean isOkayDuplicate(BindingImpl<?> original, BindingImpl<?> binding, State state) {
    113     if (original instanceof ExposedBindingImpl) {
    114       ExposedBindingImpl exposed = (ExposedBindingImpl) original;
    115       InjectorImpl exposedFrom = (InjectorImpl) exposed.getPrivateElements().getInjector();
    116       return (exposedFrom == binding.getInjector());
    117     } else {
    118       original = (BindingImpl<?>)state.getExplicitBindingsThisLevel().get(binding.getKey());
    119       // If no original at this level, the original was on a parent, and we don't
    120       // allow deduplication between parents & children.
    121       if(original == null) {
    122         return false;
    123       } else {
    124         return original.equals(binding);
    125       }
    126     }
    127   }
    128 
    129   private <T> void validateKey(Object source, Key<T> key) {
    130     Annotations.checkForMisplacedScopeAnnotations(
    131         key.getTypeLiteral().getRawType(), source, errors);
    132   }
    133 
    134   /**
    135    * Processor for visiting bindings.  Each overriden method that wants to
    136    * actually process the binding should call prepareBinding first.
    137    */
    138   abstract class Processor<T, V> extends DefaultBindingTargetVisitor<T, V> {
    139     final Object source;
    140     final Key<T> key;
    141     final Class<? super T> rawType;
    142     Scoping scoping;
    143 
    144     Processor(BindingImpl<T> binding) {
    145       source = binding.getSource();
    146       key = binding.getKey();
    147       rawType = key.getTypeLiteral().getRawType();
    148       scoping = binding.getScoping();
    149     }
    150 
    151     protected void prepareBinding() {
    152       validateKey(source, key);
    153       scoping = Scoping.makeInjectable(scoping, injector, errors);
    154     }
    155 
    156     protected void scheduleInitialization(final BindingImpl<?> binding) {
    157       bindingData.addUninitializedBinding(new Runnable() {
    158         public void run() {
    159           try {
    160             binding.getInjector().initializeBinding(binding, errors.withSource(source));
    161           } catch (ErrorsException e) {
    162             errors.merge(e.getErrors());
    163           }
    164         }
    165       });
    166     }
    167   }
    168 }
    169