Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2007 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.util;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import com.google.common.base.Objects;
     22 import com.google.common.collect.ImmutableSet;
     23 import com.google.common.collect.Sets;
     24 import com.google.inject.Inject;
     25 import com.google.inject.Injector;
     26 import com.google.inject.Provider;
     27 import com.google.inject.spi.Dependency;
     28 import com.google.inject.spi.InjectionPoint;
     29 import com.google.inject.spi.ProviderWithDependencies;
     30 
     31 import java.util.Set;
     32 
     33 /**
     34  * Static utility methods for creating and working with instances of
     35  * {@link Provider}.
     36  *
     37  * @author Kevin Bourrillion (kevinb9n (at) gmail.com)
     38  * @since 2.0
     39  */
     40 public final class Providers {
     41 
     42   private Providers() {}
     43 
     44   /**
     45    * Returns a provider which always provides {@code instance}.  This should not
     46    * be necessary to use in your application, but is helpful for several types
     47    * of unit tests.
     48    *
     49    * @param instance the instance that should always be provided.  This is also
     50    *     permitted to be null, to enable aggressive testing, although in real
     51    *     life a Guice-supplied Provider will never return null.
     52    */
     53   public static <T> Provider<T> of(final T instance) {
     54     return new ConstantProvider<T>(instance);
     55   }
     56 
     57   private static final class ConstantProvider<T> implements Provider<T> {
     58     private final T instance;
     59 
     60     private ConstantProvider(T instance) {
     61       this.instance = instance;
     62     }
     63 
     64     public T get() {
     65       return instance;
     66     }
     67 
     68     @Override public String toString() {
     69       return "of(" + instance + ")";
     70     }
     71 
     72     @Override public boolean equals(Object obj) {
     73       return (obj instanceof ConstantProvider)
     74           && Objects.equal(instance, ((ConstantProvider<?>) obj).instance);
     75     }
     76 
     77     @Override public int hashCode() {
     78       return Objects.hashCode(instance);
     79     }
     80   }
     81 
     82   /**
     83    * Returns a Guice-friendly {@code com.google.inject.Provider} for the given
     84    * JSR-330 {@code javax.inject.Provider}. The converse method is unnecessary,
     85    * since Guice providers directly implement the JSR-330 interface.
     86    *
     87    * @since 3.0
     88    */
     89   public static <T> Provider<T> guicify(javax.inject.Provider<T> provider) {
     90     if (provider instanceof Provider) {
     91       return (Provider<T>) provider;
     92     }
     93 
     94     final javax.inject.Provider<T> delegate = checkNotNull(provider, "provider");
     95 
     96     // Ensure that we inject all injection points from the delegate provider.
     97     Set<InjectionPoint> injectionPoints =
     98         InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
     99     if(injectionPoints.isEmpty()) {
    100       return new GuicifiedProvider<T>(delegate);
    101     } else {
    102       Set<Dependency<?>> mutableDeps = Sets.newHashSet();
    103       for(InjectionPoint ip : injectionPoints) {
    104         mutableDeps.addAll(ip.getDependencies());
    105       }
    106       final Set<Dependency<?>> dependencies = ImmutableSet.copyOf(mutableDeps);
    107       return new GuicifiedProviderWithDependencies<T>(dependencies, delegate);
    108     }
    109   }
    110 
    111   private static class GuicifiedProvider<T> implements Provider<T> {
    112     protected final javax.inject.Provider<T> delegate;
    113 
    114     private GuicifiedProvider(javax.inject.Provider<T> delegate) {
    115       this.delegate = delegate;
    116     }
    117 
    118     public T get() {
    119       return delegate.get();
    120     }
    121 
    122     @Override public String toString() {
    123       return "guicified(" + delegate + ")";
    124     }
    125 
    126     @Override public boolean equals(Object obj) {
    127       return (obj instanceof GuicifiedProvider)
    128           && Objects.equal(delegate, ((GuicifiedProvider<?>) obj).delegate);
    129     }
    130 
    131     @Override public int hashCode() {
    132       return Objects.hashCode(delegate);
    133     }
    134   }
    135 
    136   private static final class GuicifiedProviderWithDependencies<T>
    137       extends GuicifiedProvider<T> implements ProviderWithDependencies<T> {
    138     private final Set<Dependency<?>> dependencies;
    139 
    140     private GuicifiedProviderWithDependencies(Set<Dependency<?>> dependencies,
    141         javax.inject.Provider<T> delegate) {
    142       super(delegate);
    143       this.dependencies = dependencies;
    144     }
    145 
    146     @SuppressWarnings("unused")
    147     @Inject
    148     void initialize(Injector injector) {
    149       injector.injectMembers(delegate);
    150     }
    151 
    152     public Set<Dependency<?>> getDependencies() {
    153       return dependencies;
    154     }
    155   }
    156 }
    157