Home | History | Annotate | Download | only in internal
      1 /**
      2  * Copyright (C) 2006 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 static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.inject.Key;
     22 import com.google.inject.internal.InjectorImpl.JitLimitation;
     23 import com.google.inject.spi.Dependency;
     24 
     25 import javax.inject.Provider;
     26 
     27 /**
     28  * Delegates to a custom factory which is also bound in the injector.
     29  */
     30 final class BoundProviderFactory<T> extends ProviderInternalFactory<T> implements CreationListener {
     31 
     32   private final ProvisionListenerStackCallback<T> provisionCallback;
     33   private final InjectorImpl injector;
     34   final Key<? extends javax.inject.Provider<? extends T>> providerKey;
     35   private InternalFactory<? extends javax.inject.Provider<? extends T>> providerFactory;
     36 
     37   BoundProviderFactory(
     38       InjectorImpl injector,
     39       Key<? extends javax.inject.Provider<? extends T>> providerKey,
     40       Object source,
     41       ProvisionListenerStackCallback<T> provisionCallback) {
     42     super(source);
     43     this.provisionCallback = checkNotNull(provisionCallback, "provisionCallback");
     44     this.injector = injector;
     45     this.providerKey = providerKey;
     46   }
     47 
     48   public void notify(Errors errors) {
     49     try {
     50       providerFactory = injector.getInternalFactory(providerKey, errors.withSource(source), JitLimitation.NEW_OR_EXISTING_JIT);
     51     } catch (ErrorsException e) {
     52       errors.merge(e.getErrors());
     53     }
     54   }
     55 
     56   public T get(Errors errors, InternalContext context, Dependency<?> dependency, boolean linked)
     57       throws ErrorsException {
     58     context.pushState(providerKey, source);
     59     try {
     60       errors = errors.withSource(providerKey);
     61       javax.inject.Provider<? extends T> provider = providerFactory.get(errors, context, dependency, true);
     62       return circularGet(provider, errors, context, dependency, provisionCallback);
     63     } finally {
     64       context.popState();
     65     }
     66   }
     67 
     68   @Override
     69   protected T provision(Provider<? extends T> provider, Errors errors, Dependency<?> dependency,
     70       ConstructionContext<T> constructionContext) throws ErrorsException {
     71     try {
     72       return super.provision(provider, errors, dependency, constructionContext);
     73     } catch(RuntimeException userException) {
     74       throw errors.errorInProvider(userException).toException();
     75     }
     76   }
     77 
     78   @Override public String toString() {
     79     return providerKey.toString();
     80   }
     81 }
     82