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@gmail.com)
38  * @since 2.0
39  */
40 public final class Providers {
41 
Providers()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    */
of(final T instance)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 
ConstantProvider(T instance)60     private ConstantProvider(T instance) {
61       this.instance = instance;
62     }
63 
get()64     public T get() {
65       return instance;
66     }
67 
toString()68     @Override public String toString() {
69       return "of(" + instance + ")";
70     }
71 
equals(Object obj)72     @Override public boolean equals(Object obj) {
73       return (obj instanceof ConstantProvider)
74           && Objects.equal(instance, ((ConstantProvider<?>) obj).instance);
75     }
76 
hashCode()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    */
guicify(javax.inject.Provider<T> provider)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 
GuicifiedProvider(javax.inject.Provider<T> delegate)114     private GuicifiedProvider(javax.inject.Provider<T> delegate) {
115       this.delegate = delegate;
116     }
117 
get()118     public T get() {
119       return delegate.get();
120     }
121 
toString()122     @Override public String toString() {
123       return "guicified(" + delegate + ")";
124     }
125 
equals(Object obj)126     @Override public boolean equals(Object obj) {
127       return (obj instanceof GuicifiedProvider)
128           && Objects.equal(delegate, ((GuicifiedProvider<?>) obj).delegate);
129     }
130 
hashCode()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 
GuicifiedProviderWithDependencies(Set<Dependency<?>> dependencies, javax.inject.Provider<T> delegate)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
initialize(Injector injector)148     void initialize(Injector injector) {
149       injector.injectMembers(delegate);
150     }
151 
getDependencies()152     public Set<Dependency<?>> getDependencies() {
153       return dependencies;
154     }
155   }
156 }
157